Як перетворити PascalCase в pascal_case?


Відповіді:


163

Спробуйте це для розміру:

$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

Тут реалізуються такі правила:

  1. Послідовність, що починається з малої літери, повинна супроводжуватися малими літерами та цифрами;
  2. Послідовність, що починається з великої літери, може супроводжуватися будь-яким:
    • одна або кілька великих літер і цифр (з наступним кінцем рядка або великою літерою з наступною малою літерою або цифрою, тобто початком наступної послідовності); або
    • одна або кілька малих літер або цифр.

9
Він працює для рядків CamelCased (як запитав openfrog), але якщо ви використовуєте його з рядком введення, наприклад "r_id" (вже "підкреслено"), він обрізає префікс ("r_"). Гарне рішення, але, безумовно, не універсальне.
— Мартін

1
Цікаво, чому ви перевіряєте, чи збігається рядок з рядком all-caps? Яка перевага перетворення лише першого символу на малі (на відміну від усіх символів)?
— Джош

1
Більш коротке рішення , яке також може обробляти всі ці випадки використання: stackoverflow.com/a/35719689/4328383
— Syone

156

Коротше рішення: Подібно до редактору зі спрощеним регулярним виразом та виправленням проблеми "підкреслення-підкреслення":

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

PHP Демо | Демонстрація Regex


Зауважте, що подібні випадки SimpleXMLбудуть перетворені на simple_x_m_lвикористання вищезазначеного рішення. Це також можна вважати неправильним використанням позначення справи верблюда (правильним було б SimpleXml), а не помилкою алгоритму, оскільки такі випадки завжди неоднозначні - навіть якщо групувати великі символи в одну рядок ( simple_xml) такий алгоритм завжди вийде з ладу в інших крайових випадках наприклад, XMLHTMLConverterоднолітерні слова біля абревіатур тощо. Якщо ви не заперечуєте проти (досить рідкісних) крайових справ і хочете SimpleXMLправильно попрацювати, ви можете скористатися трохи складнішим рішенням:

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

PHP Демо | Демонстрація Regex


Не соромтесь коментувати відповідь клетуса, в якому детально описували тестові випадки, які ви виправили.
— Майк Б

3
Я не кажу, що його рішення дає неправильні результати. Його рішення просто надзвичайно складне та неефективне.
— Ян Джекеш

1
Так, прийняти відповідь, безумовно, не вдалося. Рішення Яна - приголомшливе! Як зауваження, я вважаю, що це (або незначна зміна) - це мій новий, улюблений тест кодування для розробників PHP, оскільки кількість відповідей на це питання, які насправді не працюють, неймовірна. Це було б чудовим способом зробити початкову фільтрацію. :-)
— JamesG

знайшов регулярний вираз , що використовується в цьому розчині набагато більш повний: stackoverflow.com/questions/2559759 / ...
— thoroc

2
Приємне рішення для простих випадків використання, і в більшості звичайних випадків цього достатньо, але прийняте рішення може обробляти більше випадків використання, наприклад, "simpleXML" може бути перетворений на "simple_xml", а не "simple_x_m_l"
— Syone

35

Коротке рішення і може вирішити деякі складні випадки використання:

function decamelize($string) {
    return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $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


@VivekVardhan, яку частину цього виразів ти не розумієш?
— Syone

Ум, я вважаю, що рядки, що не містять верблюдів, є побічним ефектом, якщо рядок не у форматі верблюда, слід повернути оригінал. Infact, якщо ви надсилаєте 'simple_Text', ви отримуєте Fail: simple_Test => simple_Test [simple_test]. Рядок з нижньою обробкою має бути зроблений лише тоді, якщо лише оригінальна струна є справжньою ланцюжкою верблюда. Що ви думаєте про?
— guideo

24

Порт із Рубі 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-код.


10
eПрапор preg_replaceє застарілим в PHP 5.5.
— cdmckay

До цих пір вони також не в Ruby, а в бібліотеці інфлекторів Rails - підкреслити і підкреслити. api.rubyonrails.org/classes/ActiveSupport/Inflector.html
— mahemoff

2
Це не вдається для "ThisIsATest". Здається, це не підтримує дві великі регістри поспіль.
— OnaBai

Лише зауваження: ви можете скористатися lcfirst, щоб отримати першу букву в малі регістри, тоді вам не потрібно ^|або strlen.
— Benubird

декамелізація без зневаги: gist.github.com/scones/e09c30e696246fda14578bcf8ab4910a
— scones

23

Symfony Serializer компонент має CamelCaseToSnakeCaseNameConverter , який має два методи normalize()і denormalize(). Їх можна використовувати наступним чином:

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

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

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

1
Остерігайся! $nameConverter->normalize('CamelCase')виводить _camel_caseу поточній версії 3.2 компонента серіалізатора Symfony.
— spackmat

21

Більшість рішень тут відчувають важкі руки. Ось що я використовую:

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

"CamelCASE" перетворюється на "camel_case"

  • lcfirst($camelCase) знизить перший символ (уникає перетвореного результату "CamelCASE", щоб почати з підкреслення)
  • [A-Z] знаходить великі літери
  • + буде розглядати кожну верхню верхню букву як слово (уникає перетворення "CamelCASE" на camel_C_A_S_E)
  • Другий шаблон і заміна призначені для ThoseSPECCases-> those_spec_casesзамістьthose_speccases
  • strtolower([…]) перетворює вихід на малі регістри

3
Але це також перетворює CamelCased на _camel_cased.
— акме

1
це чудово - просто додайте субстрат, починаючи з char 1, щоб подолати цю проблему.
— Оддман

4
Відмінник! Просто потрібно додати lcfirstфункцію до $ camelCase
— Edakos

Прийнята відповідь буде обробляти: TestUPSClass в test_ups_class, тоді як це перетворить його в test_u_p_s_class, що потрібно пам’ятати.
— Mazzy

Введення рядка, що починається з першого слова "allcaps", буде несподівано розділене цим рішенням через ucfirst()дзвінок. USADollarSymbolстає u_sa_dollar_symbol демо. Я не рекомендую це рішення, оскільки він повинен зробити два проходи через вхідну рядок з регулярним виразом - ознака нерафінованого шаблону.
— mickmackusa

19

php не пропонує вбудованої функції для цього afaik, але ось що я використовую

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

}

сплітер може бути вказаний у виклику функції, тож ви можете назвати його так

$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"

2
Це не вдається для "ThisIsATest". Здається, це не підтримує дві великі регістри поспіль.
— OnaBai

Напевно ви щось забули, оскільки друга заміна нічого не робить. Крім цього, ви можете легко зробити його unicode сумісним з mb_strtolowerі /uопцією preg_replace.
— BODO

8

Потрібно пропустити через нього регулярний вираз, який відповідає кожній великій літері, за винятком випадків, якщо він знаходиться на початку, і замінити його підкресленням плюс цей лист. Рішення utf-8 таке:

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

Якщо ви не впевнені, у якому випадку знаходиться ваш рядок, краще спочатку перевірити його, оскільки цей код передбачає, що введення camelCaseзамість underscore_Caseабоdash-Case , тому, якщо на запісах є великі літери, вони додадуть їм підкреслення.

Прийнята відповідь від клетка є занадто складною імхо, і вона працює лише з латинськими символами. Я вважаю це дійсно поганим рішенням і цікаво, чому це взагалі було прийнято. Перетворення TEST123Stringв test123_stringне обов'язково є дійсною вимогою. Я досить тримав його простим і розділений ABCcccна a_b_ccccзамість того , ab_ccccтому що це не втратити інформацію так і в зворотному напрямку перетворення дасть ту ж саму рядок , яку ми почали. Навіть якщо ви хочете зробити це іншим способом, відносно легко написати для нього регулярний вираз з позитивним виглядом позаду (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}або двома регулярними виразками без огляду, якщо ви не експерт з регулярних виразів. Там немає необхідності , щоб розбити його на підрядка не кажучи вже про вибір між strtolowerі lcfirstде з використанням тільки strtolowerб абсолютно нормально.


Відповіді, що стосуються лише коду, мають низьку цінність для Stackoverflow, оскільки вони роблять дуже мало для навчання / розширення можливостей тисяч майбутніх дослідників.
— mickmackusa

@mickmackusa Якщо дослідники дізнаються, як кодувати з SO, то у нас є серйозна проблема ...
— inf3rno

Тепер, коли ви отримали цю особисту атаку зі своєї системи, вдосконаліть свою відповідь. Якщо припустити, що ви знаєте, як працює ваше рішення і чому ви використовуєте ці модифікатори шаблону, я не бачу вагомих причин відмовлятися від знань у цій спільноті. Якщо ви розглядаєте можливість залишити більше химерних відповідей, я запевняю вас, що вони мене не турбують. У той час, коли ви взяли коментар, ви могли доповнити свою відповідь, ми могли видалити наші коментарі, і я міг поїхати в інше місце, щоб допомогти цьому сайту.
— mickmackusa

Звичайно, я не маю повноважень видаляти публікацію з 8 оновлень. Якщо ви хочете, ви можете видалити свою відповідь, але було б не важко просто її покращити, видаливши непотрібні модифікатори шаблону та додавши пояснення. Особисті напади на мене не впливають.
— mickmackusa

@mickmackusa Я не думаю, що я його також можу видалити. Не соромтесь редагувати його, якщо хочете.
— inf3rno

6

Якщо ви шукаєте версію 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
    );

} 

camelize produce "SmsSent" для sms_sent, потрібен lcfirst
— mik3fly-4steri5k

4

Зовсім не фантазії, а просто та швидко, як пекло:

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замість того, $i++щоб зробити це також трохи швидше;)
— Матьє Аміот

Відповіді, що стосуються лише коду, мають низьку цінність для Stackoverflow, оскільки вони роблять дуже мало для навчання / розширення можливостей тисяч майбутніх дослідників.
— mickmackusa

4

"CamelCase" - "camel_case":

function camelToSnake($camel)
{
    $snake = preg_replace('/[A-Z]/', '_$0', $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, '_');
}

Дякую. Я використовував перший підхід, але з дефісами для створенняthis-kind-of-output
— thexpand

3

Версію, яка не використовує регулярний вираз, можна знайти в джерелі 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);
}

2
Ось як виглядало б життя без регулярного
— виразу

4
Хе, так. RegEx безумовно має свої переваги. :) Сировинна швидкість - не одна з них.
— Даррелл Брогдон

чомусь отримали смішні результати з цим
— mr1031011

Не працює для мене на основі цього рядка: "CamelCaseTestAAATestAA", повинен містити: "camel_case_test_a_a_a_test_a_a", має: "" camel_case_test_aest "...
— Sybio

3

Отже, ось одноколісний:

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

Добре, але він конвертує лише перший вигляд, тому я рекомендую додати gмодифікатор до цього регулярного виразу.
— акме

@acme, я використовую його без gмене, і він чудово працює для мене.
— Seelts

Чомусь у моєму випадку мені довелося додати g. Але я не можу пригадати фразу, з якою я тестував.
— акме


3

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', '$1'.$delimiter, $value));
    }

    return $value;
}

Що це робиться: якщо він бачить, що в даному рядку є хоча б одна велика літера, для пошуку будь-якого символу ( ), за яким йде велика літера ( ) , використовується позитивний пошук . Потім він замінює знайдений символ його значенням, а потім роздільником ..(?=[A-Z])_


Ця функція, схоже, називається snake_case () і живе у глобальному просторі імен.
— Wotuu

2

Прямий порт від рейок (за вирахуванням їх спеціального поводження для :: або абревіатур) був би

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

Знаючи PHP, це буде швидше, ніж ручний розбір, що відбувається в інших відповідях, наведених тут. Недоліком є ​​те, що ви не можете вибрати, що використовувати як роздільник між словами, але це не було частиною питання.

Також перевірте відповідний вихідний код рейки

Зауважте, що це призначено для використання з ідентифікаторами ASCII. Якщо вам потрібно зробити це з символами, що знаходяться поза діапазоном ASCII, використовуйте модифікатор '/ u' для preg_matchвикористання mb_strtolower.


Ви можете, якщо просто додати параметр, який містить бажаний символ.
— Fleshgrinder

2

Ось мій внесок у шестирічне запитання з богом, скільки знає відповідей ...

Він перетворить усі слова із поданого рядка, що знаходяться у верблюді, у змію. Наприклад, "SuperSpecialAwesome, а також FizBuzz καιΚάτιΑκόμα" буде перетворено на "super_special_awesome, а також fizz_buzz και_κάτι_ακόμα".

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

2

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


2

У мене була подібна проблема, але не вдалося знайти жодної відповіді, яка б задовольняла, як перетворити CamelCase в snake_case, уникаючи при цьому дублікатів або зайвих підкреслень _імен з підкресленнями або всіх скорочень.

Проблема полягає в наступному:

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

Написане нами рішення - це простий дзвінок з двох функцій, малий і маленький пошук та пошук та заміна послідовних малих літер:

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

На сьогоднішній день це найбільш стисле і корисне рішення ІМО.
— Mr.Shan0

1
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}(або $name[$k]), що збільшить ваш код довше, але уникне великих витрат на перетворення його в масив і з нього.
— BODO

Відповіді, що стосуються лише коду, мають низьку цінність для StackOverflow, оскільки вони погано працюють із розширенням можливостей / навчанням майбутніх дослідників. Ваше рішення, уникаючи витонченості виразки, дуже важке і вивернуте. Ви розбиваєтеся на кожен символ і здійснюєте багаторазові повторення викликів функцій. Позначати порожню рядок як клею не потрібно. Я б не розважав цим рішенням в одному зі своїх проектів, оскільки немає елегантності, низької читабельності та n кількості непотрібних викликів функцій.
— mickmackusa

1

Найгірша відповідь тут була настільки близькою до того, щоб бути найкращим (використовуйте рамку). NO DON'T, просто подивіться на вихідний код. набагато надійнішим підходом (випробуваним) є бачення того, що використовує добре створена рамка. У рамках Zend є кілька фільтрів слів, які відповідають вашим потребам. Джерело .

ось пара методів, яку я адаптував із джерела.

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

1

Існує бібліотека, яка забезпечує цю функціональність:

SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"

1
Я думаю, ви маєте на увазі "я створив бібліотеку, яка забезпечує цю функціональність". Нічого поганого в саморекламі, але не приховуйте цього.
— icc97


1

Це один із коротших способів:

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

Відповіді, що стосуються лише коду, мають низьку цінність для Stackoverflow, оскільки вони роблять дуже мало для навчання / розширення можливостей тисяч майбутніх дослідників.
— mickmackusa

1
@mickmackusa - тисячі майбутніх досліджень будуть зацікавлені у витонченому однокласнику та навчатимуть себе.
— Teson

Мені шкода, що ти зайняв цю егоїстичну позицію. Ви, звичайно, могли б додати пояснення в той час, як вам знадобилося розробити та набрати цю відповідь. Ваша відповідь робить три функції дзвінка, але інші виконують завдання за два.
— mickmackusa

1

Як де-камелізіровать без використання регулярного вираження:

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

Редагування:

Як би я це зробив у 2019 році:

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

І коли PHP 7.4 вийде:

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

1
Відповіді, що стосуються лише коду, мають низьку цінність для StackOverflow, оскільки вони погано працюють із розширенням можливостей / навчанням майбутніх дослідників. Зробити від 1 до 3 функціональних дзвінків по кожному символу в рядку, а потім ще два виклики функції після виконання циклу дуже важкі. Я б не розважав над рішенням з такою поганою економікою.
— mickmackusa

Це приклад того, як це можна зробити без використання регулярних виразів, а не як це слід використовувати у виробництві, тому я не бачу вашої суті, крім того, що ви скаржитеся на відповідь 5y / o, що має одну нагоду, і навряд чи її побачать будь-які дослідники.
— лисини

Я приділяю свою увагу всім повідомленням, не лише високооціненим або останнім. Я не скаржуюся, пропоную свою критику, щоб дослідники з меншими знаннями могли краще зрозуміти різницю між цією відповіддю та іншими відповідями. Ви могли пояснити у своєму дописі, що це просто академічний виклик, щоб уникнути регулярного вираження. З огляду на це, існують способи зробити цей процес більш ефективним за допомогою кращої практики кодування.
— mickmackusa

0

Використовувати класи фільтру Zend Word Фільтри легко :

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

----- підкресленняToCamelCase -----

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


0

Бібліотека 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'

0
$str = 'FooBarBaz';

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

1
Відповіді, що стосуються лише коду, мають низьку цінність для StackOverflow, оскільки вони погано працюють із розширенням можливостей / навчанням майбутніх дослідників.
— mickmackusa

-1

ЯКЩО ви можете почати з:

$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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.