Как конвертировать CamelCase в случай верблюда?
Если бы я:
$string = "CamelCase";
мне нужно
"camel_case"
PHP предлагает функцию для этой цели?
27 ответов
Попробуй вот это:
$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);
}
выход:
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
это реализует следующие правила:
- последовательность, начинающаяся со строчной буквы, должна сопровождаться строчными буквами и цифрами;
- последовательность, начинающаяся с заглавной буквы, может сопровождаться либо:
- одна или несколько заглавных букв и цифр (за ними следует либо конец строки, либо заглавная буква, за которой следует строчная буква или цифра ie начало следующей последовательности); или
- одна или несколько строчных букв или цифр.
более короткое решение: аналогично редактора один с упрощенным регулярным выражением и фиксацией проблемы "трейлинг-подчеркивание":
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_', $input));
обратите внимание, что такие случаи, как SimpleXML
будет преобразовано в simple_x_m_l
используя вышеуказанное решение. Это также можно считать неправильным использованием обозначения случая верблюда (правильным было бы SimpleXml
), а не ошибка алгоритма, так как такие случаи всегда неоднозначны - даже путем группировки символов верхнего регистра в одну строку (simple_xml
) такой алгоритм всегда будет терпеть неудачу в других случаях, как XMLHTMLConverter
или однобуквенные слова рядом с аббревиатурами и т. д. Если вы не возражаете против (довольно редких) крайних случаев и хотите обработать SimpleXML
правильно, вы можете использовать немного более сложное решение:
$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_', $input)), '_');
краткое решение и может обрабатывать некоторые сложные случаи использования:
function decamelize($string) {
return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '_', $string));
}
может обрабатывать все эти случаи:
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
вы можете проверить эту функцию здесь:http://syframework.alwaysdata.net/decamelize
портирован с Руби String#camelize
и 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);
}
один трюк вышеуказанные решения, возможно, пропустили модификатор "e", который вызывает preg_replace
чтобы оценить строку замены как PHP-код.
большинство решений здесь чувствуют себя тяжелыми руками. Вот что я использую:
$underscored = strtolower(
preg_replace(
["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"],
["_", "__"],
lcfirst($camelCase)
)
);
"CamelCASE" преобразуется в "camel_case"
-
lcfirst($camelCase)
понизит первый символ (избегает преобразованного вывода "CamelCASE", чтобы начать с подчеркивания) -
[A-Z]
находит заглавные буквы -
+
будет рассматривать каждый последовательный верхний регистр как слово (избегает "CamelCASE" для преобразования в camel_C_A_S_E) - вторая картина и замена для
ThoseSPECCases
->those_spec_cases
вместоthose_speccases
-
strtolower([…])
переводит вывод в нижний регистр
на Компонент Сериализатора Symfony есть CamelCaseToSnakeCaseNameConverter это имеет два метода normalize()
и denormalize()
. Их можно использовать следующим образом:
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
echo $nameConverter->normalize('camelCase');
// outputs: camel_case
echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase
php не предлагает встроенную функцию для этого afaik, но вот что я использую
function uncamelize($camel,$splitter="_") {
$camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'', $camel));
return strtolower($camel);
}
разделитель может быть указан в вызове функции, поэтому вы можете назвать его так
$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', '_', 'AaaaBbbbCcccDdddÁáááŐőőő');
$lower = mb_strtolower($separated, 'utf-8');
echo $lower; //aaaa_bbbb_cccc_dddd_áááá_őőőő
(принятое "решение" - это эпический сбой...)
Не роскошный, но простой и быстрый, как ад:
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
Если вы ищете версию PHP 5.4 и более поздний ответ, Вот код:
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]/', '_', $camel);
$snake = strtolower($snake);
$snake = ltrim($snake, '_');
return $snake;
}
или:
function camelToSnake($camel)
{
$snake = preg_replace_callback('/[A-Z]/', function ($match){
return '_' . strtolower($match[0]);
}, $camel);
return ltrim($snake, '_');
}
версию, которая не использует регулярное выражение, можно найти в 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);
}
Итак, вот одна строка:
strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '_', $string));
danielstjules / Stringy provieds метод преобразования строки из camelcase в snakecase.
s('TestUCase')->underscored(); // 'test_u_case'
прямой порт от rails (минус их специальная обработка Для:: или аббревиатур) будет
function underscore($word){
$word = preg_replace('#([A-Z\d]+)([A-Z][a-z])#','_', $word);
$word = preg_replace('#([a-z\d])([A-Z])#', '_', $word);
return strtolower(strtr($word, '-', '_'));
}
зная PHP, это будет быстрее, чем ручной разбор, который происходит в других ответах, приведенных здесь. Недостатком является то, что вы не можете выбрать, что использовать в качестве разделителя между словами, но это не было частью вопроса.
проверьте соответствующий исходный код rails
обратите внимание, что это предназначено для использования с ASCII идентификаторы. Если вам нужно сделать это с символами вне диапазона ASCII, используйте модификатор' /u ' для preg_match
и использовать mb_strtolower
.
он преобразует все слова в предоставленной строке, которые находятся в camelcase в snakecase. Например, "SuperSpecialAwesome, а также FizBuzz καιΚάτιΑκόμα" будет преобразован в "super_special_awesome, а также fizz_buzz και_κάτι_ακ .μα".
mb_strtolower(
preg_replace_callback(
'/(?<!\b|_)\p{Lu}/u',
function ($a) {
return "_$a[0]";
},
'SuperSpecialAwesome'
)
);
Laravel 5.6 предоставляет очень простой способ сделать это:
/**
* 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', ''.$delimiter, $value));
}
return $value;
}
что он делает: если он видит, что в данной строке есть хотя бы одна заглавная буква, он использует положительный lookahead для поиска любого символа (.
) следуют буквы ((?=[A-Z])
). Затем он заменяет найденного символа с его значением и separactor _
.
Это то, что я использую для декамелизации метода:
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;
}
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);
}
есть библиотека обеспечение этой функции:
SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"
Если вы используете Laravel framework, вы можете использовать только snake_case () метод.
легко использовать классы фильтров Zend Слово Фильтры:
<?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
легко >>> легко
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
легко >>> легко
HTML > > > html
simpleXML >>> simple_xml
PDFLoad >>> pdf_load
startMIDDLELast >>> start_middle_last
AString >>> a_string
Some4Numbers234 >>> some4_numbers234
TEST123String >>> test123_string
худший ответ здесь был так близок к лучшему (используйте фреймворк). Нет, не надо, просто взгляните на исходный код. понимание того, что хорошо зарекомендовавшая себя рамочная основа использует, было бы гораздо более надежным подходом(испытанным и проверенным). Zend framework имеет некоторые фильтры word, которые соответствуют вашим потребностям. источник.
вот несколько методов, которые я адаптировал из источника.
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 . '', $separator . ''];
} else {
$pattern = ['#(?<=(?:[A-Z]))([A-Z]+)([A-Z][a-z])#', '#(?<=(?:[a-z0-9]))([A-Z])#'];
$replacement = ['' . $separator . '', $separator . ''];
}
return preg_replace($pattern, $replacement, $value);
}
function CamelCaseToUnderscore($value){
return CamelCaseToSeparator($value,'_');
}
function CamelCaseToDash($value){
return CamelCaseToSeparator($value,'-');
}
$string = CamelCaseToUnderscore("CamelCase");
библиотека TurboCommons с открытым исходным кодом содержит метод formatCase() общего назначения внутри класса StringUtils, который позволяет конвертировать строку во множество распространенных форматов, таких как CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case и многие другие.
https://github.com/edertone/TurboCommons
чтобы использовать его, импортируйте файл phar в свой проект и:
use org\turbocommons\src\main\php\utils\StringUtils;
echo StringUtils::formatCase('camelCase', StringUtils::FORMAT_SNAKE_CASE);
// will output 'camel_Case'
Yii2 имеют другую функцию, чтобы сделать слово snake_case из 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));
}
если бы вы могли начать с:
$string = 'Camel_Case'; // underscore or any other separator...
тогда вы можете конвертировать в любой случай только с:
$pascal = str_replace("_", "", $string);
$snake = strtolower($string);
или любые другие случаи:
$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string); // CAMEL_CASE
$train = str_replace("_", "-", $snake); // camel-case