How to convert PascalCase to pascal_case?

前端 未结 30 1443
北海茫月
北海茫月 2020-11-29 16:36

If I had:

$string = \"PascalCase\";

I need

\"pascal_case\"

Does PHP offer a function for this purpose?

相关标签:
30条回答
  • 2020-11-29 17:19

    Try this on for size:

    $tests = array(
      'simpleTest' => 'simple_test',
      'easy' => 'easy',
      'HTML' => 'html',
      'simpleXML' => 'simple_xml',
      'PDFLoad' => 'pdf_load',
      'startMIDDLELast' => 'start_middle_last',
      'AString' => 'a_string',
      'Some4Numbers234' => 'some4_numbers234',
      'TEST123String' => 'test123_string',
    );
    
    foreach ($tests as $test => $result) {
      $output = from_camel_case($test);
      if ($output === $result) {
        echo "Pass: $test => $result\n";
      } else {
        echo "Fail: $test => $result [$output]\n";
      }
    }
    
    function from_camel_case($input) {
      preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
      $ret = $matches[0];
      foreach ($ret as &$match) {
        $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
      }
      return implode('_', $ret);
    }
    

    Output:

    Pass: simpleTest => simple_test
    Pass: easy => easy
    Pass: HTML => html
    Pass: simpleXML => simple_xml
    Pass: PDFLoad => pdf_load
    Pass: startMIDDLELast => start_middle_last
    Pass: AString => a_string
    Pass: Some4Numbers234 => some4_numbers234
    Pass: TEST123String => test123_string
    

    This implements the following rules:

    1. A sequence beginning with a lowercase letter must be followed by lowercase letters and digits;
    2. A sequence beginning with an uppercase letter can be followed by either:
      • one or more uppercase letters and digits (followed by either the end of the string or an uppercase letter followed by a lowercase letter or digit ie the start of the next sequence); or
      • one or more lowercase letters or digits.
    0 讨论(0)
  • 2020-11-29 17:19

    Laravel 5.6 provides a very simple way of doing this:

     /**
     * Convert a string to snake case.
     *
     * @param  string  $value
     * @param  string  $delimiter
     * @return string
     */
    public static function snake($value, $delimiter = '_'): string
    {
        if (!ctype_lower($value)) {
            $value = strtolower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value));
        }
    
        return $value;
    }
    

    What it does: if it sees that there is at least one capital letter in the given string, it uses a positive lookahead to search for any character (.) followed by a capital letter ((?=[A-Z])). It then replaces the found character with it's value followed by the separactor _.

    0 讨论(0)
  • 2020-11-29 17:19

    If you use Laravel framework, you can use just snake_case() method.

    0 讨论(0)
  • 2020-11-29 17:20

    A version that doesn't use regex can be found in the Alchitect source:

    decamelize($str, $glue='_')
    {
        $counter  = 0;
        $uc_chars = '';
        $new_str  = array();
        $str_len  = strlen($str);
    
        for ($x=0; $x<$str_len; ++$x)
        {
            $ascii_val = ord($str[$x]);
    
            if ($ascii_val >= 65 && $ascii_val <= 90)
            {
                $uc_chars .= $str[$x];
            }
        }
    
        $tok = strtok($str, $uc_chars);
    
        while ($tok !== false)
        {
            $new_char  = chr(ord($uc_chars[$counter]) + 32);
            $new_str[] = $new_char . $tok;
            $tok       = strtok($uc_chars);
    
            ++$counter;
        }
    
        return implode($new_str, $glue);
    }
    
    0 讨论(0)
  • 2020-11-29 17:21

    If you are looking for a PHP 5.4 version and later answer here is the code:

    function decamelize($word) {
          return $word = preg_replace_callback(
            "/(^|[a-z])([A-Z])/",
            function($m) { return strtolower(strlen($m[1]) ? "$m[1]_$m[2]" : "$m[2]"); },
            $word
        );
    
    }
    function camelize($word) {
        return $word = preg_replace_callback(
            "/(^|_)([a-z])/",
            function($m) { return strtoupper("$m[2]"); },
            $word
        );
    
    } 
    
    0 讨论(0)
  • 2020-11-29 17:22

    So here is a one-liner:

    strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));
    
    0 讨论(0)
提交回复
热议问题