Si j'avais:
$string = "CamelCase";
J'ai besoin
"camel_case"
Est-ce que PHP offre une fonction à cette fin?
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);
}
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
Ceci implémente les règles suivantes:
Une solution plus courte: Similaire à celle de editor's avec une expression rationnelle simplifiée et résolvant le problème "trailing-underscore":
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
Notez que les cas tels que SimpleXML
seront convertis en simple_x_m_l
en utilisant la solution ci-dessus. Cela peut aussi être considéré comme une mauvaise utilisation de la notation de cas de chameaux (correct serait SimpleXml
) plutôt qu’un bug de l’algorithme puisque ces cas sont toujours ambigus - même en regroupant les caractères majuscules dans une chaîne (simple_xml
), cet algorithme échouera toujours Les cas Edge tels que XMLHTMLConverter
ou les mots d'une lettre proches des abréviations, etc. Si cela ne vous dérange pas du cas (plutôt rare) Edge et que vous souhaitez gérer SimpleXML
, vous pouvez utiliser une solution un 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é à partir des String#camelize
et String#decamelize
de 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 que les solutions ci-dessus ont peut-être manquée est le modificateur 'e' qui oblige preg_replace
à évaluer la chaîne de remplacement comme un code PHP.
La plupart des solutions ici sont 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)
réduira le premier caractère (évite que la sortie convertie 'CamelCASE' commence par un trait de soulignement)[A-Z]
trouve des lettres 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 de those_speccases
strtolower([…])
tourne la sortie en minusculeLe composant de sérialisation Symfony 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
php n'offre pas de fonction intégrée pour cette 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 suit
$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_áááá_őőőő
(La "solution" acceptée est un échec épique ...)
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
);
}
"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, '_');
}
Pas du tout chic 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
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 procéder:
/**
* 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 un positif lookahead pour rechercher un caractère (.
) suivi d'une majuscule ((?=[A-Z])
). Il remplace ensuite le caractère trouvé par sa valeur suivie du séparateur _
.
Donc, voici un one-liner:
strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));
Une version qui n’utilise pas regex peut être trouvée dans 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);
}
Voici ma contribution à une question vieille 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 FizBuzz καιΚάτιΑκόμα" seront convertis en "super_special_awesome et fizz_buzz και_κάτι_ακόμα".
mb_strtolower(
preg_replace_callback(
'/(?<!\b|_)\p{Lu}/u',
function ($a) {
return "_$a[0]";
},
'SuperSpecialAwesome'
)
);
Le port direct depuis Rails (moins leur traitement spécial pour :: ou des 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, cela sera plus rapide que l'analyse manuelle utilisée dans les autres réponses données ici. L'inconvénient est que vous ne devez pas choisir quoi utiliser comme séparateur entre les mots, mais cela ne faisait pas partie de la question.
Vérifiez également le code source pertinent de Rails
Notez que ceci est destiné à être utilisé avec les identificateurs ASCII. Si vous devez le faire avec des caractères situés en dehors de la plage ASCII, utilisez le modificateur '/ u' pour preg_match
et utilisez mb_strtolower
.
Si vous utilisez le framework Laravel, vous pouvez utiliser juste snake_case () method.
$str = 'FooBarBaz';
return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $str)); // foo_bar_baz
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);
}
Yii2 a la fonction différente de 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));
C'est ce que j'utilise pour la décamélisation:
function decamelize($str, $glue='_') {
$capitals = array();
$replace = array();
foreach(str_split($str) as $index => $char) {
if(ord($char) >= 65 && ord($char) <= 90) {
$capitals[] = $char;
$replace[] = ($index > 0 ? $glue : '').strtolower($char);
}
}
if(sizeof($capitals)) return str_replace($capitals, $replace, $str);
return $str;
}
C'est l'un des moyens les plus courts:
function camel_to_snake($string)
{
return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}
La bibliothèque open source TurboCommons contient une méthode polyvalente formatCase () dans la classe StringUtils, qui vous permet de convertir une chaîne en un grand nombre de formats de cas courants, tels que CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case, etc.
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'
C'est facile d'utiliser les classes de filtres de Zend Filtres de mots :
<?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 pire réponse ici était si proche d'être la meilleure (utilisez un cadre). NO DON'T, jetez simplement un coup d'œil au code source. voir ce qu'un cadre bien établi utilise serait une approche beaucoup plus fiable (testée et éprouvée) Le framework Zend a des filtres Word qui répondent à vos besoins. La source .
voici quelques méthodes que j'ai adaptées à partir 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");