Pregunta

Si tuviera:

$string = "PascalCase";

Necesito

"pascal_case"

¿El PHP ofrece una función para este propósito?

¿Fue útil?

Solución

Pruebe esto en 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 reglas siguientes:

  1. Una secuencia comenzando con una letra minúscula debe ser seguida por letras minúsculas y dígitos;
  2. Una secuencia comenzando con una letra mayúscula puede ser seguido por cualquiera de:
    • una o letras y dígitos más mayúsculas (seguido por o bien el final de la cadena o una letra mayúscula seguida por una letra minúscula o dígito es decir, el inicio de la siguiente secuencia); o
    • una o más letras o dígitos minúsculas.

Otros consejos

Una solución más corto: Al igual que en el del editor una con una expresión regular simplificada y se fija el "arrastre-subrayado" problema:

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

PHP demostración | Regex demostración


Nota que casos como SimpleXML se convertirán a simple_x_m_l usando la solución anterior. Eso también puede ser considerado como un mal uso de la caja de camello notación (correcta sería SimpleXml) en lugar de un error del algoritmo, ya que tales casos son siempre ambiguos - incluso mediante la agrupación de mayúsculas caracteres de una cadena (simple_xml) como algoritmo siempre fallará en otra casos extremos como XMLHTMLConverter o palabras de una letra cerca de abreviaturas, etc. Si no se cuenta sobre el lugar (raros) casos extremos y desea correctamente a SimpleXML mango, se puede utilizar una solución poco más complejo:

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

PHP demostración | Regex demostración

solución concisa A y puede manejar algunos casos de uso complicado:

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

portado desde String#camelize y String#decamelize de Ruby.

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 las soluciones anteriores pueden haber perdido es la 'e' modificador que causa preg_replace para evaluar la cadena de reemplazo como código PHP.

El Symfony Serializer Componente tiene un CamelCaseToSnakeCaseNameConverter que tiene dos métodos normalize() y denormalize(). Estos pueden ser utilizados como sigue:

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

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

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

La mayoría de las soluciones que aquí se sienten de mano dura. Esto es lo que yo 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 (salida convertida evita 'camelCase' para comenzar con un guión bajo)
  • [A-Z] encuentra mayúsculas
  • + va a tratar cada mayúsculas consecutivo como una palabra (evita 'camelCase' para ser convertido en camel_C_A_S_E)
  • En segundo patrón y la sustitución son para ThoseSPECCases -> those_spec_cases en lugar de those_speccases
  • strtolower([…]) convierte la salida a minúsculas

php no ofrece una función integrada para este yo sepa, pero aquí es lo que yo 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 de función, por lo que se le puede llamar como tal

$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"
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 usted está buscando una versión de PHP 5.4 y posterior respuesta 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
    );

} 

No es lujoso pero simple y rápido como el demonio:

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

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

Una versión que no utiliza expresiones regulares se puede encontrar en el href="http://alchitect.com" rel="nofollow noreferrer"> Alchitect fuente

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

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

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

danielstjules / viscosa provieds un método para convertir la cadena de CamelCase para snakecase.

s('TestUCase')->underscored(); // 'test_u_case'

laravel 5.6 proporciona una manera 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;
}

Lo que hace: si ve que hay al menos una letra mayúscula en la cadena dada, se utiliza un búsqueda positiva hacia delante para buscar cualquier carácter (.) seguido de una letra mayúscula ((?=[A-Z])). A continuación, reemplaza el carácter encontrado con su valor seguido por el _ separactor.

El puerto directo de carriles (menos su manejo especial para :: o acrónimos) 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, '-', '_'));
}

El saber PHP, esto va a ser más rápido que el análisis manual que está sucediendo en otras respuestas que se dan aquí. La desventaja es que no dan a elegir lo que a su uso como un separador entre las palabras, pero eso no era parte de la pregunta.

También compruebe la fuente relevante rieles código

Tenga en cuenta que esto es para uso con identificadores ASCII. Si necesita hacer esto con caracteres fuera del rango ASCII, utilice el '/ T' modificador para uso preg_matchand mb_strtolower.

Esta es mi contribución a una pregunta de seis años de edad, con Dios sabe cuántas respuestas ...

Se convertirá todas las palabras de la cadena, siempre que se encuentren en CamelCase para snakecase. Por ejemplo "SuperSpecialAwesome y también FizBuzz καιΚάτιΑκόμα" se convertirá en "super_special_awesome y también fizz_buzz και_κάτι_ακόμα".

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

Yii2 tener la diversa función 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));
    }
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);
}
$str = 'FooBarBaz';

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

Esta es una de las formas más cortas:

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

¿Cómo de-camelize sin utilizar 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 iba a hacer eso en 2019:

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

Y cuando PHP 7.4 será liberado:

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

solución corta:

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

Es fácil utilizando las clases de filtros del Zend Palabra filtros :

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

     

fácil >>> Fácil

     

>>> html HTML

     

simple_xml >>> SimpleXML

     

pdf_load >>> PdfLoad

     

start_middle_last >>> StartMiddleLast

     

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

La peor respuesta aquí era tan cerca de ser el mejor (utilizar un marco). NO No, sólo echar un vistazo al código fuente. viendo lo que es un bien establecidos usos marco sería un enfoque mucho más fiable (probadas). El marco de Zend tiene algunos filtros de palabras que se ajustan a sus necesidades. Fuente .

aquí es un par de métodos que Adaptado 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");

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

https://github.com/edertone/TurboCommons

Para usarlo, importar 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'

He tenido un problema similar, pero no pude encontrar ninguna respuesta que satisface la forma de convertir CamelCase para snake_case, evitando al mismo tiempo guiones duplicados o redundantes _ de nombres con guiones bajos, o todas las abreviaturas caps.

Th problema es como sigue:

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

La solución que escribí es una sencilla dos funciones llaman, minúsculas y búsqueda y reemplazo para las letras minúsculas consecutivas-mayúsculas:

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

Si usted podría comenzar con:

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

A continuación, se podría convertir en cualquiera de los casos simplemente 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top