I have a preg_replace function to find all images and wrap them inside <figure> tag with different class, which depends on image source:
$pattern = '"/<img[^>]*src="([^"]+)"[^>]*alt="([^"]+)"[^>]*>\i"e';
$replacement = '"<figure class=\"" . check($1) . "\"><img src=\"$1\" alt=\"$2\" /></figure>"';
preg_replace($pattern, $replacement, $content);
Therefore, to put a right class, I wish to call a function check($source) with image source parameter. By this way, function is going to return necessary class.
As you can see in a code above, I am trying to use e modifier, but it seems it doesn't work.
Do I have to modify my pattern and replacement?
Should I use preg_replace_all to find all the images, if they are many inside my $content variable?
You can use preg_replace_callback() for this purpose. It allows you to define and use a function for replacement. The function should expect an array of matches and it is supposed to return the replacement value.
preg_replace() with an e modifier will also do the trick.
Check the regular expression library, there are already some HTML image patterns.
Related
I want to use class method as a second variable in preg_replace, like
$x = preg_replace('/\[\[\[(.+)\]\]\]/',
(new ButtonGroupWidget(['idsForLoad' => ['\0']]))->run(),
$code);
Idea is generate buttons instead of [[[button id]]]. Yes, this is kinda strange) And yes, I know what smarty is)
You may use preg_replace_callback and pass a callback function instead of a string replacement pattern into that function. If you define the match object argument as $m, the whole match will reside in $m[0].
function repl($m) {
return (new ButtonGroupWidget(['idsForLoad' => [$m[0]]]))->run();
}
$code = "[[[btn1]]] [[[btn2]]]";
$x = preg_replace_callback('/\[\[\[(.+?)]]]/', 'repl', $code);
I also advise to use a lazy dot matching pattern in the regex to enforce the regex to match the shortest strings between [[[ and ]]]. Note that ] does not have to be escaped here.
Is there a simple way I can have php camelcase a string for me? I am using the Laravel framework and I want to use some shorthand in a search feature.
It would look something like the following...
private function search(Array $for, Model $in){
$results = [];
foreach($for as $column => $value){
$results[] = $in->{$this->camelCase($column)}($value)->get();
}
return $results;
}
Called like
$this->search(['where-created_at' => '2015-25-12'], new Ticket);
So the resulting call in the search function I would be using is
$in->whereCreateAt('2015-25-12')->get();
The only thing is I can't figure out is the camel casing...
Have you considered using Laravel's built-in camel case functtion?
$camel = camel_case('foo_bar');
Full details can be found here:
https://laravel.com/docs/4.2/helpers#strings
So one possible solution that could be used is the following.
private function camelCase($string, $dontStrip = []){
/*
* This will take any dash or underscore turn it into a space, run ucwords against
* it so it capitalizes the first letter in all words separated by a space then it
* turns and deletes all spaces.
*/
return lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-z0-9'.implode('',$dontStrip).']+/', ' ',$string))));
}
It's a single line of code wrapped by a function with a lot going on...
The breakdown
What is the dontStrip variable?
Simply put it is an array that should contain anything you don't want removed from the camelCasing.
What are you doing with that variable?
We are taking every element in the array and putting them into a single string.
Think of it as something like this:
function implode($glue, $array) {
// This is a native PHP function, I just wanted to demonstrate how it might work.
$string = '';
foreach($array as $element){
$string .= $glue . $element;
}
return $string;
}
This way you're essentially gluing all your elements in your array together.
What's preg_replace, and what's it doing?
preg_replace is a function that uses a regular expression (also known as regex) to search for and then replace any values that it finds, which match the desired regex...
Explanation of the regex search
The regex used in the search above implodes your array $dontStrip onto a little bit a-z0-9 which just means any letter A to Z as well as numbers 0 to 9. The little ^ bit tells regex that it's looking for anything that isn't whatever comes after it. So in this case it's looking for any and all things that aren't in your array or a letter or number.
If you're new to regex and you want to mess around with it, regex101 is a great place to do it.
ucwords?
This can be most easily though of as upper case words. It will take any word (a word being any bit of characters separated by a space) and it will capitalize the first letter.
echo ucwords('hello, world!');
Will print `Hello, World!'
Okay I understand what preg_replace is, what str_replace?
str_replace is the smaller, less powerful but still very useful little brother/sister to preg_replace. By this I mean that it has a similar use. str_replace doesn't regex, but does use a literal string so whatever you type into the first parameter is exactly what it will look for.
Side note, it is worth mentioning for anyone considering only using preg_replace where str_replace would work just as well. str_replace has been noted to be benchmarked a bit faster than preg_replace on larger apps.
lcfirst What?
Since about PHP 5.3 we have been able to use the lcfirst function, which much like ucwords, it's just a text manipulation function. `lcfirst turns the first letter into it's lower case form.
echo lcfirst('HELLO, WORLD!');
Will print 'hELLO, WORLD!'
Results
All this in mind the camelCase function uses distinct non-alphanumeric characters as break points to turn a string to a camelCase string.
There's a general purpose open source library that contains a method that performs case convertions for several popular case formats. library is called TurboCommons, and the formatCase() method inside the StringUtils does camel case conversion.
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'
You can use Laravel's built-in camel case helper function
use Illuminate\Support\Str;
$converted = Str::camel('foo_bar');
// fooBar
Full details can be found here:
https://laravel.com/docs/9.x/helpers#method-camel-case
Use the in-built Laravel Helper Function - camel_case()
$camelCase = camel_case('your_text_here');
I have the following HTML statement
[otsection]Wallpapers[/otsection]
WALLPAPERS GO HERE
[otsection]Videos[/otsection]
VIDEOS GO HERE
What I am trying to do is replace the [otsection] tags with an html div. The catch is I want to increment the id of the div from 1->2->3, etc..
So for example, the above statement should be translated to
<div class="otsection" id="1">Wallpapers</div>
WALLPAPERS GO HERE
<div class="otsection" id="2">Videos</div>
VIDEOS GO HERE
As far as I can research, the best way to do this is via a preg_replace_callback to increment the id variable between each replacement. But after 1 hour of working on this, I just cant get it working.
Any assistance with this would be much appreciated!
Use the following:
$out = preg_replace_callback(
"(\[otsection\](.*?)\[/otsection\])is",
function($m) {
static $id = 0;
$id++;
return "<div class=\"otsection\" id=\"ots".$id."\">".$m[1]."</div>";
},
$in);
In particular, note that I used a static variable. This variable persists across calls to the function, meaning that it will be incremented every time the function is called, which happens for each match.
Also, note that I prepended ots to the ID. Element IDs should not start with numbers.
For PHP before 5.3:
$out = preg_replace_callback(
"(\[otsection\](.*?)\[/otsection\])is",
create_function('$m','
static $id = 0;
$id++;
return "<div class=\"otsection\" id=\"ots".$id."\">".$m[1]."</div>";
'),
$in);
Note: The following is intended to be a general answer and does not attempt to solve the OP's specific problem as it has already been addressed before.
What is preg_replace_callback()?
This function is used to perform a regular expression search-and-replace. It is similar to str_replace(), but instead of plain strings, it searches for a user-defined regex pattern, and then applies the callback function on the matched items. The function returns the modified string if matches are found, unmodified string otherwise.
When should I use it?
preg_replace_callback() is very similar to preg_replace() - the only difference is that instead of specifying a replacement string for the second parameter, you specify a callback function.
Use preg_replace() when you want to do a simple regex search and replace. Use preg_replace_callback() when you want to do more than just replace. See the example below for understanding how it works.
How to use it?
Here's an example to illustrate the usage of the function. Here, we are trying to convert a date string from YYYY-MM-DD format to DD-MM-YYYY.
// our date string
$string = '2014-02-22';
// search pattern
$pattern = '~(\d{4})-(\d{2})-(\d{2})~';
// the function call
$result = preg_replace_callback($pattern, 'callback', $string);
// the callback function
function callback ($matches) {
print_r($matches);
return $matches[3].'-'.$matches[2].'-'.$matches[1];
}
echo $result;
Here, our regular expression pattern searches for a date string of the format NNNN-NN-NN where N could be a digit ranging from 0 - 9 (\d is a shorthand representation for the character class [0-9]). The callback function will be called and passed an array of matched elements in the given string.
The final result will be:
22-02-2014
Note: The above example is for illustration purposes only. You should not use to parse dates. Use DateTime::createFromFormat() and DateTime::format() instead. This question has more details.
I want to be able to search for a certain word in a string, and append and prepend characters to every instance of that word.
example:
I like cats, cats are awesome! I wish I had cats!
becomes:
I like (cats), (cats) are awesome! I wish I had (cats)!
I know I could use
str_replace( 'cats', '(cats)', $string );
but I would have to write "cats" twice.
I want a method that only requires me to write it once.
$search = 'cats';
preg_replace('/' . preg_quote($search, '/') . '/', '($0)', $string);
Paraphrased from the preg_replace documentation:
The replacement string may contain references of the form $n. Every such reference will be replaced by the text captured by the n'th parenthesized pattern. $0 refers to the text matched by the whole pattern.
use a preg_replace() with back references: http://php.net/manual/en/function.preg-replace.php
preg_replace("/cats/smi","($0)",$string);
You commented:
I have a huge plain text list of values I need to parenthesize, and I
wanted to make it easier to write the code.
Since you're going to be doing many replacements (expensive cpu-wise), and you're wanting to simply shorten your coding time, why not also save CPU by wrapping str_replace()?
function str_wrap($needle,$prefix,$suffix,$haystack) {
return str_replace($needle, $prefix . $needle . $suffix, $haystack);
}
Per the PHP manual:
If you don't need fancy replacing rules (like regular expressions),
you should always use [str_replace()] instead of preg_replace().
$end = preg_replace($pattern, $replacement, $str);
How can I make the replacement string $replacement vary with each match in $str? For example, I want to replace each matched string with an associated image. Something about callbacks... right?
Yes, something with callbacks. Specifically preg_replace_callback, which makes repeated calls redundant. For a list of things to replace:
$src = preg_replace_callback('/(thing1|thing2|thing3)/', 'cb_vars', $src);
Where the callback can do some form of lookup or conversion:
function cb_vars($m) {
return strtoupper($m[1]);
}
Likewise can you do that inline with the normal preg_replace and the /e modifier.
You need to either use preg_replace_callback, or the /e modifier in the pattern string. The first is more powerful, but the second is more convenient if you are only after something relatively simple.