PHP Using str_replace along with preg_replace - php

I have a string of comma separated values that comes from a database, which actually are image paths. Like so:
/images/us/US01021422717777-m.jpg,/images/us/US01021422717780-m.jpg,/images/us/US01021422717782-m.jpg,/images/us/US01021422718486-m.jpg
I then do like below, to split them at the , and convert them into paths for the web page.
preg_replace('~\s?([^\s,]+)\s?(?:,|$)~','<img class="gallery" src="$1">', $a)
Works well, but in one place further in my page, I need to change the -m to -l (which means large)
When I do like below (put a str_replace inside the preg_replace), nothing happens. How can I do something like this?
preg_replace('~\s?([^\s,]+)\s?(?:,|$)~','<img class="gallery" src="$1" data-slide="'.str_replace('-m','-l','$1').'">', $a)

You're putting the str_replace() call in the output pattern for the preg_replace() call. That means preg_replace() is treating it as literal text.
What you want is something like this:
$imgtag = preg_replace(match, replacement, $a);
$imgtag = str_replace('-m','-l',$imgtag);
But, in my opinion it would be safer and easier to debug this stuff if you changed the order of your replacement operations, something like this:
foreach ($path in explode(",", $a)) {
$path = str_replace('-m','-l',$path);
$imgtag= sprintf ('<img class="gallery" src="%s">', $path);
/* do something with the $imgtag */
}
That way you don't have to whistle into your modem :-) to program that regexp.

Use str_replace on preg_replace return
$large = str_replace('-m','-l', preg_replace('~\s?([^\s,]+)\s?(?:,|$)~','<img class="gallery" src="$1">', $a));
Output will be
<img class="gallery" src="/images/us/US01021422717777-l.jpg">
<img class="gallery" src="/images/us/US01021422717780-l.jpg">
<img class="gallery" src="/images/us/US01021422717782-l.jpg">
<img class="gallery" src="/images/us/US01021422718486-l.jpg">

Use preg_replace_callback():
preg_replace_callback(
'~\s?([^\s,]+)\s?(?:,|$)~',
function (array $matches) {
$src = $matches[1]; // this is "$1"
$slide = str_replace('-m', '-l', $matches[1]);
return '<img class="gallery" src="'.$src.'" data-slide="'.$slide.'">';
},
$a
);
Instead of the replace expression, preg_replace_callback() gets as its second argument a function that receives the list of matched expressions and returns the replacement string.

Actually your str_replace is simply invoked before preg_replace is invoked. Result of str_replace is then passed as argument to preg_replace.
What I could suggest is using preg_replace_callback:
function replace_img($match)
{
return '<img class="gallery" src="' .
$match[1] .
'" data-slide="' .
str_replace('-m','-l',$match[1]) .
'">';
}
preg_replace_callback('~\s?([^\s,]+)\s?(?:,|$)~','replace_img', $a);

If you need two separate outputs from each comma-separated value, I would write a pattern that stores the fullstring match and the substrings on either side of the m in each file.
*note: I match the trailing - in the first capture group and the leading . in the second capture group for minimal assurance of accuracy. This is somewhat weak validation; you can firm it up if your project requires it by adding literal or more restrictive pattern components in the capture groups.
Code: (Demo)
$csv='/images/us/US01021422717777-m.jpg,/images/us/US01021422717780-m.jpg,/images/us/US01021422717782-m.jpg,/images/us/US01021422718486-m.jpg';
if(preg_match_all('~([^,]+-)m(\.[^,]+)~',$csv,$out,PREG_SET_ORDER)){
foreach($out as $m){
$mediums[]="<img class=\"gallery\" src=\"{$m[0]}\">";
$larges[]="<img class=\"gallery\" src=\"{$m[0]}\" data-slide=\"{$m[1]}l{$m[2]}\">";
}
}
var_export($mediums);
echo "\n\n";
var_export($larges);
Output:
array (
0 => '<img class="gallery" src="/images/us/US01021422717777-m.jpg">',
1 => '<img class="gallery" src="/images/us/US01021422717780-m.jpg">',
2 => '<img class="gallery" src="/images/us/US01021422717782-m.jpg">',
3 => '<img class="gallery" src="/images/us/US01021422718486-m.jpg">',
)
array (
0 => '<img class="gallery" src="/images/us/US01021422717777-m.jpg" data-slide="/images/us/US01021422717777-l.jpg">',
1 => '<img class="gallery" src="/images/us/US01021422717780-m.jpg" data-slide="/images/us/US01021422717780-l.jpg">',
2 => '<img class="gallery" src="/images/us/US01021422717782-m.jpg" data-slide="/images/us/US01021422717782-l.jpg">',
3 => '<img class="gallery" src="/images/us/US01021422718486-m.jpg" data-slide="/images/us/US01021422718486-l.jpg">',
)

Related

Regex replace keyword with different string by loop (PHP)

Let say I have a string
$content = "hello . wow . cool . yes!";
It's easy to just replace the dot to another string:
echo preg_replace("/\./", "<img>", $content);
so the output is:
hello <img> wow <img> cool <img> yes!
however, is there any way to replace it one by one?
for example, I have an array and would like to insert them into the string.
$arr = ['<img src="a"/>', '<img src="b"/>', '<img src="c"/>'];
the expected output:
hello <img src="a"/> wow <img src="b"/> cool <img src="c"/> yes!
I can use preg_match_all to get the separator but still have no idea how to replace it respectively.
Thank you for any help.
Use preg_replace_callback. Store the number of the current full stop in a static variable. Access $arr from the callback with use (). Use modulo in case there are not enough items in $arr.
<?php
$content = 'hello . wow . cool . yes!';
$arr = ['<img src="a"/>', '<img src="b"/>', '<img src="c"/>'];
$content = preg_replace_callback ('/\./', function ($_) use ($arr) {
static $count = 0;
return $arr [$count++ % count ($arr)];
}, $content);
echo ($content);
http://sandbox.onlinephpfunctions.com/code/f9115bdb6eb17e30012d987ed1fc4b95e7c10d33.

issus with emoji in array

In this code, when I use ":-)" emoji doesn't show in output.
But when use "1f60a" OR "1f60c" OR "e252" emoji are shown. What's the problem?
<?php
$emoji_url = "http://coremobile.ir/images_smileys";
$emoji_style = "";
$emoji_code = array(
":-)",
"1f60a",
"1f60c",
"e252"
);
$emoji_img = array(
'<img src="'.$emoji_url.'/1f60a.png" '.$emoji_style.'>',
'<img src="'.$emoji_url.'/1f60a.png" '.$emoji_style.'>',
'<img src="'.$emoji_url.'/1f60c.png" '.$emoji_style.'>',
'<img src="'.$emoji_url.'/e252.png" '.$emoji_style.'>'
);
$ret = 'This Test :-) 1f60a';
$ret = str_replace($emoji_code, $emoji_img, $ret);
echo $ret;
?>
This should work for you:
(Just use strtr() instead of str_replace(), so that it won't go through the string multiple times)
$ret = strtr($ret, array_combine($emoji_code, $emoji_img));
output:
This Test
The otherone didn't worked, because it replaced every match for the first replacement and then the second and so on.
0 replaced:
This Test :-) 1f60a
//^^^ match
first replaced:
This Test <img src="http://coremobile.ir/images_smileys/1f60a.png" > 1f60a
//^^^^^ match ^^^^^ match
second replaced:
This Test <img src="http://coremobile.ir/images_smileys/<img src="http://coremobile.ir/images_smileys/1f60a.png" >.png" > <img src="http://coremobile.ir/images_smileys/1f60a.png" >

How would one use PHP preg_match_all to differentiate anchor elements identified by attribute of inner HTML element?

I have sets of HTML anchor elements enclosing image elements. For each set, using PHP-CLI, I want to pull the URLs and classify them according to their types. The type of anchor can only be determined by an attribute of its child image element. It would be easy if there was only one of each type per set. My problem is when two anchor elements of one type are separated by one or more of the other types. My non-greedy parenthesized sub-pattern seems to become greedy and expands to find the second relevant child attribute. In my test script I'm trying to pull the 'Userlink' URLs from amongst the other types. Using a simple pattern like:
#<a href="(.*?)" custattr="value1"><img alt="Userlink"#
On a set like:
<li><img alt="Userlink" class="common_link_class" height="123" src="pic0.png" width="123" style="width: 123px;"></li><li><img alt="Socnet1" class="common_link_class" height="123" src="pic1.png" width="123" style="width: 123px;"></li><li><img alt="Socnet2" class="common_link_class" height="123" src="pic2.png" width="123" style="width: 123px;"></li><li><img alt="Usermail" class="common_link_class" height="123" src="pic3.png" width="123" style="width: 123px;"></li><li><img alt="Userlink" class="common_link_class" height="123" src="pic4.png" width="123" style="width: 123px;"></li>
(sorry, but the actual html is on one line like that)
My sub-pattern captures from the beginning of the first "Userlink" URL to the end of the last one.
I've tried many variations of look-aheads, not sure I should list them all here. So far they've either returned no match at all or the same as described above.
Here's my test script (running in a Bash shell):
#!/usr/bin/php
<?
$lines = 0;
$input = "";
$matches = array();
while ($line = fgets(STDIN)){
$input .= $line;
$lines++;
}
fwrite(STDERR, "Processing $lines\n");
$pcre = '#<a href="(.*?)" custattr="value1"><img alt="Userlink"#';
if (preg_match_all($pcre,$input,$matches)){
fwrite(STDERR, "\$matches has " . count($matches) . " elements\n");
foreach ($matches[1] as $match){
fwrite(STDOUT, $match . "\n");
}
}
?>
What PCRE pattern for PHP's preg_match_all() would return the two "Userlink" URLs in the above example?
I have taken the liberty of changing your variable names:
$pattern = '~<a href="([^"]++)" custattr="value1"><img alt="Userlink"~';
if ($nb = preg_match_all($pattern, $input, $matches)) {
fwrite(STDERR, "\$matches has " . $nb . " elements\n");
fwrite(STDOUT, implode("\n", $match) . "\n");
}
Note that the preg_match_all function returns the number of matches.
This regex should work -
<a href="([^"]*?)"[^>]*\><img alt="Userlink"
You can see how it work here.
Testing it -
$pcre = '/<a href="([^"]*?)"[^>]*\><img alt="Userlink"/';
if (preg_match_all($pcre,$input,$matches)){
var_dump($matches);
//$matches[1] will be the array containing the urls.
}
/*
OUTPUT-
array
0 =>
array
0 => string '<a href="http://www.userlink1.com/my/page.html" custattr="value1"><img alt="Userlink"' (length=85)
1 => string '<a href="http://www.userlink2.com/my/page.html" custattr="value1"><img alt="Userlink"' (length=85)
1 =>
array
0 => string 'http://www.userlink1.com/my/page.html' (length=37)
1 => string 'http://www.userlink2.com/my/page.html' (length=37)
*/

php regex to change paths

I am new to PHP and regex hence need help using it to che some image paths.
My CMS generates image paths like this:
<img src="http://localhost/test/images/normal/ima1.jpg" width="100" height="100" alt="ima1">
I am using PHP and i have a variable $size and I want that if $size = 'small' then the path should be
<img src="http://localhost/test/images/small/ima1.jpg" width="100" height="100" alt="ima1">
and if if $size = 'medium' then the path should be
<img src="http://localhost/test/images/medium/ima1.jpg" width="100" height="100" alt="ima1">
These links are dynamically generated by my CMS hence I am looking for the PHP code which will replace the flder name in these links after the page is rendered.
All I want to replace is the word between images/ and the / after the replacing word.
Try $blabla = preg_replace( "/images\/[a-zA-Z]\//" , "images\/" . $size . "\/" , $sourceCode );
Now, $blabla is a random name. You could change it to whatever you want.
$sourceCode is also a name. You need to replace it with the string you want to replace.
E.g. $sourceCode = "<img src=\"http://localhost/test/images/small/ima1.jpg\" width=\"100\" height=\"100\" alt=\"ima1\">".
The syntax of the function preg_replace is as follows: preg_replace ( mixed $pattern , mixed $replacement , mixed $subject ).
It means: $pattern - the pattern you would like to replace in you string (our case $sourceCode), like "/images\/[a-zA-Z]\//". You could read about regexp syntax here.
$replacement - the text you want to put instead of the pattern. Since we are looking for everything that looks like "images/SOME_TEXT/" - we are replacing the whole pattern. To fill the src attribute correctly, we make our replacement as "image/" . $size . "/".
If we wrote a single $size as the replacement, we would get our $blalba as "<img src=\"http://localhost/test/smallima1.jpg\" width=\"100\" height=\"100\" alt=\"ima1\">".
Notice the smallima1.jpg (that's in case $size = "small").
P.S. Notice the backslashes before every ". They are preventing from the php parser to think it's the end of the string input. E.g. $name = "The "Batman""; will return error, while $name = "The \"Batman\""; will assign The "Batman" to the variable $name.
They are neccessary, if you assign a string that contains quotes to a variable.
My question for you is why do you want to replace ??? I if your site is properly structured you don't need replace
I expect something like this
$sizes = array("normal"=>array(500,500),
"small"=>array(100,100),
"medium"=>array(300,200));
$selected = "small" ;
$imageHost= "http://localhost/test/images" ;
$imagePath = "/public_html/test/images" ;
$imageName = "ima1.jpg" ;
$tag = "<img src=\"{$imageHost}/%s/$imageName\" width=\"%d\" height=\"%s\" alt=\"ima1\">";
Simple Demo to output all sizes
echo "<pre>" ;
foreach($sizes as $size => $dim){
if(!file_exists($imagePath . DIRECTORY_SEPARATOR . $selected . DIRECTORY_SEPARATOR . $imageName))
{
// Am sure you want to either create the image or copu the thumn here
}
echo printf($tag,$size,$dim[0],$dim[1]) . PHP_EOL;
}
Output
<img src="http://localhost/test/images/normal/ima1.jpg" width="500" height="500" alt="ima1">
<img src="http://localhost/test/images/small/ima1.jpg" width="100" height="100" alt="ima1">
<img src="http://localhost/test/images/medium/ima1.jpg" width="300" height="200" alt="ima1">
Providing that all your images are under the same path, I recommend you leave regular expressions alone (this time), and opt for a much easier explode() method.
Using the PHP explode() function you can split a string into an array using a delimiter.
$str = 'http://localhost/test/images/small/ima1.jpg';
$arr = explode('/',$str);
This should give you something like this -
Array
(
[0] => http:
[1] =>
[2] => localhost
[3] => test
[4] => images
[5] => small
[6] => ima1.jpg
)
// remove the protocol specification and the empty element.
// You'll see that the `explode()` function actually removes the slashes
// (including the two at the beginning of the URL in the protocol specification),
// you'll have to return them once you have finished.
array_shift($arr);
array_shift($arr);
Now you are left with -
Array
(
[0] => localhost
[1] => test
[2] => images
[3] => small
[4] => ima1.jpg
)
Providing the URL's are the same for all images, you can simply replace the fourth element ($arr[3]) with the relevant size and then reassemble your URL using the implode() function.
array_unshift($arr,'/'); // adds an element to the beginning of an array
array_unshift($arr,'http:');
$finalURL = implode('/',$arr);
Relevant documentation -
explode() - http://www.php.net/manual/en/function.explode.php
implode() - http://php.net/manual/en/function.implode.php
array_shift() - http://php.net/manual/en/function.array-shift.php
array_unshift() - http://www.php.net/manual/en/function.array-unshift.php

replacing certain images with certain words

i want to change the word :)) to a smily img before displaying it from database with php how can i do that
A solution would be to use the str_replace function.
For instance (Using ":-)", which I like more than your ":))" -- only a matter of taste ^^ Up to you to use the "right one") :
$str = "This is a sentence with a smiley :-)";
$new_str = str_replace(
array(
':-)',
),
array(
'<img src="smiley.png" alt=":-)" />'
),
$str
);
echo $new_str;
Will get you this output :
This is a sentence with a smiley <img src="smiley.png" alt=":-)" />
i.e. the smiley has been replaced with an image.
Note that I used an array for the first and second parameter, when calling str_replace : if you have other smileys, you can just add them to those two arrays (the first array being for the "searched" string, and the second for the "replacement").
(What I mean is : no need to call str_replace several time : one time, using arrays, should be enough for several replacements)
And, as a sidenote : I used the original "text" of the smiley for the alt attribute of the img tag : this way, if the image cannot be displayed, the browser will display the textual version of the smiley -- which is better than nothing.
You could use something like:
str_replace(':))', '<img src="path to your image" title="image title" />', $string);
If you want to replace multiple 'smileys', use arrays:
$find = array(
':)',
':('
);
$replace = array(
'<img src="path to happy image" title="" />',
'<img src="path to sad image" title="" />');
);
str_replace($find, $replace, $string);
You can use something like the following. Create a new replacement for each image you've got.
$message = str_replace(":)", "<img src='happy.png' alt=':)'/>", $message);
$message = str_replace(":(", "<img src='unhappy.png' alt=':('/>", $message);
This will turn $message "I'm happy :)" into "I'm happy <img src='happy.png' alt=':)'/>". The alt tag reveals the original smiley when users don't see images.

Categories