Si je l'avais fait :
$string = "PascalCase";
J'ai besoin
"pascal_case"
PHP offre-t-il une fonction à cet effet ?
Si je l'avais fait :
$string = "PascalCase";
J'ai besoin
"pascal_case"
PHP offre-t-il une fonction à cet effet ?
Une solution plus courte : Semblable à la de l'éditeur l'un avec une expression régulière simplifiée et en corrigeant le problème du "trailing-underscore" :
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
Démo PHP | Démonstration de Regex
Notez que des cas comme SimpleXML
sera converti 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 la casse (la solution correcte serait SimpleXml
) plutôt qu'un bug de l'algorithme puisque de tels cas sont toujours ambigus - même en regroupant les caractères majuscules en une seule chaîne ( simple_xml
), un tel algorithme échouera toujours dans d'autres cas limites tels que XMLHTMLConverter
ou des mots d'une lettre près des abréviations, etc. Si vous ne vous préoccupez pas de ces cas limites (plutôt rares) et que vous souhaitez traiter SimpleXML
correctement, vous pouvez utiliser une solution un peu plus complexe :
$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
N'hésitez pas à commenter la réponse de cletus en détaillant les cas de test que vous avez corrigés.
Je ne dis pas que sa solution donne de mauvais résultats. Sa solution est juste extrêmement compliquée et inefficace.
Oui, la réponse acceptée est définitivement un échec. La solution de Jan est géniale ! En passant, je pense que ce test (ou une légère variation) est mon nouveau test de codage préféré pour les développeurs PHP, car le nombre de réponses fournies à cette question qui ne fonctionnent pas est incroyable. Ce serait un excellent moyen de faire le filtrage initial :-)
Essayez-le 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
Cela met en œuvre les règles suivantes :
Il fonctionne pour les chaînes en casse camel (comme l'a demandé openfrog), mais si vous l'utilisez avec une chaîne en entrée, par exemple "r_id" (déjà "soulignée"), il coupe le préfixe ("r_"). Bonne solution, mais certainement pas universelle.
Je suis curieux de savoir pourquoi vous vérifiez si une chaîne de caractères correspond à une chaîne de caractères en majuscules ? Quel est l'avantage de convertir uniquement le premier caractère en minuscules (par opposition à tous les caractères) ?
Une solution plus concise qui peut également gérer tous ces cas d'utilisation : stackoverflow.com/a/35719689/4328383
Porté par le programme 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 peut-être oubliée est le modificateur "e" qui fait que preg_replace
pour évaluer la chaîne de remplacement en tant que code PHP.
D'ailleurs, ceux-ci ne sont pas non plus dans Ruby, mais dans la bibliothèque d'inflecteurs de Rails - camelize et underscore. api.rubyonrails.org/classes/ActiveSupport/Inflector.html
Cela échoue pour "ThisIsATest". Il semble qu'il ne supporte pas deux majuscules consécutives.
La plupart des solutions proposées 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 (pour éviter que la sortie convertie par 'CamelCASE' ne 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([…])
met la sortie en minuscules
C'est génial - il suffit d'ajouter un substrat commençant au caractère 1 pour contourner ce problème.
Php n'offre pas de fonction intégrée pour cela, 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 la fonction, ainsi vous pouvez l'appeler comme suit
$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"
Cela échoue pour "ThisIsATest". Il semble qu'il ne supporte pas deux majuscules consécutives.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
31 votes
Techniquement, la première chaîne d'exemple est PascalCase.
33 votes
Et le deuxième exemple de chaîne est connu sous le nom de snake_case .