133

もしわたしが持っていたら:

$string = "PascalCase";

私は欲しい

"pascal_case"

PHPはこの目的のための機能を提供していますか?

4

32 に答える 32

173

これを試着してサイズを確認してください:

$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. 大文字で始まるシーケンスの後には、次のいずれかを続けることができます。
    • 1 つまたは複数の大文字と数字 (文字列の末尾または大文字の後に小文字または数字が続く、つまり次のシーケンスの開始); また
    • 1 つ以上の小文字または数字。
于 2010-01-03T02:45:58.407 に答える
43

簡潔な解決策であり、いくつかのトリッキーなユースケースを処理できます。

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

于 2016-03-01T09:54:36.877 に答える
24

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

preg_replace上記のソリューションで見逃された可能性のあるトリックの1つは、置換文字列をPHPコードとして評価する「e」修飾子です。

于 2011-03-04T13:40:41.040 に答える
22

ここでのほとんどのソリューションは、手荒に感じます。これが私が使用するものです:

$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 に変換されるのを回避します)
  • 2 番目のパターンと置換は for ThoseSPECCases->those_spec_casesではなくthose_speccases
  • strtolower([…])出力を小文字にします
于 2013-05-01T13:48:48.343 に答える
20

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"
于 2010-01-03T02:27:59.843 に答える
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_áááá_őőőő

文字列の大文字と小文字が不明な場合は、最初に確認することをお勧めします。このコードは、入力がorcamelCaseではなく、後者に大文字が含まれている場合はアンダースコアを追加することを前提としているためです。underscore_Casedash-Case

cletus から受け入れられた回答は複雑すぎて、ラテン文字でのみ機能します。私はそれが本当に悪い解決策だと思い、なぜそれが受け入れられたのか疑問に思っています。に変換TEST123Stringすることtest123_stringは、必ずしも有効な要件ではありません。このように情報が失われることはなく、逆方向の変換によって元の文字列とまったく同じ文字列が得られるため、代わりにシンプルにして分離ABCcccしました。他の方法でやりたい場合でも、正規表現の専門家でない場合は、肯定的な後読みまたは後読みなしの2つの正規表現を使用して正規表現を作成するのは比較的簡単です。それを部分文字列に分割する必要はなく、使用する場所と使用する場所を決定することは言うまでもなく、完全に問題ありません。a_b_ccccab_cccc(?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}strtolowerlcfirststrtolower

于 2012-05-23T19:45:23.117 に答える
7

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

} 
于 2015-02-25T23:20:03.790 に答える
7

同様の問題がありましたが、キャメルケースをスネークケースに変換する方法を満たす答えが見つかりませんでしたが、アンダースコア_のある名前の重複または冗長なアンダースコア、またはすべて大文字の略語を避けました。

問題は次のとおりです。

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

私が書いた解決策は、単純な 2 つの関数呼び出し、小文字と検索、および連続した小文字と大文字の置換です。

strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $name));
于 2019-09-07T10:57:04.923 に答える
5

短い解決策:

$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));
于 2019-06-12T11:01:34.297 に答える
3

danielstjules/ Stringy は、文字列をキャメルケースからスネークケースに変換する方法を提供します。

s('TestUCase')->underscored(); // 'test_u_case'
于 2016-11-29T12:35:27.860 に答える
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);
}
于 2010-01-03T03:58:20.663 に答える
2

これは、答えがいくつあるかは神のみぞ知るという 6 年前の質問に対する私の貢献です...

指定された文字列内のキャメルケースのすべての単語をスネークケースに変換します。たとえば、「SuperSpecialAwesome and also FizBuzz καιΚάτιΑκόμα」は、「super_special_awesome and also fizz_buzz και_κάτι_ακόμα」に変換されます。

mb_strtolower(
    preg_replace_callback(
        '/(?<!\b|_)\p{Lu}/u',
        function ($a) {
            return "_$a[0]";
        },
        'SuperSpecialAwesome'
    )
);
于 2016-12-28T15:17:55.697 に答える
1

ここでの最悪の答えは、最高に近いものでした(フレームワークを使用)。いいえ、しないでください。ソースコードを見てください。十分に確立されたフレームワークが使用するものを確認することは、はるかに信頼性の高いアプローチになります (試行およびテスト済み)。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");
于 2015-11-09T09:36:52.360 に答える
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);
}
于 2013-04-09T12:30:17.247 に答える
1

この機能を提供するライブラリがあります。

SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"
于 2016-04-02T01:04:31.200 に答える
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);
}
于 2013-12-05T05:01:44.643 に答える
1

Laravel フレームワークを使用している場合は、snake_case()メソッドのみを使用できます。

于 2016-11-11T16:25:48.130 に答える
1

これは、より短い方法の 1 つです。

function camel_to_snake($input)
{
    return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}
于 2019-02-15T13:12:34.210 に答える
0

Zend Word Filtersの Filter クラスを使用すると簡単です。

<?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 >>> シンプルテスト

簡単 >>> 簡単

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

TEST123文字列 >>> test123_string

于 2013-12-16T17:02:13.473 に答える
-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
于 2015-03-28T15:40:21.247 に答える