Question

Si je devais:

$string = "PascalCase";

Je dois

"pascal_case"

Est-ce que PHP offre une fonction à cet effet?

Était-ce utile?

La solution

Essayez ceci sur la taille:

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

Sortie:

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

met en œuvre les règles suivantes:

  1. Une séquence commençant par une lettre minuscule doit être suivie par des lettres minuscules et chiffres;
  2. peut suivre une séquence commençant par une lettre majuscule soit par:
    • une ou plusieurs lettres majuscules et des chiffres (suivi soit par la fin de la chaîne ou une lettre majuscule suivie par une lettre minuscule ou un chiffre-à-dire le début de la séquence suivante); ou
    • une ou plusieurs lettres ou chiffres minuscules.

Autres conseils

Une solution plus courte: Similaire à éditeur de une avec une expression régulière simplifiée et régler le problème "de fuite-underscore":

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

PHP Demo | Regex Démo


Notez que des cas comme SimpleXML seront convertis en simple_x_m_l en utilisant la solution ci-dessus. Cela peut également être considéré comme une mauvaise utilisation de la notation de cas de chameau (correct serait SimpleXml) plutôt que d'un bug de l'algorithme car ces cas sont toujours ambigus - même en regroupant les caractères majuscules à une chaîne (simple_xml) tel algorithme sera toujours échouer dans d'autres cas de pointe comme des mots XMLHTMLConverter ou à une lettre près des abréviations, etc. Si vous ne me dérange pas sur les cas de bord (plutôt rare) et que vous souhaitez gérer correctement SimpleXML, vous pouvez utiliser une solution peu plus complexe:

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

PHP Demo | Regex Démo

Une solution concise et peut traiter certains cas d'utilisation délicate:

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

Peut gérer tous ces cas:

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

Vous pouvez tester ici cette fonction: http://syframework.alwaysdata.net/decamelize

Ported de la String#camelize et String#decamelize 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); 
}

Une astuce les solutions ci-dessus peut-être manqué est le modificateur « e » qui provoque preg_replace d'évaluer la chaîne de remplacement code PHP.

La composante Symfony sérialiseur a CamelCaseToSnakeCaseNameConverter qui a deux méthodes normalize() et denormalize(). Ceux-ci peuvent être utilisés comme suit:

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

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

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

La plupart des solutions ici sentent la main lourde. Voici ce que j'utilise:

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

"camelcase" est converti en "camel_case"

  • lcfirst($camelCase) abaissera le premier caractère (évite de la camelcase 'sortie convertie commencer par un trait de soulignement)
  • [A-Z] trouve des lettres majuscules
  • + traitera chaque majuscule consécutive comme mot ( « évite camelcase » à convertir en camel_C_A_S_E)
  • Second motif et le remplacement sont pour ThoseSPECCases -> those_spec_cases au lieu de those_speccases
  • strtolower([…]) tourne la sortie à bas de casse

php ne propose pas construit en fonction de ce AFAIK, mais voici ce que j'utilise

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

}

le séparateur peut être spécifié dans l'appel de fonction, de sorte que vous pouvez l'appeler comme si

$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_áááá_őőőő

Si vous cherchez une version PHP 5.4 et répondre plus tard voici le 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
    );

} 

Pas de fantaisie du tout, mais simple et rapide comme l'enfer:

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" à "camel_case":

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

ou

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

Une version qui n'utilise pas regex peut être trouvée dans la source Alchitect :

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

Voici donc un one-liner:

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

danielstjules / Stringy provieds un procédé pour convertir la chaîne de camelcase à snake case.

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

Laravel 5.6 fournit un moyen très simple de faire ceci:

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

Ce qu'il fait: si elle voit qu'il ya au moins une lettre majuscule dans la chaîne donnée, il utilise un positif pour rechercher préanalyse tout caractère (.) suivi d'une lettre capitale ((?=[A-Z])). Il remplace alors le caractère trouvé avec sa valeur suivie par la _ de separactor.

Le port direct de rails (moins leur traitement spécial pour :: ou acronymes) serait

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, '-', '_'));
}

Savoir PHP, ce sera plus rapide que l'analyse syntaxique manuel qui se passe dans d'autres réponses ici. L'inconvénient est que vous ne recevez pas de choisir ce qu'il faut utiliser comme séparateur entre les mots, mais qui ne faisait pas partie de la question.

Vérifiez également la de code

Notez que cela est destiné à être utilisé avec des identificateurs ASCII. Si vous devez le faire avec des caractères en dehors de la plage ASCII, utilisez le modificateur « / u » pour preg_match mb_strtolowerand d'utilisation.

Voici ma contribution à une question de six ans avec Dieu sait combien de réponses ...

Il convertit tous les mots dans la chaîne fournie qui sont dans camelcase à snake case. Par exemple "SuperSpecialAwesome et aussi FizBuzz καιΚάτιΑκόμα" sera converti en "super_special_awesome et aussi fizz_buzz και_κάτι_ακόμα".

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

Yii2 ont les différentes fonctions pour rendre le mot snake_case de 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);
}
$str = 'FooBarBaz';

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

Ceci est l'une des façons plus courtes:

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

Comment dé-camelize sans utiliser regex:

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

Un edit:

Comment puis-je faire cela en 2019:

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

Et quand PHP 7.4 sera disponible:

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

Solution à court:

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

Il est facile à l'aide des classes de filtre du Zend Mot filtres :

<?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

J'ai eu un problème similaire mais ne pouvait pas trouver une réponse qui satisfait comment convertir CamelCase à snake_case, tout en évitant de dupliquer ou redondantes pour les noms des underscores _ avec des underscores, ou toutes les abréviations caps.

Th problème est comme suit:

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

La solution que j'ai écrit est un deux simples fonctions d'appel, minuscules et rechercher et remplacer les lettres minuscules en majuscules consécutives:

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

Si vous pouviez commencer par:

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

Ensuite, vous pouvez convertir en deux cas seulement avec:

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

Ou tout autre cas:

$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string);               // CAMEL_CASE
$train = str_replace("_", "-", $snake);        // camel-case
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top