¿Cómo convertir PascalCase a pascal_case?


Respuestas:


163

Pruébate esto para ver el tamaño:

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

Salida:

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

Esto implementa las siguientes reglas:

  1. Una secuencia que comience con una letra minúscula debe ir seguida de letras minúsculas y dígitos;
  2. Una secuencia que comienza con una letra mayúscula puede ir seguida de:
    • una o más letras mayúsculas y dígitos (seguidos del final de la cadena o una letra mayúscula seguida de una letra minúscula o un dígito, es decir, el comienzo de la siguiente secuencia); o
    • una o más letras minúsculas o dígitos.

9
Funciona para cadenas CamelCased (como pedía openfrog), pero si lo usa con una cadena de entrada, por ejemplo, "r_id" (ya "subrayado"), recorta el prefijo ("r_"). Buena solución, pero definitivamente no universal.
Martin

1
¿Tiene curiosidad por saber por qué está comprobando si la cadena coincide con la cadena en mayúsculas? ¿Cuál es el beneficio de convertir solo el primer carácter a minúsculas (a diferencia de todos los caracteres)?
Josh

1
Una solución más concisa que también puede manejar todos estos casos de uso: stackoverflow.com/a/35719689/4328383
Syone

156

Una solución más corta: similar a la del editor con una expresión regular simplificada y solucionando el problema de "guión bajo al final":

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

Demostración de PHP | Demostración de expresiones regulares


Tenga en cuenta que los casos como SimpleXMLse convertirán para simple_x_m_lusar la solución anterior. Eso también puede considerarse un uso incorrecto de la notación de mayúsculas y minúsculas (lo correcto sería SimpleXml) en lugar de un error del algoritmo, ya que tales casos son siempre ambiguos, incluso al agrupar caracteres en mayúscula en una cadena ( simple_xml), dicho algoritmo siempre fallará en otros casos de borde. me gusta XMLHTMLConvertero palabras de una letra cerca de abreviaturas, etc. Si no le importan los casos extremos (bastante raros) y desea manejarlos SimpleXMLcorrectamente, puede usar una solución un poco más compleja:

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

Demostración de PHP | Demostración de expresiones regulares


Siéntase libre de comentar sobre la respuesta de cletus que detalla qué casos de prueba solucionó.
Mike B

3
No digo que su solución dé resultados incorrectos. Su solución es extremadamente complicada e ineficaz.
Jan Jakeš

1
Sí, la respuesta de aceptar es definitivamente un fracaso. ¡La solución de Jan es increíble! Como nota al margen, creo que esta (o una ligera variación) es mi nueva prueba de codificación favorita para los desarrolladores de PHP, porque la cantidad de respuestas proporcionadas a esta pregunta que en realidad no funcionan es increíble. Sería una excelente manera de realizar el filtrado inicial. :-)
JamesG

Encontré la expresión regular utilizada en esta solución mucho más completa: stackoverflow.com/questions/2559759/…
thoroc

2
Buena solución para casos de uso simples y en la mayoría de los casos es suficiente, pero la solución aceptada puede manejar más casos de uso, por ejemplo, "simpleXML" puede convertirse a "simple_xml" y no a "simple_x_m_l"
Syone

35

Una solución concisa que puede manejar algunos casos de uso complicados:

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

Puede manejar todos estos casos:

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

Puede probar esta función aquí: http://syframework.alwaysdata.net/decamelize


@VivekVardhan, ¿qué parte de esta expresión regular no entiendes?
Syone

Uhm, creo que las cadenas en minúsculas que no sean camelcase es un efecto secundario, en caso de que la cadena no esté en formato camel case, se debe devolver la original. De hecho, si envía 'simple_Text' obtendrá Fail: simple_Test => simple_Test [simple_test]. La cadena en minúsculas debe hacerse solo y si solo la cadena original es una cadena de caja de camello real. ¿Qué piensa usted acerca de?
guido

24

Portado de Ruby's String#camelizey 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); 
}

Un truco que las soluciones anteriores pueden haber pasado por alto es el modificador 'e' que hace preg_replaceque se evalúe la cadena de reemplazo como código PHP.


10
La ebandera para preg_replaceestá en desuso en PHP 5.5.
cdmckay

Por cierto, estos tampoco están en Ruby, sino en la biblioteca de inflectores de Rails: camelize y subrayado. api.rubyonrails.org/classes/ActiveSupport/Inflector.html
mahemoff

2
Esto falla para "ThisIsATest". Parece que no admite dos mayúsculas consecutivas.
OnaBai

Solo una nota: puede usar lcfirst para poner la primera letra en minúsculas, entonces no necesita la ^|o strlen.
Benubird


23

El componente de serializador de Symfony tiene un CamelCaseToSnakeCaseNameConverter que tiene dos métodos normalize()y denormalize(). Estos se pueden utilizar de la siguiente manera:

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

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

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

1
¡Tener cuidado! $nameConverter->normalize('CamelCase')salidas _camel_caseen la versión 3.2 actual del componente de serializador de Symfony.
spackmat

21

La mayoría de las soluciones aquí se sienten torpes. Esto es lo que uso:

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

"CamelCASE" se convierte en "camel_case"

  • lcfirst($camelCase) bajará el primer carácter (evita que la salida convertida 'CamelCASE' comience con un guión bajo)
  • [A-Z] encuentra letras mayúsculas
  • + tratará cada mayúscula consecutiva como una palabra (evita que 'CamelCASE' se convierta en camel_C_A_S_E)
  • El segundo patrón y reemplazo son para ThoseSPECCases-> en those_spec_caseslugar dethose_speccases
  • strtolower([…]) convierte la salida en minúsculas

3
Pero también convierte CamelCased en _camel_cased.
acme

1
esto es genial, simplemente agregue una subcadena que comience en el carácter 1 para solucionar ese problema.
Oddman

4
¡Excelente! Solo necesito agregar una lcfirstfunción a $ camelCase
Edakos

La respuesta aceptada manejará: TestUPSClass en test_ups_class mientras que esto lo convertirá en test_u_p_s_class, algo a tener en cuenta.
Mazzy

Esta solución dividirá inesperadamente una cadena de entrada que comience con una primera "palabra" en mayúsculas debido a la ucfirst()llamada. USADollarSymbolse convierte en u_sa_dollar_symbol demostración No recomiendo esta solución porque tiene que hacer dos pasadas a través de la cadena de entrada con expresiones regulares, un signo de un patrón sin refinar.
mickmackusa

19

php no ofrece una función incorporada para este afaik, pero esto es lo que uso

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

}

el divisor se puede especificar en la llamada a la función, por lo que puede llamarlo así

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

2
Esto falla para "ThisIsATest". Parece que no admite dos mayúsculas consecutivas.
OnaBai

Seguro que olvidaste algo ya que el segundo reemplazo no hace nada. Aparte de esto, puede hacer que sea compatible con Unicode mb_strtolowery la /uopción activada preg_replace.
bodo

8

Debe ejecutar una expresión regular que coincida con todas las letras mayúsculas, excepto si está al principio, y reemplazarla con un subrayado más esa letra. Una solución utf-8 es esta:

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

Si no está seguro de qué caso es su cadena, es mejor verificarla primero, porque este código asume que la entrada es en camelCaselugar de underscore_Caseodash-Case , por lo que si las últimas tienen letras mayúsculas, les agregará guiones bajos.

La respuesta aceptada de cletus es demasiado complicada en mi humilde opinión y funciona solo con caracteres latinos. Me parece una solución realmente mala y me pregunto por qué fue aceptada. Convertir TEST123Stringen test123_stringno es necesariamente un requisito válido. Preferí mantenerlo simple y separado ABCcccen a_b_cccclugar de ab_ccccporque no pierde información de esta manera y la conversión hacia atrás dará exactamente la misma cadena con la que comenzamos. Incluso si desea hacerlo de la otra manera, es relativamente fácil escribir una expresión regular con una mirada atrás positiva (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}o dos expresiones regulares sin mirar atrás si no es un experto en expresiones regulares. No hay necesidad de dividirlo en subcadenas sin mencionar decidir entre strtolowery lcfirstdónde usarlo strtolowerestaría completamente bien.


Las respuestas de solo código tienen poco valor en Stackoverflow porque hacen muy poco para educar / capacitar a miles de futuros investigadores.
mickmackusa

@mickmackusa Si los investigadores aprenden a codificar desde SO, entonces tenemos un problema serio ...
inf3rno

Ahora que eliminó ese ataque personal de su sistema, mejore su respuesta. Suponiendo que sabe cómo funciona su solución y por qué está utilizando esos modificadores de patrones, no veo ninguna buena razón para ocultar su conocimiento a esta comunidad. En caso de que estés pensando en dejar respuestas más sarcásticas, te aseguro que no me molestan. En el tiempo que se tomó para comentar, podría haber completado su respuesta, podríamos haber eliminado nuestros comentarios y podría haber ido a otra parte para ayudar a este sitio.
mickmackusa

Por supuesto, no tengo autoridad para eliminar una publicación con 8 votos a favor. Si lo desea, puede eliminar su respuesta, pero no sería muy difícil simplemente mejorarla eliminando modificadores de patrones innecesarios y agregando una explicación. Los ataques personales no me afectan.
mickmackusa

@mickmackusa No creo que pueda eliminarlo tampoco. Siéntase libre de editarlo si lo desea.
inf3rno

6

Si está buscando una versión de PHP 5.4 y una respuesta posterior, aquí está el código:

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" para sms_sent, necesitas un lcfirst
mik3fly-4steri5k

4

No es nada sofisticado, pero es simple y rápido como el infierno:

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

++$ien lugar de $i++lo haría un poco más rápido también;)
Mathieu Amiot

Las respuestas de solo código tienen poco valor en Stackoverflow porque hacen muy poco para educar / capacitar a miles de futuros investigadores.
mickmackusa

4

"CamelCase" a "camel_case":

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

o:

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

Gracias. this-kind-of-output
Usé

3

Se puede encontrar una versión que no usa expresiones regulares en la fuente de 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);
}

1
Así sería la vida sin
expresiones

4
Je, sí. La expresión regular definitivamente tiene sus ventajas. :) La velocidad bruta no es uno de ellos.
Darrell Brogdon

obtuve algunos resultados divertidos con este por alguna razón
mr1031011

No me funciona según esta cadena: "CamelCaseTestAAATestAA", debería tener: "camel_case_test_a_a_a_test_a_a", tiene: "" camel_case_test_aest "...
Sybio

3

Así que aquí hay una sola línea:

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

Bien, pero solo convierte la primera aparición, por lo que recomendaría agregar un gmodificador a esta expresión regular.
acme

@acme, lo uso sin gél y funciona bien para mí.
cierra el

Por alguna razón en mi caso tuve que agregar el g. Pero no recuerdo la frase con la que probé.
acme


3

Laravel 5.6 proporciona una forma muy sencilla de hacer esto:

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

Qué hace: si ve que hay al menos una letra mayúscula en la cadena dada, usa una búsqueda anticipada positiva para buscar cualquier carácter ( .) seguido de una letra mayúscula ( (?=[A-Z])). Luego reemplaza el carácter encontrado con su valor seguido por el separador _.


Esta función ahora parece llamarse snake_case () y vive en el espacio de nombres global.
Wotuu

2

El puerto directo desde rieles (menos su manejo especial para :: o siglas) sería

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

Conociendo PHP, esto será más rápido que el análisis manual que está sucediendo en otras respuestas dadas aquí. La desventaja es que no puedes elegir qué usar como separador entre palabras, pero eso no era parte de la pregunta.

También verifique el código fuente de rieles relevante

Tenga en cuenta que está diseñado para su uso con identificadores ASCII. Si necesita hacer esto con caracteres fuera del rango ASCII, use el modificador '/ u' para preg_matchy use mb_strtolower.


Podría, si simplemente agrega un parámetro que contiene el carácter deseado.
Fleshgrinder

2

Aquí está mi contribución a una pregunta de seis años con Dios sabe cuántas respuestas ...

Convertirá todas las palabras en la cadena proporcionada que están en camelcase a snakecase. Por ejemplo, "SuperSpecialAwesome y también FizBuzz καιΚάτιΑκόμα" se convertirán en "super_special_awesome y también fizz_buzz και_κάτι_ακόμα".

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

2

Yii2 tiene la función diferente para hacer la palabra snake_case de 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

Solución corta:

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

2

Tuve un problema similar, pero no pude encontrar ninguna respuesta que satisfaga cómo convertir CamelCase a snake_case, evitando al mismo tiempo guiones bajos duplicados o redundantes _para nombres con guiones bajos o abreviaturas en mayúsculas.

El problema es el siguiente:

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

La solución que escribí es una simple llamada de dos funciones, minúsculas y buscar y reemplazar por letras minúsculas y mayúsculas consecutivas:

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

De lejos, esta es la solución más concisa y útil de la OMI.
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);
}

Puede acceder a los caracteres directamente usando $name{$k}(o $name[$k]), lo que alargaría su código, pero evita la gran sobrecarga de convertirlo hacia y desde una matriz.
bodo

Las respuestas de solo código tienen poco valor en StackOverflow porque hacen un mal trabajo a la hora de empoderar / educar a los futuros investigadores. Su solución, mientras evita la gracia de las expresiones regulares, es muy torpe y complicada. Está dividiendo en cada carácter y haciendo múltiples llamadas a funciones iteradas. No es necesario nombrar una cuerda vacía como pegamento. No consideraría esta solución en uno de mis proyectos porque no hay elegancia, baja legibilidad y un número n de llamadas a funciones innecesarias.
mickmackusa

1

La peor respuesta aquí estuvo muy cerca de ser la mejor (use un marco). NO NO, simplemente eche un vistazo al código fuente. ver lo que utiliza un marco bien establecido sería un enfoque mucho más confiable (probado y comprobado). El marco Zend tiene algunos filtros de palabras que se adaptan a sus necesidades. Fuente .

aquí hay un par de métodos que adapté de la fuente.

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

Hay una biblioteca que proporciona esta funcionalidad:

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

1
Creo que te refieres a "He creado una biblioteca que ofrece esta funcionalidad". No hay nada de malo en la autopromoción, pero no lo ocultes.
icc97


1

Esta es una de las formas más cortas:

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

Las respuestas de solo código tienen poco valor en Stackoverflow porque hacen muy poco para educar / capacitar a miles de futuros investigadores.
mickmackusa

1
@mickmackusa: miles de investigaciones futuras estarán interesadas en una frase única y se educarán a sí mismos.
Teson

Lamento que hayas adoptado esa postura egoísta. Ciertamente podría haber agregado una explicación en el tiempo que le tomó diseñar y escribir esa respuesta sarcástica. Su respuesta realiza tres llamadas de función, pero otras realizan la tarea en dos.
mickmackusa

1

Cómo des-camelizar sin usar expresiones regulares:

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

Una edición:

¿Cómo haría eso en 2019?

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

Y cuándo se lanzará PHP 7.4:

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

1
Las respuestas de solo código tienen poco valor en StackOverflow porque hacen un mal trabajo a la hora de empoderar / educar a los futuros investigadores. Hacer de 1 a 3 llamadas de función en cada carácter de la cadena y luego dos llamadas de función más después de que el bucle está terminado es muy pesado. No consideraría una solución con una economía tan pobre.
mickmackusa

Es un ejemplo de cómo se podría hacer sin usar expresiones regulares, no cómo debería usarse en producción, así que no veo su punto, además de que se queja de una respuesta de 5 años que tiene un voto a favor y es poco probable que la vea cualquier investigador.
Calvos

Presto atención a todas las publicaciones, no solo a las que han votado a favor o las recientes. No me quejo, estoy ofreciendo mi crítica para que los investigadores con menos conocimiento puedan comprender mejor la diferencia entre esta respuesta y otras respuestas. Podrías haber explicado en tu publicación que era simplemente un desafío académico evitar las expresiones regulares. Dicho esto, hay formas de hacer que este proceso sea más eficiente con mejores prácticas de codificación.
mickmackusa

0

Es fácil usar las clases de filtro de los filtros 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;
    }
}

----- subrayadoToCamelCase -----

simple_test >>> SimpleTest

fácil >>> Fácil

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

fácil >>> fácil

HTML >>> html

simpleXML >>> simple_xml

PDFLoad >>> pdf_load

startMIDDLELast >>> start_middle_last

AString >>> una_cadena

Some4Numbers234 >>> some4_numbers234

TEST123String >>> test123_string


0

La biblioteca TurboCommons de código abierto contiene un método formatCase () de propósito general dentro de la clase StringUtils, que le permite convertir una cadena a muchos formatos de casos comunes, como CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case y muchos más.

https://github.com/edertone/TurboCommons

Para usarlo, importe el archivo phar a su proyecto y:

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
Las respuestas de solo código tienen poco valor en StackOverflow porque hacen un mal trabajo a la hora de empoderar / educar a los futuros investigadores.
mickmackusa

-1

SI pudieras comenzar con:

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

Entonces podrías convertir a cualquier caso solo con:

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

O cualquier otro caso:

$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string);               // CAMEL_CASE
$train = str_replace("_", "-", $snake);        // camel-case
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.