Domanda

Se avessi:

$string = "PascalCase";

Ho bisogno

"pascal_case"

Il PHP offrono una funzione per questo scopo?

È stato utile?

Soluzione

Prova questo per il formato:

$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

Questa implementa le seguenti regole:

  1. Una sequenza inizia con una lettera minuscola deve essere seguita da lettere minuscole e cifre;
  2. Una sequenza che inizia con una lettera maiuscola può essere seguito da uno:
    • una o più lettere maiuscole e cifre (seguiti dalle estremità della stringa o una lettera maiuscola seguita da una lettera minuscola o cifre, cioè l'inizio della successiva sequenza); o
    • una o più lettere minuscole o cifre.

Altri suggerimenti

Una soluzione più corta: Simile al dell'editor uno con un'espressione regolare semplificato e risolvere il problema "trailing-underscore":

$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));

PHP Demo | Regex Demo


Si noti che casi come SimpleXML saranno convertiti simple_x_m_l utilizzando la soluzione di cui sopra. Che può anche essere considerato un uso sbagliato di caso cammello notazione (corretta sarebbe SimpleXml), piuttosto che un bug dell'algoritmo in quanto tali casi sono sempre ambigui - anche dal raggruppamento di caratteri maiuscoli a una stringa (simple_xml) tale algoritmo sarà sempre fallire in altri casi limite come XMLHTMLConverter o uno parolacce vicino abbreviazioni, ecc Se non si mente circa i casi (piuttosto rara) bordo e desidera gestire correttamente SimpleXML, è possibile utilizzare un po 'di soluzione più complessa:

$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');

PHP Demo | Regex Demo

Una soluzione concisa e in grado di gestire alcuni casi di utilizzo ingannevole:

function decamelize($string) {
    return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}

In grado di gestire tutti questi casi:

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
hello_world => hello_world
hello__world => hello__world
_hello_world_ => _hello_world_
hello_World => hello_world
HelloWorld => hello_world
helloWorldFoo => hello_world_foo
hello-world => hello-world
myHTMLFiLe => my_html_fi_le
aBaBaB => a_ba_ba_b
BaBaBa => ba_ba_ba
libC => lib_c

È possibile provare questa funzione qui: http://syframework.alwaysdata.net/decamelize

porting da String#camelize e String#decamelize di Ruby.

function decamelize($word) {
  return preg_replace(
    '/(^|[a-z])([A-Z])/e', 
    'strtolower(strlen("\\1") ? "\\1_\\2" : "\\2")',
    $word 
  ); 
}

function camelize($word) { 
  return preg_replace('/(^|_)([a-z])/e', 'strtoupper("\\2")', $word); 
}

Un trucco le soluzioni di cui sopra possono avere perso è il modificatore 'e' che provoca preg_replace di valutare la stringa di sostituzione come codice PHP.

Il Symfony Serializer Componente ha una CamelCaseToSnakeCaseNameConverter che ha due metodi normalize() e denormalize(). Questi possono essere utilizzati come segue:

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

echo $nameConverter->normalize('camelCase');
// outputs: camel_case

echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase

La maggior parte delle soluzioni qui si sentono mano pesante. Ecco quello che io uso:

$underscored = strtolower(
    preg_replace(
        ["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"], 
        ["_$1", "_$1_$2"], 
        lcfirst($camelCase)
    )
);

"CamelCase" viene convertito in "camel_case"

  • lcfirst($camelCase) abbasserà il primo carattere (evita 'camelCase' convertito uscita per iniziare con un trattino)
  • [A-Z] ritrova lettere maiuscole
  • + tratterà ogni maiuscolo consecutivo come una parola ( 'evita camelCase' da convertire in camel_C_A_S_E)
  • Secondo modello e la sostituzione sono per ThoseSPECCases -> those_spec_cases invece di those_speccases
  • strtolower([…]) trasforma l'uscita in minuscolo

php non offre una costruito in funzione di questo afaik, ma qui è quello che io uso

function uncamelize($camel,$splitter="_") {
    $camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '$0', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'$0', $camel));
    return strtolower($camel);

}

lo splitter può essere specificato nella chiamata di funzione, in modo da poter chiamare in questo modo

$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"
header('content-type: text/html; charset=utf-8');
$separated = preg_replace('%(?<!^)\p{Lu}%usD', '_$0', 'AaaaBbbbCcccDdddÁáááŐőőő');
$lower = mb_strtolower($separated, 'utf-8');
echo $lower; //aaaa_bbbb_cccc_dddd_áááá_őőőő

Se siete alla ricerca di una versione di PHP 5.4 e successive risposta qui è il codice:

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
    );

} 

Non lussuoso ma semplice e veloce come l'inferno:

function uncamelize($str) 
{
    $str = lcfirst($str);
    $lc = strtolower($str);
    $result = '';
    $length = strlen($str);
    for ($i = 0; $i < $length; $i++) {
        $result .= ($str[$i] == $lc[$i] ? '' : '_') . $lc[$i];
    }
    return $result;
}

echo uncamelize('HelloAWorld'); //hello_a_world

"CamelCase" a "camel_case":

function camelToSnake($camel)
{
    $snake = preg_replace('/[A-Z]/', '_$0', $camel);
    $snake = strtolower($snake);
    $snake = ltrim($snake, '_');
    return $snake;
}

o

function camelToSnake($camel)
{
    $snake = preg_replace_callback('/[A-Z]/', function ($match){
        return '_' . strtolower($match[0]);
    }, $camel);
    return ltrim($snake, '_');
}

Una versione che non utilizza regex può essere trovato nel href="http://alchitect.com" rel="nofollow noreferrer"> Alchitect fonte

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);
}

Quindi, ecco una battuta:

strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));

danielstjules / filante provieds un metodo per convertire la stringa da CamelCase a snake case.

s('TestUCase')->underscored(); // 'test_u_case'

laravel 5.6 fornisce un modo molto semplice di fare questo:

 /**
 * 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;
}

Cosa fa: se vede che ci sia almeno una lettera maiuscola nella stringa data, utilizza un positivo lookahead per la ricerca di qualsiasi carattere (.) seguito da una lettera maiuscola ((?=[A-Z])). Esso sostituisce quindi il carattere trovato con il suo valore seguito dal _ separactor.

Il porto diretta da rotaie (meno il loro trattamento speciale per :: o acronimi) sarebbe

function underscore($word){
    $word = preg_replace('#([A-Z\d]+)([A-Z][a-z])#','\1_\2', $word);
    $word = preg_replace('#([a-z\d])([A-Z])#', '\1_\2', $word);
    return strtolower(strtr($word, '-', '_'));
}

Conoscere PHP, questo sarà più veloce rispetto al parsing manuale che sta accadendo in altre risposte qui riportati. Lo svantaggio è che non si arriva a scegliere cosa usare come separatore tra le parole, ma che non faceva parte della questione.

Controllare anche la rilevante fonte rotaie codice

Si noti che questo è destinato all'uso con identificatori ASCII. Se avete bisogno di fare questo con i personaggi al di fuori del range ASCII, utilizzare il modificatore '/ u' per l'uso preg_matchand mb_strtolower.

Ecco il mio contributo a una domanda di sei anni con Dio sa quante risposte ...

Sarà convertire tutte le parole nella stringa a condizione che sono in CamelCase a snake case. Ad esempio, "SuperSpecialAwesome e anche FizBuzz καιΚάτιΑκόμα" saranno convertiti in "super_special_awesome e anche fizz_buzz και_κάτι_ακόμα".

mb_strtolower(
    preg_replace_callback(
        '/(?<!\b|_)\p{Lu}/u',
        function ($a) {
            return "_$a[0]";
        },
        'SuperSpecialAwesome'
    )
);

Yii2 hanno la diversa funzione di rendere la parola snake_case da CamelCase.

    /**
     * Converts any "CamelCased" into an "underscored_word".
     * @param string $words the word(s) to underscore
     * @return string
     */
    public static function underscore($words)
    {
        return strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $words));
    }
function camel2snake($name) {
    $str_arr = str_split($name);
    foreach ($str_arr as $k => &$v) {
        if (ord($v) >= 64 && ord($v) <= 90) { // A = 64; Z = 90
            $v = strtolower($v);
            $v = ($k != 0) ? '_'.$v : $v;
        }
    }
    return implode('', $str_arr);
}

C'è libreria un fornire questa funzionalità:

SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"

Se si utilizza quadro laravel, è possibile utilizzare solo snake_case () metodo.

$str = 'FooBarBaz';

return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $str)); // foo_bar_baz

Questo è uno dei modi più brevi:

function camel_to_snake($input)
{
    return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}

Come de-camelize senza l'utilizzo di espressioni regolari:

function decamelize($str, $glue = '_') {
    $capitals = [];
    $replace  = [];

    foreach(str_split($str) as $index => $char) {
        if(!ctype_upper($char)) {
            continue;
        }

        $capitals[] = $char;
        $replace[]  = ($index > 0 ? $glue : '') . strtolower($char);
    }

    if(count($capitals) > 0) {
        return str_replace($capitals, $replace, $str);
    }

    return $str;
}

Una modifica:

Come dovrei farlo nel 2019:

function toSnakeCase($str, $glue = '_') {
    return preg_replace_callback('/[A-Z]/', function ($matches) use ($glue) {
        return $glue . strtolower($matches[0]);
    }, $str);
}

E quando il PHP 7.4 sarà rilasciato:

function toSnakeCase($str, $glue = '_') {
    return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}

soluzione breve:

$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));

E 'facile utilizzando le classi di filtro della Zend Word filtri :

<?php
namespace MyNamespace\Utility;

use Zend\Filter\Word\CamelCaseToUnderscore;
use Zend\Filter\Word\UnderscoreToCamelCase;

class String
{
    public function test()
    {
        $underscoredStrings = array(
            'simple_test',
            'easy',
            'html',
            'simple_xml',
            'pdf_load',
            'start_middle_last',
            'a_string',
            'some4_numbers234',
            'test123_string',
        );
        $camelCasedStrings = array(
            'simpleTest',
            'easy',
            'HTML',
            'simpleXML',
            'PDFLoad',
            'startMIDDLELast',
            'AString',
            'Some4Numbers234',
            'TEST123String',
        );
        echo PHP_EOL . '-----' . 'underscoreToCamelCase' . '-----' . PHP_EOL;
        foreach ($underscoredStrings as $rawString) {
            $filteredString = $this->underscoreToCamelCase($rawString);
            echo PHP_EOL . $rawString . ' >>> ' . $filteredString . PHP_EOL;
        }
        echo PHP_EOL . '-----' . 'camelCaseToUnderscore' . '-----' . PHP_EOL;
        foreach ($camelCasedStrings as $rawString) {
            $filteredString = $this->camelCaseToUnderscore($rawString);
            echo PHP_EOL . $rawString . ' >>> ' . $filteredString . PHP_EOL;
        }
    }

    public function camelCaseToUnderscore($input)
    {
        $camelCaseToSeparatorFilter = new CamelCaseToUnderscore();
        $result = $camelCaseToSeparatorFilter->filter($input);
        $result = strtolower($result);
        return $result;
    }

    public function underscoreToCamelCase($input)
    {
        $underscoreToCamelCaseFilter = new UnderscoreToCamelCase();
        $result = $underscoreToCamelCaseFilter->filter($input);
        return $result;
    }
}
  

----- ----- underscoreToCamelCase

     

simple_test >>> SimpleTest

     

>>> facile facile

     

HTML >>> Html

     

simple_xml >>> SimpleXML

     

pdf_load >>> PdfLoad

     

start_middle_last >>> StartMiddleLast

     

a_string >>> astring

     

some4_numbers234 >>> Some4Numbers234

     

test123_string >>> Test123String

     

----- ----- camelCaseToUnderscore

     

simpletest >>> simple_test

     

>>> facile facile

     

HTML >>> html

     

SimpleXML >>> simple_xml

     

PDFLoad >>> pdf_load

     

startMIDDLELast >>> start_middle_last

     

astring >>> a_string

     

Some4Numbers234 >>> some4_numbers234

     

TEST123String >>> test123_string

La risposta peggiore qui è stato così vicino ad essere il migliore (utilizzare un framework). NO NON, basta dare un'occhiata al codice sorgente. vedendo ciò che un uso quadro ben consolidata sarebbe un approccio molto più affidabile (provati e testati). Il framework Zend ha alcuni filtri parola che si adattano alle vostre esigenze. Source.

ecco un paio di metodi mi sono adattato dalla fonte.

function CamelCaseToSeparator($value,$separator = ' ')
{
    if (!is_scalar($value) && !is_array($value)) {
        return $value;
    }
    if (defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1) {
        $pattern     = ['#(?<=(?:\p{Lu}))(\p{Lu}\p{Ll})#', '#(?<=(?:\p{Ll}|\p{Nd}))(\p{Lu})#'];
        $replacement = [$separator . '\1', $separator . '\1'];
    } else {
        $pattern     = ['#(?<=(?:[A-Z]))([A-Z]+)([A-Z][a-z])#', '#(?<=(?:[a-z0-9]))([A-Z])#'];
        $replacement = ['\1' . $separator . '\2', $separator . '\1'];
    }
    return preg_replace($pattern, $replacement, $value);
}
function CamelCaseToUnderscore($value){
    return CamelCaseToSeparator($value,'_');
}
function CamelCaseToDash($value){
    return CamelCaseToSeparator($value,'-');
}
$string = CamelCaseToUnderscore("CamelCase");

La biblioteca TurboCommons open source contiene un metodo generale scopo formatCase () all'interno della classe StringUtils, che permette di convertire una stringa in un sacco di formati più comuni casi, come CamelCase, UpperCamelCase, LowerCamelCase, snake_case, caso di titolo, e molti altri.

https://github.com/edertone/TurboCommons

Per utilizzarlo, importare il file phar al progetto e:

use org\turbocommons\src\main\php\utils\StringUtils;

echo StringUtils::formatCase('camelCase', StringUtils::FORMAT_SNAKE_CASE);

// will output 'camel_Case'

Ho avuto un problema simile, ma non ho trovato alcuna risposta che soddisfi come convertire CamelCase a snake_case, evitando duplicati o ridondanti sottolineature _ per i nomi con sottolineature, o tutti caps abbreviazioni.

Th problema è come segue:

CamelCaseClass            => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ                       => faq

La soluzione che ho scritto è un semplice due funzioni di chiamata, minuscole e di ricerca e sostituzione per le lettere minuscole-maiuscole consecutive:

strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $name));

Se si potrebbe iniziare con:

$string = 'Camel_Case'; // underscore or any other separator...

Poi si potrebbe convertire in entrambi i casi solo con:

$pascal = str_replace("_", "", $string);
$snake = strtolower($string);

O tutti gli altri casi:

$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string);               // CAMEL_CASE
$train = str_replace("_", "-", $snake);        // camel-case
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top