PHP preg_replace: MY_NEW_CLASS to My_New_Class - php

I've got a string in PHP, MY_NEW_CLASS and I want to convert it to My_New_Class.
Is this possible using preg_replace or should I explode the string on the underscore, strtolower it, ucfirst it, then implode it back together?
I appreciate any help you can offer.

preg_replace by itself can't really do it I'd think, but it's not hard with a callback:
$str = preg_replace_callback('/(?<=\b|_)./',
function ($m) { return strtoupper($m[0]); },
strtolower($str));

Why use regex?
function camelize( $string ){
return strtoupper( $string{0} ) . strtolower( substr( $string, 1 ) );
}
function camelizeClass( $class ){
$parts = explode( '_', $class );
array_walk( $parts, function( &$value, $key ){
$value = camelize( $value );
});
return implode( '_', $parts );
}
echo camelizeClass( 'MY_NEW_CLASS' ); // My_New_Class

Related

Migrate create_function() which is not supported since PHP 7.2

I have 'create_function() in my PHP code:
function encode_code_in_comment( $source ) { $encoded = preg_replace_callback( '/\[(php|html|javascript|css|nginx|apache|terminal)\](.*?)\[\/\1\]/ims',
create_function(
'$matches',
'$matches[2] = preg_replace(
array("/^[\r|\n]+/i", "/[\r|\n]+$/i"), "",
$matches[2]);
return "<pre class=\"language-" . $matches[1] . "\"><code>" . esc_html( $matches[2] ) . "</code></pre>";'
),
$source );
if ( $encoded ) {
return $encoded;
} else {
return $source;
}}
I know that there are duplicates threads about the subject, but nevertheless, i'm really struggling to covert this to an anonymous function. How do i rewrite it?
Your main problem is that your code is badly formatted, making it hard to see where the create_function call begins and ends; here it is with some more logical linebreaks and indents:
function encode_code_in_comment( $source ) {
$encoded = preg_replace_callback(
'/\[(php|html|javascript|css|nginx|apache|terminal)\](.*?)\[\/\1\]/ims',
create_function(
'$matches',
'
$matches[2] = preg_replace(
array("/^[\r|\n]+/i", "/[\r|\n]+$/i"),
"",
$matches[2]
);
return "<pre class=\"language-" . $matches[1] . "\"><code>" . esc_html( $matches[2] ) . "</code></pre>";
'
),
$source
);
if ( $encoded ) {
return $encoded;
} else {
return $source;
}
}
From this and the documentation of create_function, we can see that the created function needs one argument, $matches, and to have a body starting $matches[2] = and ending </pre>";
Looking at the manual for anonymous functions we see that the new syntax is function(arguments) { body }, so instead of:
create_function('$matches', ... )
you want:
function($matches) { ... }
and in between, instead of:
'
$matches[2] = ...
...
... </pre>";
'
you want to just remove the quotes and leave the code:
$matches[2] = ...
...
... </pre>";
The body is in single quotes, and there are no escaped single quotes in there, so the code doesn't need any other changes.

remove - and make every letter after as capital in the string - PHP [duplicate]

I want to take a string like this: 'this-is-a-string' and convert it to this: 'thisIsAString':
function dashesToCamelCase($string, $capitalizeFirstCharacter = false) {
// Do stuff
return $string;
}
I need to convert "kebab-case" to "camelCase".
No regex or callbacks necessary. Almost all the work can be done with ucwords:
function dashesToCamelCase($string, $capitalizeFirstCharacter = false)
{
$str = str_replace(' ', '', ucwords(str_replace('-', ' ', $string)));
if (!$capitalizeFirstCharacter) {
$str[0] = strtolower($str[0]);
}
return $str;
}
echo dashesToCamelCase('this-is-a-string');
If you're using PHP >= 5.3, you can use lcfirst instead of strtolower.
Update
A second parameter was added to ucwords in PHP 5.4.32/5.5.16 which means we don't need to first change the dashes to spaces (thanks to Lars Ebert and PeterM for pointing this out). Here is the updated code:
function dashesToCamelCase($string, $capitalizeFirstCharacter = false)
{
$str = str_replace('-', '', ucwords($string, '-'));
if (!$capitalizeFirstCharacter) {
$str = lcfirst($str);
}
return $str;
}
echo dashesToCamelCase('this-is-a-string');
This can be done very simply, by using ucwords which accepts delimiter as param:
function camelize($input, $separator = '_')
{
return str_replace($separator, '', ucwords($input, $separator));
}
NOTE: Need php at least 5.4.32, 5.5.16
Overloaded one-liner, with doc block...
/**
* Convert underscore_strings to camelCase (medial capitals).
*
* #param {string} $str
*
* #return {string}
*/
function snakeToCamel ($str) {
// Remove underscores, capitalize words, squash, lowercase first.
return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $str))));
}
In Laravel use Str::camel()
use Illuminate\Support\Str;
$converted = Str::camel('foo_bar');
// fooBar
this is my variation on how to deal with it. Here I have two functions, first one camelCase turns anything into a camelCase and it wont mess if variable already contains cameCase. Second uncamelCase turns camelCase into underscore (great feature when dealing with database keys).
function camelCase($str) {
$i = array("-","_");
$str = preg_replace('/([a-z])([A-Z])/', "\\1 \\2", $str);
$str = preg_replace('#[^a-zA-Z0-9\-_ ]+#', '', $str);
$str = str_replace($i, ' ', $str);
$str = str_replace(' ', '', ucwords(strtolower($str)));
$str = strtolower(substr($str,0,1)).substr($str,1);
return $str;
}
function uncamelCase($str) {
$str = preg_replace('/([a-z])([A-Z])/', "\\1_\\2", $str);
$str = strtolower($str);
return $str;
}
lets test both:
$camel = camelCase("James_LIKES-camelCase");
$uncamel = uncamelCase($camel);
echo $camel." ".$uncamel;
I would probably use preg_replace_callback(), like this:
function dashesToCamelCase($string, $capitalizeFirstCharacter = false) {
return preg_replace_callback("/-[a-zA-Z]/", 'removeDashAndCapitalize', $string);
}
function removeDashAndCapitalize($matches) {
return strtoupper($matches[0][1]);
}
You're looking for preg_replace_callback, you can use it like this :
$camelCase = preg_replace_callback('/-(.?)/', function($matches) {
return ucfirst($matches[1]);
}, $dashes);
here is very very easy solution in one line code
$string='this-is-a-string' ;
echo str_replace('-', '', ucwords($string, "-"));
output ThisIsAString
Try this:
$var='snake_case';
$ucword= ucword($var,'_');
echo $ucword;
Output:
Snake_Case
remove _ with str_replace
str_replace('_','',$ucword); //SnakeCase
and result
$result='SnakeCase'; //pascal case
echo lcfirst('SnakeCase'); //snakeCase (camel case)
the important thing is the approach here I used snake case and camel case in the example
$string = explode( "-", $string );
$first = true;
foreach( $string as &$v ) {
if( $first ) {
$first = false;
continue;
}
$v = ucfirst( $v );
}
return implode( "", $string );
Untested code. Check the PHP docs for the functions im-/explode and ucfirst.
One liner, PHP >= 5.3:
$camelCase = lcfirst(join(array_map('ucfirst', explode('-', $url))));
The TurboCommons library contains a general purpose formatCase() method inside the StringUtils class, which lets you convert a string to lots of common case formats, like CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case, and many more.
https://github.com/edertone/TurboCommons
To use it, import the phar file to your project and:
use org\turbocommons\src\main\php\utils\StringUtils;
echo StringUtils::formatCase('sNake_Case', StringUtils::FORMAT_CAMEL_CASE);
// will output 'sNakeCase'
Here's the link to the method source code:
https://github.com/edertone/TurboCommons/blob/b2e015cf89c8dbe372a5f5515e7d9763f45eba76/TurboCommons-Php/src/main/php/utils/StringUtils.php#L653
function camelize($input, $separator = '_')
{
return lcfirst(str_replace($separator, '', ucwords($input, $separator)));
}
echo ($this->camelize('someWeir-d-string'));
// output: 'someWeirdString';
Try this ;)
$string = 'this-is-a-string';
$separator = '-';
$stringCamelize = str_replace(
$separator,
'',
lcfirst(
ucwords(
strtolower($string),
$separator
)
)
);
var_dump($stringCamelize); // -> 'thisIsAString'
Alternatively, if you prefer not to deal with regex, and want to avoid explicit loops:
// $key = 'some-text', after transformation someText
$key = lcfirst(implode('', array_map(function ($key) {
return ucfirst($key);
}, explode('-', $key))));
Another simple approach:
$nasty = [' ', '-', '"', "'"]; // array of nasty characted to be removed
$cameled = lcfirst(str_replace($nasty, '', ucwords($string)));
Many good solutions above, and I can provide a different way that no one mention before. This example uses array. I use this method on my project Shieldon Firewall.
/**
* Covert string with dashes into camel-case string.
*
* #param string $string A string with dashes.
*
* #return string
*/
function getCamelCase(string $string = '')
{
$str = explode('-', $string);
$str = implode('', array_map(function($word) {
return ucwords($word);
}, $str));
return $str;
}
Test it:
echo getCamelCase('This-is-example');
Result:
ThisIsExample
Some very good solutions here. I compiled them together for easy c&p
declare(strict_types=1);
/**
* convert kebab-case to PascalCase
*/
function kebabToPascal( string $str ): string {
return str_replace( ' ', '', ucwords( str_replace( '-', ' ', $str ) ) );
}
/**
* convert snake_case to PascalCase
*/
function snakeToPascal( string $str ): string {
return str_replace (' ', '', ucwords( str_replace( '_', ' ', $str ) ) );
}
/**
* convert snake_case to camelCase
*/
function snakeToCamel( string $str ): string {
return lcfirst( snakeToPascal( $str ) );
}
/**
* convert kebab-case to camelCase
*/
function kebabToCamel( string $str): string {
return lcfirst( kebabToPascal( $str ) );
}
echo snakeToCamel( 'snake_case' ). '<br>';
echo kebabToCamel( 'kebab-case' ). '<br>';
echo snakeToPascal( 'snake_case' ). '<br>';
echo kebabToPascal( 'kebab-case' ). '<br>';
echo kebabToPascal( 'It will BREAK on things-like_this' ). '<br>';
In Yii2 you can use yii\helpers\Inflector::camelize():
use yii\helpers\Inflector;
echo Inflector::camelize("send_email");
// outputs: SendEmail
Yii provides a lot of similar functions, see the Yii2 Docs.
function camelCase($text) {
return array_reduce(
explode('-', strtolower($text)),
function ($carry, $value) {
$carry .= ucfirst($value);
return $carry;
},
'');
}
Obviously, if another delimiter than '-', e.g. '_', is to be matched too, then this won't work, then a preg_replace could convert all (consecutive) delimiters to '-' in $text first...
If you use Laravel framework, you can use just camel_case() method.
camel_case('this-is-a-string') // 'thisIsAString'
Here is another option:
private function camelcase($input, $separator = '-')
{
$array = explode($separator, $input);
$parts = array_map('ucwords', $array);
return implode('', $parts);
}
$stringWithDash = 'Pending-Seller-Confirmation';
$camelize = str_replace('-', '', ucwords($stringWithDash, '-'));
echo $camelize;
output: PendingSellerConfirmation
ucwords second(optional) parameter helps in identify a separator to camelize the string.
str_replace is used to finalize the output by removing the separator.
Here is a small helper function using a functional array_reduce approach.
Requires at least PHP 7.0
private function toCamelCase(string $stringToTransform, string $delimiter = '_'): string
{
return array_reduce(
explode($delimiter, $stringToTransform),
function ($carry, string $part): string {
return $carry === null ? $part: $carry . ucfirst($part);
}
);
}
private function dashesToCamelCase($string)
{
$explode = explode('-', $string);
$return = '';
foreach ($explode as $item) $return .= ucfirst($item);
return lcfirst($return);
}
This works for me:
function camelCase($string){
$chunks = preg_split("/\s+|-|_/",$string);
$camel = "";
foreach ($chunks as $idx => $chunk){
if ($idx===0){
$camel = strtolower($chunk);
}else{
$camel .= ucfirst($chunk);
}
}
return $camel;
}
The shortest and most elegant solution would be:
function dashesToCamelCase($string, $capitalizeFirstCharacter = false) {
$result = join("", array_map("ucfirst", explode("-", $string)));
if ($capitalizeFirstCharacter === false) {
return lcfirst($result);
}
return $result;
}
One Line Option
echo str_replace(' ', '', lcfirst(ucwords(str_replace("_", " ", 'facebook_catalog_id_type'))));
//output: facebookCatalogIdType
Try this:
return preg_replace("/\-(.)/e", "strtoupper('\\1')", $string);
This is simpler :
$string = preg_replace( '/-(.?)/e',"strtoupper('$1')", strtolower( $string ) );

PHP preg_match ignore within certain elements

I'm writing a regex where I need to filter content to format it's typography. So far, my code seems to be filtering out my content properly using preg_replace, but I can't figure out how to avoid this for content wrapped within certain tags, say <pre>.
As a reference, this is to be used within WordPress's the_content filter, so my current code looks like so:
function my_typography( $str ) {
$ignore_elements = array("code", "pre");
$rules = array(
"?" => array("before"=> " ", "after"=>""),
// the others are stripped out for simplicity
);
foreach($rules as $rule=>$params) {
// Pseudo :
// if( !in_array( $parent_tag, $ignore_elements) {
// /Pseudo
$formatted = $params['before'] . $rule . $params['after'];
$str = preg_replace( $rule, $formatted, $str );
// Pseudo :
// }
// /Pseudo
}
return $str;
}
add_filter( 'the_content', 'my_typography' );
Basically:
<p>Was this filtered? I hope so</p>
<pre>Was this filtered? I hope not.</pre>
should become
<p>Was this filtered ? I hope so</p>
<pre>Was this filtered? I hope not.</pre>
You need to wrap search regex with regex delimiter in preg_replace and must call preg_quote to escape all special regex characters such ?, ., *, + etc:
$str = preg_replace( '~' . preg_quote($rule, '~') . '~', $formatted, $str );
Full Code:
function my_typography( $str ) {
$ignore_elements = array("code", "pre");
$rules = array(
"?" => array("before"=> " ", "after"=>""),
// the others are stripped out for simplicity
);
foreach($rules as $rule=>$params) {
// Pseudo :
// if( !in_array( $parent_tag, $ignore_elements) {
// /Pseudo
$formatted = $params['before'] . $rule . $params['after'];
$str = preg_replace( '~' . preg_quote($rule, '~') . '~', $formatted, $str );
// Pseudo :
// }
// /Pseudo
}
return $str;
}
Output:
<p>Was this filtered ? I hope so</p>
<pre>Was this filtered ? I hope not.</pre>

Warnings in Regular Expression with Posix Collating Elements

I am trying to run following regular expression based function in php where in the end am returning the output.
function vg_excerpt_more( $output ) {
$string = $output;
$pattern_auto_excerpt = '#([...]</p>)$#';
$pattern_manual_excerpt = '#(</p>)$#';
$replacement = ' [Continue...]</p>';
if ( preg_match( $pattern_auto_excerpt, $string ) ) {
$pattern = $pattern_auto_excerpt;
} else if ( preg_match( $pattern_manual_excerpt, $string ) ) {
$pattern = $pattern_manual_excerpt;
}
$output = preg_replace( $pattern, $replacement, $string );
return $output;
}
add_filter( 'the_excerpt', 'vg_excerpt_more' );
add_filter( 'excerpt_more', 'vg_excerpt_more' );
Well, the string could either end in [...]</p> OR </p> so I have to check the two cases.
The problem is, it is throwing warnings as -
WARNING: PREG_MATCH(): COMPILATION FAILED: POSIX COLLATING ELEMENTS
ARE NOT SUPPORTED AT OFFSET 1 in - 'preg_match( $pattern_auto_excerpt,
$string )'
and
WARNING: PREG_REPLACE(): EMPTY REGULAR EXPRESSION in - '$output =
preg_replace( $pattern, $replacement, $string );'
EDIT:
After useful replies by #user1852180 I moved ahead and did this -
function vg_excerpt_more( $output ) {
$string = $output;
$pattern = '';
// $pattern_auto_excerpt = '#(\[...\]</p>)$#';
$pattern_auto_excerpt = '#(\[(?:\.|…)+\])#';
$pattern_manual_excerpt = '#(</p>)$#';
$replacement = ' [Continue...]</p>';
if ( preg_match( $pattern_auto_excerpt, $string ) ) {
$pattern = '#(\[(?:\.|…)+\]</p>)$#';
if ( preg_match( $pattern, $string ) ) {
return preg_replace( $pattern, $replacement, $string ) . "Dummy2";
}
} else if ( preg_match( $pattern_manual_excerpt, $string ) ) {
$pattern = $pattern_manual_excerpt;
return preg_replace( $pattern, $replacement, $string ) . "Dummy";
}
return $output;
}
add_filter( 'the_excerpt', 'vg_excerpt_more' );
add_filter( 'excerpt_more', 'vg_excerpt_more' );
But am still seeing [...] in the frontend along with the replacement.
PS. It also never prints 'Dummy2', always 'Dummy'.
You need to escape the brackets in the first pattern, and the dot:
$pattern_auto_excerpt = '#(\[(?:\.|…)+\]</p>)$#';
You don't need to use the if/else to check if it has [...], let regex check that with the question mark:
function vg_excerpt_more( $output ) {
$pattern = '#(?:\[(?:\.|…)+\])?</p>$#';
$replacement = ' [Continue...]</p>';
return preg_replace( $pattern, $replacement, $output );
}

PHP Sentence case a string with capitalized proper nouns using a known words dictionary?

I need to search a string of words against a dictionary of words(txt file) and capitalize any word that is not found.
I'm trying to split the string into an array of words and check them against the unix /usr/dict/words dictionary. If a match is found for the word it gets lcfirst($word) if no match then ucfirst( $word )
The dictionary is opened and put into an array using fgetcsv (I also tried using fgets and exploding on end of line).
function wnd_title_case( $string ) {
$file = fopen( "/users/chris/sites/wp-dev/trunk/core/words.txt", "rb" );
while ( !feof( $file ) ) {
$line_of_text = fgetcsv( $file );
$exceptions = array( $line_of_text );
}
fclose( $file );
$delimiters = array(" ", "-", "O'");
foreach ( $delimiters as $delimiter ) {
$words = explode( $delimiter, $string );
$newwords = array();
foreach ($words as $word) {
if ( in_array( strtoupper( $word ), $exceptions ) ) {
// check exceptions list for any words that should be lower case
$word = lcfirst( $word );
} elseif ( !in_array( $word, $exceptions ) ) {
// everything else capitalized
$word = ucfirst( $word );
}
array_push( $newwords, $word );
}
$string = join( $delimiter, $newwords );
}
$string = ucfirst( $string );
return $string;
}
I have verified that the file gets opened.
The desired output: Sentence case title string with proper nouns capitalized.
The current output: Title string with every word capitalized
Edit:
Using Jay's answer below I came up with a workable solution. My first problem was that my words dictionary contained both capitalized and non capitalized words so I found a proper names dictionary to to check against using a regex callback. It's not perfect but gets it right most of the time.
function title_case( $string ) {
$fp = #fopen( THEME_DIR. "/_/inc/propernames", "r" );
$exceptions = array();
if ( $fp ) {
while( !feof($fp) ) {
$buffer = fgets( $fp );
array_push( $exceptions, trim($buffer) );
}
}
fclose( $fp );
$content = strtolower( $string );
$pattern = '~\b' . implode ( '|', $exceptions ) . '\b~i';
$content = preg_replace_callback ( $pattern, 'regex_callback', $content );
$new_content = $content;
return ucfirst( $new_content );
}
function regex_callback ( $data ) {
if ( strlen( $data[0] ) > 3 )
return ucfirst( strtolower( $data[0] ));
else return ( $data[0] );
}
The simplest way to do this with regex is to do the following
convert your text to all uppercase first letters $content = ucwords($original_content);
Using your array of words in the dictionary, create a regex by imploding all your words with a pipe character |, and surrounding it with boundary markers and delimiters followed by the case insensitive flag, so you would end up with ~\bword1|word2|word3\b~i (obviously with your large list)
create a function to lower the matched value using strtolower to be used with preg_replace_callback
An example of a working demo is this
function regex_callback($data) {
return strtolower($data[0]);
}
$original_content = 'hello my name is jay gilford';
$words = array('hello', 'my', 'name', 'is');
$content = ucwords($original_content);
$pattern = '~\b' . implode('|', $words) . '\b~i';
$content = preg_replace_callback($pattern, 'regex_callback', $content);
echo $content;
You could also optionally use strtolower to begin with on the content for consistency. The above code outputs hello my name is Jay Gilford

Categories