PascalCase'i pascal_case'e nasıl dönüştürebilirim?


Yanıtlar:


163

Bunu boyut için deneyin:

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

Çıktı:

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

Bu, aşağıdaki kuralları uygular:

  1. Küçük harfle başlayan bir dizinin ardından küçük harfler ve rakamlar gelmelidir;
  2. Büyük harfle başlayan bir diziden sonra şunlardan biri gelebilir:
    • bir veya daha fazla büyük harf ve rakam (ardından dizinin sonu veya büyük harf ve ardından küçük harf veya rakam, yani sonraki dizinin başlangıcı); veya
    • bir veya daha fazla küçük harf veya rakam.

9
CamelCased dizeleri için çalışır (openfrog'un sorduğu gibi), ancak eğer onu örneğin "r_id" (zaten "altı çizili") gibi girdi dizgisiyle kullanırsanız, öneki ("r_") keser. İyi çözüm, ama kesinlikle evrensel değil.
Martin

1
Dizenin tüm büyük harf dizesiyle eşleşip eşleşmediğini neden kontrol ettiğinizi merak ediyor musunuz? Yalnızca ilk karakteri küçük harfe dönüştürmenin (tüm karakterlerin aksine) faydası nedir?
Josh

1
Tüm bu kullanım durumlarının üstesinden gelebilecek daha kısa bir çözüm: stackoverflow.com/a/35719689/4328383
Syone

156

Daha kısa bir çözüm: Düzenleyicinin basitleştirilmiş bir normal ifadeye sahip olana benzer ve "sondaki alt çizgi" sorununu düzeltir:

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

PHP Demosu | Regex Demosu


Bu gibi durumların yukarıdaki çözüme SimpleXMLdönüştürüleceğini unutmayın simple_x_m_l. Bu SimpleXml, algoritmanın bir hatası yerine deve büyük / küçük harf gösteriminin yanlış kullanımı olarak da düşünülebilir (doğru olacaktır ) çünkü bu tür durumlar her zaman belirsizdir - büyük harfli karakterleri bir dizede gruplandırmakla bile ( simple_xml) bu tür algoritma diğer uç durumlarda her zaman başarısız olur. XMLHTMLConverterkısaltmaların yanında benzer veya tek harfli kelimeler, vb. (Oldukça nadir) uç durumları önemsemiyorsanız ve SimpleXMLdoğru şekilde ele almak istiyorsanız, biraz daha karmaşık bir çözüm kullanabilirsiniz:

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

PHP Demosu | Regex Demosu


Hangi test durumlarını düzelttiğinizi detaylandıran cletus'un cevabı hakkında yorum yapmaktan çekinmeyin.
Mike B

3
Çözümünün yanlış sonuçlar verdiğini söylemiyorum. Çözümü son derece karmaşık ve etkisiz.
Jan Jakeš

1
Evet, kabul et cevabı kesinlikle başarısız. Jan'ın çözümü harika! Bir yan not olarak, bunun (veya küçük bir varyasyonun) PHP geliştiricileri için yeni, favori kodlama testim olduğunu düşünüyorum, çünkü bu soruya verilen yanıtların sayısı gerçekten işe yaramıyor. İlk filtrelemeyi yapmanın harika bir yolu olacaktır. :-)
JamesG

bu çözümde kullanılan normal
ifadeyi

2
Basit kullanım durumları için güzel bir çözüm ve çoğu zaman yeterlidir, ancak kabul edilen çözüm daha fazla kullanım durumunun üstesinden gelebilir, örneğin "simpleXML", "simple_x_m_l" yerine "simple_xml" dönüştürülebilir
Syone

35

Kısa bir çözümdür ve bazı zorlu kullanım durumlarının üstesinden gelebilir:

function decamelize($string) {
    return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}

Tüm bu durumların üstesinden gelebilir:

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

Bu işlevi burada test edebilirsiniz : http://syframework.alwaysdata.net/decamelize


@VivekVardhan Bu regex'in hangi kısmını anlamıyorsun?
2016

Uhm, deve harfli olmayan dizeleri küçültmenin bir yan etki olduğunu düşünüyorum, eğer dizge deve kasa formatında değilse orijinali döndürülmelidir. Infact eğer 'basit_Metni' gönderirseniz Başarısız olur: basit_Test => basit_Test [basit_test]. Küçük harfli dizi yalnızca ve yalnızca orijinal dizi gerçek bir deve harf dizesi ise yapılmalıdır. Ne hakkında düşünüyorsun?
guido

24

Ruby'nin String#camelizeve 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); 
}

Yukarıdaki çözümlerin kaçırmış olabileceği bir numara, preg_replacedeğiştirme dizesinin PHP kodu olarak değerlendirilmesine neden olan 'e' değiştiricisidir .


10
İçin ebayrağı preg_replacePHP 5.5'te kullanımdan kaldırılıyor.
cdmckay

BTW bunlar da Ruby'de değil, ancak Rails'in çekim kitaplığında - deve ve alt çizgi. api.rubyonrails.org/classes/ActiveSupport/Inflector.html
mahemoff

2
Bu, "ThisIsATest" için başarısız olur. Arka arkaya iki büyük harfi desteklemiyor gibi görünüyor.
OnaBai

Sadece bir not: lcfirst kullanarak ilk harfi küçük harfe çevirebilirsiniz, o zaman ^|veya strlen.
Benubird

kullanımdan kaldırılmadan decamelize
scones

23

Symfony serileştiricisi Bileşeni bir sahiptir CamelCaseToSnakeCaseNameConverter iki yöntem vardır normalize()ve denormalize(). Bunlar şu şekilde kullanılabilir:

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

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

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

1
Dikkat! Symfony Serializer Bileşeninin 3.2 sürümünde $nameConverter->normalize('CamelCase')çıktılar _camel_case.
spackmat

21

Buradaki çoğu çözümün eli ağır geliyor. İşte kullandığım şey:

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

"CamelCASE", "camel_case" biçimine dönüştürülür

  • lcfirst($camelCase) ilk karakteri düşürür ('CamelCASE' dönüştürülmüş çıktının alt çizgiyle başlamasını önler)
  • [A-Z] büyük harfleri bulur
  • + ardışık her büyük harfe bir kelime olarak davranır ('CamelCASE'in camel_C_A_S_E'ye dönüştürülmesini önler)
  • İkinci kalıp ve değiştirme için ThoseSPECCases-> those_spec_casesyerinethose_speccases
  • strtolower([…]) çıkışı küçük harflere çevirir

3
Ama aynı zamanda CamelCased'i _camel_cased'e çeviriyor.
acme

1
bu harika - bu sorunu aşmak için char 1'den başlayan bir substrat eklemeniz yeterli.
Oddman

4
Mükemmel! lcfirst$
CamelCase'e

Kabul edilen cevap: TestUPSClass'ı test_ups_class'a işleyecektir, bu ise onu test_u_p_s_class'a çevirecek, akılda tutulması gereken bir şey.
Mazzy

Bir allcaps ilk "kelime" ile başlayan bir girdi dizesi, ucfirst()çağrı nedeniyle bu çözüm tarafından beklenmedik bir şekilde bölünecektir . DemoUSADollarSymbol oluyor Bu çözümü önermiyorum çünkü girdi dizgisinden regex ile iki geçiş yapması gerekiyor - rafine edilmemiş bir modelin işareti. u_sa_dollar_symbol
mickmackusa

19

php bu afaik için yerleşik bir işlev sunmuyor, ama işte kullandığım şey

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

}

ayırıcı işlev çağrısında belirtilebilir, böylece onu böyle çağırabilirsiniz

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

2
Bu, "ThisIsATest" için başarısız olur. Arka arkaya iki büyük harfi desteklemiyor gibi görünüyor.
OnaBai

İkinci yedek hiçbir şey yapmadığı için kesinlikle bir şeyi unutmuşsunuzdur. Bunun dışında unicode ile uyumlu mb_strtolowerve açık /useçeneği ile kolayca yapabilirsiniz preg_replace.
bodo

8

Başında olması dışında her büyük harfle eşleşen bir normal ifade çalıştırmanız ve onu alt çizgi artı o harfle değiştirmeniz gerekir. Bir utf-8 çözümü şudur:

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

Dizenizin hangi durumda olduğundan emin değilseniz, önce kontrol etmeniz daha iyi olur, çünkü bu kod girdinin veya camelCaseyerine olduğunu varsayar , bu nedenle sonların büyük harfleri varsa bunlara alt çizgi ekleyecektir.underscore_Casedash-Case

Cletus'tan kabul edilen cevap çok fazla karmaşık bir imho'dur ve sadece latin karakterlerle işe yarar. Bunu gerçekten kötü bir çözüm buluyorum ve neden kabul edildiğini merak ediyorum. TEST123Stringİçine dönüştürme test123_stringmutlaka geçerli bir gereklilik değildir. Daha doğrusu basit tutulması ve ayrılmış ABCccciçine a_b_ccccyerine ab_ccccdeğil kaybetmek Bu şekilde bilgi yapar ve geriye dönüşüm başladığımız aynı dizeyi verir çünkü. Bunu başka bir şekilde yapmak isteseniz bile, (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}bir normal ifade uzmanı değilseniz, arkasına pozitif bakmadan veya iki normal ifadeyle bir normal ifade yazmak görece kolaydır . Kullanmanın tamamen iyi olacağı arasında strtolowerve lcfirstnerede karar vereceğinden bahsetmeye gerek yok, onu alt dizelere ayırmaya gerek yok strtolower.


Yalnızca kod yanıtları Stackoverflow'da düşük değerlidir çünkü gelecekteki binlerce araştırmacıyı eğitmek / güçlendirmek için çok az şey yaparlar.
mickmackusa

@mickmackusa Araştırmacılar SO'dan kod yazmayı öğrenirlerse, ciddi bir sorunumuz var demektir ...
inf3rno

Artık sisteminizden bu kişisel saldırıyı aldığınıza göre, lütfen yanıtınızı geliştirin. Çözümünüzün nasıl çalıştığını ve neden bu model değiştiricileri kullandığınızı bildiğinizi varsayarsak, bu topluluktan bilgi saklamak için iyi bir neden göremiyorum. Daha keskin yanıtlar bırakmayı düşünüyorsanız, beni rahatsız etmediklerini sizi temin ederim. Yorum yapmak için ayırdığınız zaman içinde cevabınızı tamamlayabilirdiniz, yorumlarımızı silebilirdik ve bu siteye yardım etmek için başka bir yere gidebilirdim.
mickmackusa

Tabii ki, 8 olumlu oy içeren bir yayını silme yetkim yok. İsterseniz cevabınızı silebilirsiniz, ancak gereksiz kalıp değiştiricilerini kaldırıp bir açıklama ekleyerek basitçe iyileştirmek çok zor olmaz. Kişisel saldırıların benim üzerimde hiçbir etkisi yok.
mickmackusa

@mickmackusa Ben de silebileceğimi sanmıyorum. İsterseniz düzenlemekten çekinmeyin.
inf3rno

6

Bir PHP 5.4 sürümü ve daha sonraki bir sürümü arıyorsanız, kod şu şekildedir:

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 sms_sent için "SmsSent" üretir, bir lcfirst'e ihtiyacınız var
mik3fly-4steri5k

4

Hiç de fantezi değil ama cehennem kadar basit ve hızlı:

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

++$iyerine $i++biraz daha hızlı hale getirirdi;)
Mathieu Amiot

Yalnızca kod yanıtları Stackoverflow'da düşük değerlidir çünkü gelecekteki binlerce araştırmacıyı eğitmek / güçlendirmek için çok az şey yaparlar.
mickmackusa

4

"CamelCase" ile "camel_case":

function camelToSnake($camel)
{
    $snake = preg_replace('/[A-Z]/', '_$0', $camel);
    $snake = strtolower($snake);
    $snake = ltrim($snake, '_');
    return $snake;
}

veya:

function camelToSnake($camel)
{
    $snake = preg_replace_callback('/[A-Z]/', function ($match){
        return '_' . strtolower($match[0]);
    }, $camel);
    return ltrim($snake, '_');
}

Teşekkür ederim. İlk yaklaşımı kullandım, ancak oluşturmak için kısa çizgilerlethis-kind-of-output
thexpand

3

Regex kullanmayan bir sürüm Alchitect kaynağında bulunabilir:

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


4
Heh, evet. RegEx'in kesinlikle avantajları vardır. :) Ham hız bunlardan biri değil.
Darrell Brogdon


Şu dizeye dayalı olarak benim için çalışmıyor: "CamelCaseTestAAATestAA", sahip olması gereken: "camel_case_test_a_a_a_test_a_a", sahip: "" camel_case_test_aest "...
Sybio,

3

İşte tek satırlık:

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

Güzel, ancak yalnızca ilk görünümü dönüştürüyor, bu nedenle gbu regex'e bir değiştirici eklemenizi öneririm .
acme

@acme, kullanmıyorum gve benim için iyi çalışıyor.
seelts

Nedense benim durumumda g. Ama test ettiğim ifadeyi hatırlayamıyorum.
acme


3

Laravel 5.6, bunu yapmanın çok basit bir yolunu sağlar:

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

Ne yapar: Verilen dizede en az bir büyük harf olduğunu görürse, herhangi bir karakteri ( ) ve ardından bir büyük harfi ( ) aramak için pozitif bir ilerleme kullanır . Ardından bulunan karakteri değeriyle ve ardından ayırıcıyla değiştirir ..(?=[A-Z])_


Bu işlev artık snake_case () olarak adlandırılıyor gibi görünüyor ve küresel isim alanında yaşıyor.
Wotuu

2

Raylardan doğrudan bağlantı noktası (:: veya kısaltmalar için özel kullanımları hariç)

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'yi bilmek, burada verilen diğer cevaplarda meydana gelen manuel çözümlemeden daha hızlı olacaktır. Dezavantajı, kelimeler arasında ayırıcı olarak neyi kullanacağınızı seçememenizdir, ancak bu sorunun bir parçası değildi.

Ayrıca ilgili rayların kaynak kodunu kontrol edin

Bunun ASCII tanımlayıcılarla kullanılmak üzere tasarlandığını unutmayın. Bunu ASCII aralığı dışındaki karakterlerle yapmanız gerekiyorsa, '/ u' değiştiricisini preg_matchkullanın ve kullanın mb_strtolower.


İstenen karakteri içeren bir parametre eklerseniz, bunu yapabilirsiniz.
Fleshgrinder

2

İşte tanrı bilir altı yaşındaki bir soruya katkım kaç cevaptır ...

Sağlanan dizedeki deve harfli tüm kelimeleri yılan kılıfına dönüştürür. Örneğin "SuperSpecialAwesome ve ayrıca FizBuzz καιΚάτιΑκόμα", "super_special_awesome ve ayrıca fizz_buzz και_κάτι_ακόμα" biçimine dönüştürülecektir.

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

2

Yii2, snake_case kelimesini CamelCase'den yapmak için farklı bir işleve sahiptir.

    /**
     * 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

Kısa çözüm:

$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));

2

Benzer bir sorun yaşadım, ancak alt _çizgi veya tümü büyük harf kısaltmaları olan adlar için yinelenen veya gereksiz alt çizgilerden kaçınırken, CamelCase'i snake_case'e nasıl dönüştüreceğimi tatmin eden bir yanıt bulamadım .

Sorun şu şekildedir:

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

Yazdığım çözüm basit bir iki işlev çağrısı, küçük harf ve ardışık küçük-büyük harfler için arama ve değiştirme:

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

Bu, açık ara en özlü ve kullanışlı çözüm IMO'dur.
Bay Shan 0

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

Karakterlere doğrudan $name{$k}(veya $name[$k]) kullanarak erişebilirsiniz , bu kodunuzu daha uzun hale getirir, ancak bir diziye ve diziden dönüştürmenin büyük ek yükünü önler.
bodo

Yalnızca kod yanıtları, StackOverflow'da düşük değerlidir çünkü gelecekteki araştırmacıları güçlendirmek / eğitmek konusunda kötü bir iş çıkarırlar. Çözümünüz, normal ifadenin zarafetinden kaçınırken, çok ağır ve karmaşıktır. Her karaktere bölünüyorsunuz ve birden çok yinelenen işlev çağrısı yapıyorsunuz. Tutkal olarak boş bir dizgiyi aday göstermek gereksizdir. Bu çözümü projelerimden birinde eğlendirmezdim çünkü zarafet, düşük okunabilirlik ve n sayıda gereksiz fonksiyon çağrısı yok.
mickmackusa

1

Buradaki en kötü cevap, en iyi olmaya çok yakındı (bir çerçeve kullanın). HAYIR YAPMAYIN, sadece kaynak koduna bir göz atın. İyi kurulmuş bir çerçevenin ne kullandığını görmek çok daha güvenilir bir yaklaşım olacaktır (denenmiş ve test edilmiş). Zend çerçevesi, ihtiyaçlarınıza uyan bazı kelime filtrelerine sahiptir. Kaynak .

İşte kaynaktan uyarladığım birkaç yöntem.

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

Bu işlevi sağlayan bir kitaplık var :

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

1
Sanırım "Bu işlevi sağlayan bir kitaplık oluşturdum" demek istiyorsunuz. Kendini tanıtmada yanlış bir şey yok, ama saklamayın.
icc97


1

Bu, daha kısa yollardan biridir:

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

Yalnızca kod yanıtları Stackoverflow'da düşük değerlidir çünkü gelecekteki binlerce araştırmacıyı eğitmek / güçlendirmek için çok az şey yaparlar.
mickmackusa

1
@mickmackusa - Gelecekteki binlerce araştırma, tek satırlık zarafetle ilgilenecek ve kendilerini eğitecek.
Teson

Bu bencil tavrı aldığın için üzgünüm. Bu keskin cevabı tasarlamanız ve yazmanız için geçen süre içinde kesinlikle bir açıklama ekleyebilirdiniz. Cevabınız üç işlev çağrısı yapar, ancak diğerleri görevi ikide gerçekleştirir.
mickmackusa

1

Normal ifade kullanmadan nasıl deveden arındırılır:

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

Bir düzenleme:

Bunu 2019'da nasıl yaparım:

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

Ve PHP 7.4 piyasaya çıktığında:

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

1
Yalnızca kod yanıtları, StackOverflow'da düşük değerlidir çünkü gelecekteki araştırmacıları güçlendirmek / eğitmek konusunda kötü bir iş çıkarırlar. Dizedeki her karakter için 1 ila 3 işlev çağrısı yapmak, ardından döngü tamamlandıktan sonra iki işlev çağrısı daha yapmak çok ağırdır. Bu kadar zayıf ekonomiye sahip bir çözümü ağırlamazdım.
mickmackusa

Bu, üretimde nasıl kullanılması gerektiğinden değil, normal ifadeler kullanılmadan nasıl yapılabileceğine bir örnektir, bu nedenle, bir olumlu oy içeren ve muhtemelen görülmesi muhtemel olmayan 5y / o cevabından şikayet etmenizin yanı sıra amacınızı göremiyorum. herhangi bir araştırmacı.
keller

Dikkatimi yalnızca yüksek oy alanlara veya yeni gönderilere değil, tüm gönderilere veriyorum. Şikayet etmiyorum, daha az bilgiye sahip araştırmacıların bu cevapla diğer cevaplar arasındaki farkı daha iyi anlayabilmesi için eleştirimi sunuyorum. Yazınızda, normal ifadeden kaçınmanın sadece akademik bir zorluk olduğunu açıklayabilirdiniz. Bununla birlikte, daha iyi kodlama uygulamalarıyla bu süreci daha verimli hale getirmenin yolları vardır.
mickmackusa

0

Zend Kelime Filtrelerinin Filtre sınıflarını kullanmak kolaydır :

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

kolay >>> Kolay

html >>> Html

simple_xml >>> SimpleXml

pdf_load >>> PdfLoad

start_middle_last >>> StartMiddleLast

a_string >>> AString

some4_numbers234 >>> Some4Numbers234

test123_string >>> Test123String

----- ----- camelCaseToUnderscore

simpleTest >>> basit_test

kolay >>> kolay

HTML >>> html

simpleXML >>> basit_xml

PDFLoad >>> pdf_load

startMIDDLELast >>> start_middle_last

AString >>> a_string

Some4Numbers234 >>> some4_numbers234

TEST123String >>> test123_string


0

Açık kaynak TurboCommons kitaplığı, StringUtils sınıfı içinde genel amaçlı bir formatCase () yöntemi içerir; bu, bir dizeyi CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case ve daha pek çok yaygın durum biçimine dönüştürmenize olanak tanır.

https://github.com/edertone/TurboCommons

Kullanmak için, phar dosyasını projenize aktarın ve:

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
Yalnızca kod yanıtları, StackOverflow'da düşük değerlidir çünkü gelecekteki araştırmacıları güçlendirmek / eğitmek konusunda kötü bir iş çıkarırlar.
mickmackusa

-1

Şununla başlayabilirsen:

$string = 'Camel_Case'; // underscore or any other separator...

O zaman sadece şununla her iki duruma da dönüştürebilirsiniz:

$pascal = str_replace("_", "", $string);
$snake = strtolower($string);

Veya diğer durumlar:

$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string);               // CAMEL_CASE
$train = str_replace("_", "-", $snake);        // camel-case
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.