Si j'avais:
$string = "PascalCase";
j'ai besoin
"pascal_case"
PHP propose-t-il une fonction à cet effet?
Si j'avais:
$string = "PascalCase";
j'ai besoin
"pascal_case"
PHP propose-t-il une fonction à cet effet?
Réponses:
Essayez ceci pour 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);
}
Production:
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
Cela met en œuvre les règles suivantes:
Une solution plus courte: similaire à celle de l' éditeur avec une expression régulière simplifiée et corrigeant le problème du "trait de soulignement de fin":
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
Notez que les cas comme SimpleXML
seront convertis en simple_x_m_l
utilisant la solution ci-dessus. Cela peut également être considéré comme une mauvaise utilisation de la notation en cas de chameau (ce serait correct SimpleXml
) plutôt qu'un bogue de l'algorithme car de tels cas sont toujours ambigus - même en regroupant les caractères majuscules dans une chaîne ( simple_xml
), cet algorithme échouera toujours dans les autres cas extrêmes comme XMLHTMLConverter
ou mots d' une lettre près abréviations, etc. Si vous ne me dérange pas sur les cas de bord (plutôt rare) et que vous souhaitez gérer SimpleXML
correctement, vous pouvez utiliser une solution peu plus complexe:
$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
Une solution concise et peut gérer certains cas d'utilisation délicats:
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 cette fonction ici: http://syframework.alwaysdata.net/decamelize
Porté de Ruby String#camelize
et String#decamelize
.
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 que les solutions ci-dessus ont pu manquer est le modificateur «e» qui permet preg_replace
d'évaluer la chaîne de remplacement en tant que code PHP.
e
indicateur pour preg_replace
est obsolète dans PHP 5.5.
^|
ou strlen
.
Le composant Symfony Serializer a un 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
$nameConverter->normalize('CamelCase')
sorties _camel_case
dans la version actuelle 3.2 du composant Symfony Serializer.
La plupart des solutions ici semblent lourdes. 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 que la sortie convertie 'CamelCASE' commence par un trait de soulignement)[A-Z]
trouve les majuscules+
traitera chaque majuscule consécutive comme un mot (évite que 'CamelCASE' soit converti en camel_C_A_S_E)ThoseSPECCases
-> those_spec_cases
au lieu dethose_speccases
strtolower([…])
transforme la sortie en minusculeslcfirst
fonction à $ camelCase
ucfirst()
appel. USADollarSymbol
devient u_sa_dollar_symbol
Demo Je ne recommande pas cette solution car elle doit faire deux passes dans la chaîne d'entrée avec regex - un signe d'un modèle non raffiné.
php n'offre pas de fonction intégrée pour cet 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, vous pouvez donc l'appeler comme ceci
$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"
mb_strtolower
et l' /u
option activée preg_replace
.
Vous devez exécuter une expression régulière qui correspond à toutes les lettres majuscules sauf si elle est au début et la remplacer par un trait de soulignement plus cette lettre. Une solution utf-8 est la suivante:
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 n'êtes pas sûr de la casse de votre chaîne, mieux vaut la vérifier d'abord, car ce code suppose que l'entrée est à la camelCase
place de underscore_Case
ou dash-Case
, donc si les derniers ont des lettres majuscules, il leur ajoutera des traits de soulignement.
La réponse acceptée de cletus est beaucoup trop compliquée à mon humble avis et cela ne fonctionne qu'avec les caractères latins. Je trouve que c'est une très mauvaise solution et je me demande pourquoi elle a été acceptée. La conversion TEST123String
en test123_string
n'est pas nécessairement une exigence valable. Je l'ai plutôt gardé simple et séparé ABCccc
en a_b_cccc
au lieu de ab_cccc
parce qu'il ne perd pas d'informations de cette façon et la conversion vers l'arrière donnera exactement la même chaîne avec laquelle nous avons commencé. Même si vous voulez le faire dans l'autre sens, il est relativement facile d'écrire une expression régulière pour elle avec un (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}
regard en arrière positif ou deux expressions régulières sans regarder en arrière si vous n'êtes pas un expert en expression régulière. Il n'est pas nécessaire de le diviser en sous-chaînes sans parler du choix entre strtolower
et lcfirst
où l'utilisation strtolower
serait tout à fait correcte.
Si vous recherchez une version PHP 5.4 et une réponse ultérieure, 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 du tout fantaisiste 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
++$i
au lieu de $i++
le rendre un peu plus rapide aussi;)
"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, '_');
}
this-kind-of-output
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));
g
modificateur à cette expression régulière.
g
et cela fonctionne très bien pour moi.
g
. Mais je ne me souviens pas de la phrase avec laquelle j'ai testé.
danielstjules / Stringy fournit une méthode pour convertir une chaîne de camelcase en snakecase.
s('TestUCase')->underscored(); // 'test_u_case'
Laravel 5.6 fournit un moyen très simple de le faire:
/**
* 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: s'il voit qu'il y a au moins une lettre majuscule dans la chaîne donnée, il utilise une anticipation positive pour rechercher n'importe quel caractère ( .
) suivi d'une majuscule ( (?=[A-Z])
). Il remplace ensuite le caractère trouvé par sa valeur suivie du séparateur _
.
Le port direct depuis les rails (moins leur traitement spécial pour :: ou les 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, '-', '_'));
}
Connaissant PHP, ce sera plus rapide que l'analyse manuelle qui se produit dans d'autres réponses données ici. L'inconvénient est que vous ne pouvez pas choisir ce qu'il faut utiliser comme séparateur entre les mots, mais cela ne faisait pas partie de la question.
Vérifiez également le code source des rails pertinents
Notez que ceci est destiné à être utilisé avec les identificateurs ASCII. Si vous devez faire cela avec des caractères en dehors de la plage ASCII, utilisez le modificateur '/ u' pour preg_match
et utilisez mb_strtolower
.
Voici ma contribution à une question de six ans avec Dieu sait combien de réponses ...
Il convertira tous les mots de la chaîne fournie qui sont dans camelcase en snakecase. Par exemple, "SuperSpecialAwesome et aussi FizBuzz καιΚάτιΑκόμα" seront convertis en "super_special_awesome et aussi fizz_buzz και_κάτι_ακόμα".
mb_strtolower(
preg_replace_callback(
'/(?<!\b|_)\p{Lu}/u',
function ($a) {
return "_$a[0]";
},
'SuperSpecialAwesome'
)
);
Yii2 a la fonction différente pour créer 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));
}
Solution courte:
$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));
J'ai eu un problème similaire mais je n'ai trouvé aucune réponse satisfaisant la conversion de CamelCase en snake_case, tout en évitant les traits de soulignement en double ou redondants _
pour les noms avec des traits de soulignement ou les abréviations en majuscules.
Le problème est le suivant:
CamelCaseClass => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ => faq
La solution que j'ai écrite est un simple appel à deux fonctions, minuscules et rechercher et remplacer des lettres minuscules-majuscules consécutives:
strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $name));
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);
}
$name{$k}
(ou $name[$k]
), ce qui allongerait votre code, mais évite la surcharge de le convertir vers et à partir d'un tableau.
La pire réponse ici était si proche d'être la meilleure (utilisez un cadre). NON NE PAS, jetez un œil au code source. voir ce qu'un cadre bien établi utilise serait une approche beaucoup plus fiable (éprouvée et testée). Le framework Zend a quelques filtres de mots qui correspondent à vos besoins. Source .
voici quelques méthodes que j'ai adaptées de la source.
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");
Il existe une bibliothèque offrant cette fonctionnalité:
SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"
Si vous utilisez le framework Laravel, vous pouvez utiliser uniquement la méthode snake_case () .
C'est l'un des moyens les plus courts:
function camel_to_snake($input)
{
return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}
Comment dé-caméliser 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;
}
Une modification:
Comment pourrais-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 sortira:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}
C'est facile d'utiliser les classes Filter des Zend Word Filters :
<?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;
}
}
----- soulignéToCamelCase -----
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 bibliothèque open source TurboCommons contient une méthode formatCase () à usage général dans la classe StringUtils, qui vous permet de convertir une chaîne en de nombreux formats de cas courants, tels que CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case, et bien d'autres.
https://github.com/edertone/TurboCommons
Pour l'utiliser, importez le fichier phar dans votre projet et:
use org\turbocommons\src\main\php\utils\StringUtils;
echo StringUtils::formatCase('camelCase', StringUtils::FORMAT_SNAKE_CASE);
// will output 'camel_Case'
$str = 'FooBarBaz';
return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $str)); // foo_bar_baz
SI vous pouviez commencer par:
$string = 'Camel_Case'; // underscore or any other separator...
Ensuite, vous pouvez convertir dans les deux cas simplement 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