Your camelCase
to kebab-case
pattern doesn't need to capture anything or use a backreference in the replacement.
Code: (Demo)
$className = 'getADog';
echo strtolower(preg_replace('/[a-zA-Z]\K(?=[A-Z])/', '-', $className));
// get-a-dog
For a regex that is more robust and will handle camelCase and StudlyCase and will correctly handle acronyms and numeric strings, try the following. (Demo)
(?> #start atomic group (use first qualifying branch)
[A-Z]?[a-z]+ #zero or one upper followed by one or more lowers
| #OR
[A-Z]+ #one or more uppers
(?= #start lookahead without consuming characters
[A-Z][a-z] #one upper followed by one lower
| #OR
[^A-Za-z] #one non-letter
) #end lookahead
| #OR
[^A-Za-z]+ #one or more non-letters
) #end atomic group
\K #forget any consumed matched characters so far
(?!$) #position must not be the end of the string
Code: (Demo)
$tests = [
'getADogThenROCKInTheUSA',
'SomeOfTheWords',
'getADog',
'ADog',
'aDog',
'XML',
'SimpleXMLReader',
'FREE4NOW',
'123ABC',
'DEF456',
'ghi789',
'wtf666Omg',
'PHP8Point3',
];
foreach ($tests as $test) {
printf(
"%25s => %s\n",
$test,
strtolower(
preg_replace(
'/(?>[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|[^A-Za-z])|[^A-Za-z]+)\K(?!$)/',
'-',
$test
)
)
);
}
Output:
getADogThenROCKInTheUSA => get-a-dog-then-rock-in-the-usa
SomeOfTheWords => some-of-the-words
getADog => get-a-dog
ADog => a-dog
aDog => a-dog
XML => xml
SimpleXMLReader => simple-xml-reader
FREE4NOW => free-4-now
123ABC => 123-abc
DEF456 => def-456
ghi789 => ghi-789
wtf666Omg => wtf-666-omg
PHP8Point3 => php-8-point-3
camelCase
versusPascalCase
versusStudlyCase
versussnake_case
versuskebab-case
– Commemorative