Wie konvertiere ich PascalCase in pascal_case?


Antworten:


163

Probieren Sie dies für die Größe an:

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

Ausgabe:

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

Dies implementiert die folgenden Regeln:

  1. Auf eine Sequenz, die mit einem Kleinbuchstaben beginnt, müssen Kleinbuchstaben und Ziffern folgen.
  2. Einer Sequenz, die mit einem Großbuchstaben beginnt, kann folgendermaßen folgen:
    • ein oder mehrere Großbuchstaben und Ziffern (gefolgt vom Ende der Zeichenfolge oder einem Großbuchstaben, gefolgt von einem Kleinbuchstaben oder einer Ziffer, dh dem Beginn der nächsten Sequenz); oder
    • ein oder mehrere Kleinbuchstaben oder Ziffern.

9
Es funktioniert für CamelCased-Zeichenfolgen (wie von openfrog gefragt), aber wenn Sie es mit einer Eingabezeichenfolge verwenden, z. B. "r_id" (bereits "unterstrichen"), wird das Präfix ("r_") gekürzt. Gute Lösung, aber definitiv nicht universell.
Martin

1
Neugierig, warum Sie prüfen, ob die Zeichenfolge mit der Zeichenfolge mit Großbuchstaben übereinstimmt? Was ist der Vorteil, wenn nur das erste Zeichen in Kleinbuchstaben konvertiert wird (im Gegensatz zu allen Zeichen)?
Josh

1
Eine präzisere
Syone

155

Eine kürzere Lösung: Ähnlich wie beim Editor mit einem vereinfachten regulären Ausdruck und der Behebung des Problems des "nachgestellten Unterstrichs":

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

PHP Demo | Regex Demo


Beachten Sie, dass Fälle wie SimpleXMLdie simple_x_m_lVerwendung der obigen Lösung konvertiert werden. Dies kann auch als falsche Verwendung der Kamelschreibweise (richtig wäre SimpleXml) und nicht als Fehler des Algorithmus angesehen werden, da solche Fälle immer mehrdeutig sind - selbst wenn Gruppen in Großbuchstaben zu einer Zeichenfolge gruppiert werden ( simple_xml), schlägt ein solcher Algorithmus in anderen Randfällen immer fehl Like- XMLHTMLConverteroder Ein-Buchstaben-Wörter in der Nähe von Abkürzungen usw. Wenn Sie sich nicht für die (eher seltenen) Randfälle interessieren und SimpleXMLrichtig damit umgehen möchten, können Sie eine etwas komplexere Lösung verwenden:

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

PHP Demo | Regex Demo


Fühlen Sie sich frei, die Antwort von cletus zu kommentieren, in der angegeben ist, welche Testfälle Sie behoben haben.
Mike B

3
Ich sage nicht, dass seine Lösung falsche Ergebnisse liefert. Seine Lösung ist nur äußerst kompliziert und ineffektiv.
Jan Jakeš

1
Ja, die Antwort ist definitiv ein Fehlschlag. Jan's Lösung ist großartig! Als Randnotiz denke ich, dass dies (oder eine geringfügige Abweichung) mein neuer, bevorzugter Codierungstest für PHP-Entwickler ist, da die Anzahl der Antworten auf diese Frage, die nicht wirklich funktionieren, unglaublich ist. Es wäre eine großartige Möglichkeit, die anfängliche Filterung durchzuführen. :-)
JamesG

fand den in dieser Lösung verwendeten regulären
Ausdruck

2
Gute Lösung für einfache Anwendungsfälle und in den meisten Fällen reicht es aus, aber die akzeptierte Lösung kann mehr Anwendungsfälle verarbeiten. Beispielsweise kann "simpleXML" in "simple_xml" und nicht in "simple_x_m_l"
konvertiert werden

35

Eine prägnante Lösung, die einige knifflige Anwendungsfälle bewältigen kann:

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

Kann alle diese Fälle behandeln:

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

Sie können diese Funktion hier testen: http://syframework.alwaysdata.net/decamelize


@VivekVardhan Welchen Teil dieser Regex verstehst du nicht?
Syone

Ähm, ich denke, dass das Verringern von Nicht-Camelcase-Zeichenfolgen ein Nebeneffekt ist, falls die Zeichenfolge nicht im Camelcase-Format vorliegt, sollte die ursprüngliche zurückgegeben werden. Wenn Sie 'simple_Text' senden, erhalten Sie Fail: simple_Test => simple_Test [simple_test]. Die Zeichenfolge in Kleinbuchstaben sollte nur erstellt werden, und wenn nur die ursprüngliche Zeichenfolge eine echte Kamelkastenzeichenfolge ist. Was denkst du über?
Guido

24

Portiert von Ruby's String#camelizeund 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); 
}

Ein Trick, den die oben genannten Lösungen möglicherweise übersehen haben, ist der Modifikator 'e', ​​der dazu führt preg_replace, dass die Ersatzzeichenfolge als PHP-Code ausgewertet wird.


10
Das eFlag für preg_replacewird in PHP 5.5 veraltet.
CDMckay

Übrigens sind diese auch nicht in Ruby, sondern in der Inflector-Bibliothek von Rails - Kamelisieren und Unterstreichen. api.rubyonrails.org/classes/ActiveSupport/Inflector.html
Mahemoff

2
Dies schlägt für "ThisIsATest" fehl. Scheint, dass zwei aufeinanderfolgende Großbuchstaben nicht unterstützt werden.
OnaBai

Nur eine Anmerkung: Sie können lcfirst verwenden, um den ersten Buchstaben in Kleinbuchstaben zu schreiben, dann brauchen Sie das ^|oder nicht strlen.
Benubird


23

Die Symfony Serializer-Komponente verfügt über einen CamelCaseToSnakeCaseNameConverter mit zwei Methoden normalize()und denormalize(). Diese können wie folgt verwendet werden:

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

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

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

1
In acht nehmen! $nameConverter->normalize('CamelCase')Ausgaben _camel_casein der aktuellen Version 3.2 der Symfony Serializer-Komponente.
Spackmat

21

Die meisten Lösungen hier fühlen sich schwerfällig an. Folgendes verwende ich:

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

"CamelCASE" wird in "camel_case" konvertiert

  • lcfirst($camelCase) verringert das erste Zeichen (vermeidet die konvertierte Ausgabe von 'CamelCASE', um mit einem Unterstrich zu beginnen)
  • [A-Z] findet Großbuchstaben
  • + behandelt jeden aufeinanderfolgenden Großbuchstaben als Wort (verhindert, dass 'CamelCASE' in camel_C_A_S_E konvertiert wird)
  • Zweites Muster und Ersatz sind für ThoseSPECCases-> those_spec_casesstattthose_speccases
  • strtolower([…]) Schaltet die Ausgabe in Kleinbuchstaben um

3
Aber es wird auch CamelCased zu _camel_cased.
Acme

1
Das ist großartig - fügen Sie einfach einen Teil ab Zeichen 1 hinzu, um dieses Problem zu umgehen.
Oddman

4
Hervorragend! Nur müssen hinzufügen lcfirstFunktion $ Camelcase
Edakos

Die akzeptierte Antwort lautet: TestUPSClass in test_ups_class, während dies in test_u_p_s_class umgewandelt wird, was zu beachten ist.
Mazzy

Eine Eingabezeichenfolge, die mit dem ersten "Wort" von allcaps beginnt, wird von dieser Lösung aufgrund des ucfirst()Aufrufs unerwartet aufgeteilt . USADollarSymbolwird u_sa_dollar_symbol Demo Ich empfehle diese Lösung nicht, da sie zwei Durchgänge mit Regex durch die Eingabezeichenfolge machen muss - ein Zeichen für ein nicht verfeinertes Muster.
Mickmackusa

19

PHP bietet keine eingebaute Funktion für diesen Afaik, aber hier ist, was ich benutze

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

}

Der Splitter kann im Funktionsaufruf angegeben werden, so dass Sie ihn so aufrufen können

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

2
Dies schlägt für "ThisIsATest" fehl. Scheint, dass zwei aufeinanderfolgende Großbuchstaben nicht unterstützt werden.
OnaBai

Sicher haben Sie etwas vergessen, da der zweite Ersatz nichts bewirkt. Abgesehen davon können Sie es einfach Unicode-kompatibel machen mb_strtolowerund die /uOption aktivieren preg_replace.
Bodo

8

Sie müssen einen regulären Ausdruck durchlaufen, der mit jedem Großbuchstaben übereinstimmt, außer wenn er am Anfang steht, und ihn durch einen Unterstrich plus diesen Buchstaben ersetzen. Eine utf-8-Lösung ist folgende:

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

Wenn Sie sich nicht sicher sind, in welchem ​​Fall sich Ihre Zeichenfolge befindet, überprüfen Sie sie besser zuerst, da dieser Code davon ausgeht, dass die Eingabe camelCaseanstelle von underscore_Caseoder erfolgtdash-Case erfolgt. Wenn die letzteren also Großbuchstaben enthalten, werden ihnen Unterstriche hinzugefügt.

Die akzeptierte Antwort von Cletus ist imho viel zu kompliziert und funktioniert nur mit lateinischen Zeichen. Ich finde es eine wirklich schlechte Lösung und frage mich, warum es überhaupt akzeptiert wurde. Die Konvertierung TEST123Stringin test123_stringist nicht unbedingt eine gültige Voraussetzung. Ich eher hielt es einfach und getrennt ABCcccin a_b_ccccstatt , ab_ccccweil es nicht verlieren Informationen auf diese Weise und die Rückkonvertierung wird genau die gleiche Zeichenfolge wir begannen mit geben. Selbst wenn Sie es anders machen möchten, ist es relativ einfach, eine Regex mit positivem Lookbehind (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}oder zwei Regexes ohne Lookbehind zu schreiben, wenn Sie kein Regex-Experte sind. Es besteht keine Notwendigkeit, es in Teilzeichenfolgen aufzuteilen, ganz zu schweigen von der Entscheidung, zwischen strtolowerund lcfirstwo die Verwendung nur strtolowervöllig in Ordnung wäre.


Nur-Code-Antworten sind für Stackoverflow von geringem Wert, da sie nur sehr wenig dazu beitragen, Tausende zukünftiger Forscher auszubilden / zu befähigen.
Mickmackusa

@mickmackusa Wenn Forscher lernen, wie man aus SO codiert, dann haben wir ein ernstes Problem ...
inf3rno

Nachdem Sie diesen persönlichen Angriff von Ihrem System erhalten haben, verbessern Sie bitte Ihre Antwort. Angenommen, Sie wissen, wie Ihre Lösung funktioniert und warum Sie diese Mustermodifikatoren verwenden, sehe ich keinen guten Grund, dieser Community Wissen vorzuenthalten. Für den Fall, dass Sie erwägen, mehr snarky Antworten zu hinterlassen, versichere ich Ihnen, dass sie mich nicht stören. In der Zeit, die Sie für einen Kommentar benötigt haben, hätten Sie Ihre Antwort vervollständigen können, wir hätten unsere Kommentare löschen können, und ich hätte woanders hingehen können, um dieser Site zu helfen.
Mickmackusa

Natürlich habe ich keine Berechtigung, einen Beitrag mit 8 Upvotes zu löschen. Wenn Sie möchten, können Sie Ihre Antwort löschen, aber es wäre nicht sehr schwierig, sie einfach zu verbessern, indem Sie unnötige Mustermodifikatoren entfernen und eine Erklärung hinzufügen. Die persönlichen Angriffe haben keinen Einfluss auf mich.
Mickmackusa

@mickmackusa Ich glaube nicht, dass ich es auch löschen kann. Fühlen Sie sich frei, es zu bearbeiten, wenn Sie möchten.
inf3rno

6

Wenn Sie nach einer PHP 5.4-Version suchen und später antworten, ist hier der Code:

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 produziere "SmsSent" für sms_sent, du brauchst ein erstes
mik3fly-4steri5k

4

Gar nichts Besonderes, aber einfach und schnell wie die Hölle:

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

++$ianstatt $i++würde es auch ein bisschen schneller machen;)
Mathieu Amiot

Nur-Code-Antworten sind für Stackoverflow von geringem Wert, da sie nur sehr wenig dazu beitragen, Tausende zukünftiger Forscher auszubilden / zu befähigen.
Mickmackusa

4

"CamelCase" bis "camel_case":

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

oder:

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

Danke dir. Ich habe den ersten Ansatz verwendet, aber mit Bindestrichen zu generierenthis-kind-of-output
thexpand

3

Eine Version, die keinen regulären Ausdruck verwendet, finden Sie in der Alchitect- Quelle:

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

1
So würde das Leben ohne Regex
aussehen

4
Heh, ja. RegEx hat definitiv seine Vorteile. :) Rohe Geschwindigkeit gehört nicht dazu.
Darrell Brogdon

habe aus irgendeinem Grund einige lustige Ergebnisse mit diesem
erzielt

Funktioniert nicht für mich basierend auf dieser Zeichenfolge: "CamelCaseTestAAATestAA", sollte haben: "camel_case_test_a_a_a_test_a_a", hat: "" camel_case_test_aest "...
Sybio

3

Also hier ist ein Einzeiler:

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

Schön, aber es konvertiert nur das erste Erscheinungsbild, daher würde ich empfehlen g, diesem regulären Ausdruck einen Modifikator hinzuzufügen .
Acme

@acme, ich benutze es ohne gund es funktioniert gut für mich.
Seelts

Aus irgendeinem Grund musste ich in meinem Fall das hinzufügen g. Aber ich kann mich nicht an den Satz erinnern, mit dem ich getestet habe.
Acme


3

Laravel 5.6 bietet eine sehr einfache Möglichkeit, dies zu tun:

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

Was es tut: Wenn es sieht, dass die angegebene Zeichenfolge mindestens einen Großbuchstaben enthält, verwendet es einen positiven Lookahead , um nach einem Zeichen ( .) zu suchen, gefolgt von einem Großbuchstaben ( (?=[A-Z])). Anschließend wird das gefundene Zeichen durch seinen Wert ersetzt, gefolgt vom Trennzeichen _.


Diese Funktion scheint nun snake_case () zu heißen und befindet sich im globalen Namespace.
Wotuu

2

Der direkte Port von Schienen (abzüglich ihrer speziellen Behandlung für :: oder Akronyme) wäre

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

Wenn Sie PHP kennen, ist dies schneller als das manuelle Parsen, das in anderen hier gegebenen Antworten durchgeführt wird. Der Nachteil ist, dass Sie nicht auswählen können, was als Trennzeichen zwischen Wörtern verwendet werden soll, aber das war nicht Teil der Frage.

Überprüfen Sie auch den entsprechenden Rails-Quellcode

Beachten Sie, dass dies für die Verwendung mit ASCII-Kennungen vorgesehen ist. Wenn Sie dies mit Zeichen außerhalb des ASCII-Bereichs tun müssen, verwenden Sie den Modifikator '/ u' für preg_matchund verwenden Sie mb_strtolower.


Sie könnten, wenn Sie einfach einen Parameter hinzufügen, der das gewünschte Zeichen enthält.
Fleischwolf

2

Hier ist mein Beitrag zu einer sechs Jahre alten Frage mit Gott weiß, wie viele Antworten ...

Es werden alle Wörter in der bereitgestellten Zeichenfolge, die sich in camelcase befinden, in snakecase konvertiert. Zum Beispiel wird "SuperSpecialAwesome und auch FizBuzz καιΚάτιΑκόμα" in "super_special_awesome und auch fizz_buzz και_κάτι_ακόμα" konvertiert.

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

2

Yii2 hat die unterschiedliche Funktion, das Wort snake_case aus CamelCase zu erstellen.

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

Kurze Lösung:

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

2

Ich hatte ein ähnliches Problem, konnte jedoch keine Antwort finden, die die Konvertierung von CamelCase in snake_case erfüllt, wobei doppelte oder redundante Unterstriche vermieden wurden _ für Namen mit Unterstrichen oder alle .

Das Problem ist wie folgt:

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

Die Lösung, die ich geschrieben habe, ist ein einfacher Aufruf mit zwei Funktionen: Kleinbuchstaben und Suchen und Ersetzen nach aufeinanderfolgenden Kleinbuchstaben in Großbuchstaben:

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

Dies ist bei weitem die prägnanteste und nützlichste Lösung IMO.
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);
}

Sie können direkt mit $name{$k}(oder $name[$k]) auf Zeichen zugreifen , wodurch Ihr Code länger wird, aber der große Aufwand für die Konvertierung in und aus einem Array vermieden wird.
Bodo

Nur-Code-Antworten sind für StackOverflow von geringem Wert, da sie zukünftige Forscher nur schlecht befähigen / ausbilden. Ihre Lösung vermeidet zwar die Anmut von Regex, ist jedoch sehr hartnäckig und verworren. Sie teilen jedes Zeichen auf und führen mehrere iterierte Funktionsaufrufe durch. Es ist nicht erforderlich, eine leere Schnur als Klebstoff zu benennen. Ich würde diese Lösung in einem meiner Projekte nicht in Betracht ziehen, da es keine Eleganz, geringe Lesbarkeit und n unnötige Funktionsaufrufe gibt.
Mickmackusa

1

Die schlechteste Antwort hier war so nah dran, die beste zu sein (benutze ein Framework). NEIN NICHT, schauen Sie sich einfach den Quellcode an. Zu sehen, was ein gut etabliertes Framework verwendet, wäre ein weitaus zuverlässigerer Ansatz (bewährt). Das Zend-Framework verfügt über einige Wortfilter, die Ihren Anforderungen entsprechen. Quelle .

Hier sind einige Methoden, die ich aus der Quelle angepasst habe.

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

Es gibt eine Bibliothek, die diese Funktionalität bietet:

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

1
Ich denke, Sie meinen "Ich habe eine Bibliothek erstellt, die diese Funktionalität bietet". An Eigenwerbung ist nichts auszusetzen, aber verstecken Sie sie nicht.
icc97


1

Dies ist eine der kürzeren Möglichkeiten:

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

Nur-Code-Antworten sind für Stackoverflow von geringem Wert, da sie nur sehr wenig dazu beitragen, Tausende zukünftiger Forscher auszubilden / zu befähigen.
Mickmackusa

1
@mickmackusa - Tausende von zukünftigen Forschungen werden sich für einen eleganten Einzeiler interessieren und sich selbst ausbilden.
Teson

Es tut mir leid, dass Sie diese egoistische Haltung eingenommen haben. Sie hätten sicherlich eine Erklärung in der Zeit hinzufügen können, die Sie für das Entwerfen und Eingeben dieser snarky Antwort benötigt haben. Ihre Antwort führt drei Funktionsaufrufe aus, andere führen die Aufgabe in zwei Schritten aus.
Mickmackusa

1

So entkamelisieren Sie ohne Regex:

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

Eine Bearbeitung:

Wie würde ich das 2019 machen:

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

Und wenn PHP 7.4 veröffentlicht wird:

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

1
Nur-Code-Antworten sind für StackOverflow von geringem Wert, da sie zukünftige Forscher nur schlecht befähigen / ausbilden. Das Ausführen von 1 bis 3 Funktionsaufrufen für jedes Zeichen in der Zeichenfolge und zwei weitere Funktionsaufrufe nach Abschluss der Schleife ist sehr schwierig. Ich würde keine Lösung mit solch einer schlechten Wirtschaft finden.
Mickmackusa

Es ist ein Beispiel dafür, wie es ohne die Verwendung regulärer Ausdrücke gemacht werden könnte, nicht wie es in der Produktion verwendet werden sollte. Ich verstehe Ihren Standpunkt nicht, außer dass Sie sich über eine 5-jährige Antwort beschweren, die eine positive Bewertung hat und von der es unwahrscheinlich ist, dass sie gesehen wird irgendwelche Forscher.
Baldrs

Ich widme mich allen Beiträgen, nicht nur den hoch bewerteten oder den jüngsten. Ich beschwere mich nicht, ich biete meine Kritik an, damit Forscher mit weniger Wissen den Unterschied zwischen dieser Antwort und anderen Antworten besser verstehen können. Sie hätten in Ihrem Beitrag erklären können, dass es lediglich eine akademische Herausforderung war, Regex zu vermeiden. Es gibt jedoch Möglichkeiten, diesen Prozess durch bessere Codierungspraktiken effizienter zu gestalten.
Mickmackusa

0

Mit den Filterklassen der Zend Word-Filter ist dies ganz einfach :

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

einfach >>> einfach

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

einfach >>> einfach

HTML >>> HTML

simpleXML >>> simple_xml

PDFLoad >>> pdf_load

startMIDDLELast >>> start_middle_last

AString >>> a_string

Some4Numbers234 >>> some4_numbers234

TEST123String >>> test123_string


0

Die Open-Source-TurboCommons-Bibliothek enthält eine universelle formatCase () -Methode innerhalb der StringUtils-Klasse, mit der Sie einen String in viele gängige Groß- und Kleinschreibung wie CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case und viele mehr konvertieren können.

https://github.com/edertone/TurboCommons

Um es zu verwenden, importieren Sie die Phar-Datei in Ihr Projekt und:

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
Nur-Code-Antworten sind für StackOverflow von geringem Wert, da sie zukünftige Forscher nur schlecht befähigen / ausbilden.
Mickmackusa

-1

WENN Sie beginnen könnten mit:

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

Dann könnten Sie in beide Fälle konvertieren, nur mit:

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

Oder andere Fälle:

$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string);               // CAMEL_CASE
$train = str_replace("_", "-", $snake);        // camel-case
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.