Str_replace with subject passed by reference - php

Given the following example:
public function replaceMyText($search, $replace, &$content)
{
$newContent = str_replace($search, $replace, $content, $count = 1)
$content = $newContent;
}
Can this cause a Warning that only variables can be passed by reference? If so, I can't fully understand why.
Should I assigned the $content to another variable before passing it to the str_replace function?

<?php
function replaceMyText($search, $replace, &$content)
{
$newContent = str_replace($search, $replace, $content, $count = 1);
$content = $newContent;
}
replaceMyText("123", "456", "123456");
using this function without variable will get a fatal error
Fatal error: Only variables can be passed by reference in /usercode/file.php on line 8
because
No other expressions should be passed by reference, as the result is undefined.
from http://php.net/manual/en/language.references.pass.php
you just can using by this
$a = "123456";
replaceMyText("123", "456", $a);
echo $a;
Sorry for my bad english. I hope it can help you.

EDIT
Please try this code :
function replaceMyText($search, $replace, $content)
{
$newContent = str_replace($search, $replace, $content,$count=1);
return $newContent;
}
$searchValue = "test";
$replaceWith = "magic trick";
$actualContent = "This is a test.";
$replaced = replaceMyText($searchValue,$replaceWith,$actualContent);
echo $replaced;

Related

HOw to make this php class work as expected

Can anyone see what i have done incorreclty using this class it should change the word before to after but it just sits there doing nothing.
The second php pgm is the actual classs I am using..
<?php
include("parse.inc.php");
$bob = new parseClass();
$tag = "{Before}";
$replacement = "After";
$content = "My animal runs around all over the place and his name is {Before}.";
$bob->ReplaceTag($tag, $replacement, $content);
echo $bob;
?>
parse.inc.php (file name)
***************************
<?php
Class parseClass {
function ReplaceTag($tag, $replacement, $content) {
$content = str_replace($tag, $replacement, $content);
return $content;
}
}
// END Class parseClass
?>
In your case, you pass the content into class's function
Therefore, you should store the return value into variable first
$result = $bob->ReplaceTag($tag, $replacement, $content);
echo $result;
You just need to store the result of your function in a local variable, and print that.
$result = $bob->ReplaceTag($x, $y, $z);
print($result);
I guess you want to print the string having be replaced,so you should :
$result = $bob->ReplaceTag($tag, $replacement, $content);
echo $result;
Why are you use echo to print class?If you want to do this,please use "var_dump" or 'print_r' instead;
If the hard requirement is that you want to be able to echo the instance of parseClass, try this:
class parseClass
{
private $content;
public function ReplaceTag($tag, $replacement, $content)
{
$this->content = str_replace($tag, $replacement, $content);
}
public function __toString()
{
return $this->content;
}
}
$bob = new parseClass();
$tag = "{Before}";
$replacement = "After";
$content = "My animal runs around all over the place and his name is {Before}.";
$bob->ReplaceTag($tag, $replacement, $content);
echo $bob;
For reference, see:
http://php.net/manual/en/language.oop5.magic.php#object.tostring
Simply replace these two lines
$bob->ReplaceTag($tag, $replacement, $content);
echo $bob;
with
$content = $bob->ReplaceTag($tag, $replacement, $content);
echo $content;

Trying to call a function inside preg_replace

$string = 'Hello [user=1]';
$bbc = array('/\[user=(.*?)\]/is');
$replace = array(user('textlink',$1));
$s = preg_replace($bbc , $replace, $string);
echo $s
How do I change $1 in preg_replace with a function?
If I understand you correctly, you want to execute user() function on each match? As mentioned in comments, use the preg_replace_callback() function.
<?php
$string = 'Hello [user=1]';
$s = preg_replace_callback(
'/\[user=(.*?)\]/is',
function($m) {return user('textlink', $m[1]);},
$string
);
echo $s;
You may use a preg_replace_callback_array:
$string = 'Hello [user=1]';
$bbc = array(
'/\[user=(.*?)\]/is' => function ($m) {
return user('textlink',$m[1]);
});
$s = preg_replace_callback_array($bbc, $string);
echo $s;
See PHP demo.
You may add up the patterns and callbacks to $bbc.

Creating a function to act on many variables

php noob here trying to create a function but can't quite find the resource on the web that rids my confusions. Here it goes;
I want to create a function which takes a variable name, for example
Thief's Wit (4)
And converts it to
thiefswit.jpg
So far, here is what I have
THIS CODE IS LOADED TO TEST MY FUNCTION
require_once 'functions.php';
$mod = "Thief's Wit (4)";
convertImage($mod);
echo $mod;
?>
THIS CODE IS THE ACTUAL FUNCTION
function convertImage($string)
{
$string = preg_replace('/\s+/', '', $string);
$string = str_replace("'", "", $string);
$stringlength = strlen($string);
substr ($string, 0, ($stringlength-4));
$string = strtolower ($string);
$string = "$string" . ".jpg";
return $string;
}
?>
The format of the strings will always be
NAME HERE (4)
which is why I substr the length-4.
When I run this function, it echoes the original string.
Any help here?
I'm new to PHP and don't really understand
a) What the 'return' does at the end of the function and
b) Does the function inherently know to replace "$string" with the variable you tell it to act on in another file? In this case $mod.
Thanks!
You need to save the output of the function:
$mod = "Thief's Wit (4)";
$mod = convertImage($mod); // save the return value to $mod variable
echo $mod;
The return value of a function is the value you get from calling a function. So convertImage($mod) will have the value that you return. At this point, you need to store the results to a variable, which you can do by doing $mod = convertImage($mod);
An alternative would be to "pass by reference", where modifying the arguments of your function will modify the variables themselves.
function convertImage(&$string) // use &$string to pass by reference
{
$string = preg_replace('/\s+/', '', $string);
$string = str_replace("'", "", $string);
$stringlength = strlen($string);
substr ($string, 0, ($stringlength-4));
$string = strtolower ($string);
$string = "$string" . ".jpg";
//return $string; this won't be needed anymore
}
...
$mod = "Thief's Wit (4)";
convertImage($mod);
echo $mod;
You have to either return the new string you created
$mod = convertImage($mod);
Or pass by reference, which means that the function convertImage is working with the same reference to the passed in string as its caller
function convertImage(&$string) {...}
convertImage($mod); // $mod will point to a new string after the call
function convertImage(&$string) {
$string = strtolower(preg_replace("/[^a-zA-Z]+/", "", $string));
}
should do all you need - it will strip any punctuation and numbers etc, and make it lower case.
edited to allow passing by reference
You aren't assigning the variable value anywhere. To get the actual result, you'd have the function return value to a variable, like so:
$mod = convertImage($mod);
Once the actual function output is stored in a variable, you'll be able to use it anywhere as you like.
Demo: http://codepad.org/naFB74K6
<?php
function convertImage(&$string)
{
$string = preg_replace('/\s+/', '', $string); //Thief'sWit(4)
$string = str_replace("'", "", $string); //ThiefsWit(4)
$string = substr($string, 0, strlen($string)-3); //ThiefsWit
$string = strtolower($string); //thiefswit
return $string.".jpg";
}
$mod = "Thief's Wit (4)";
convertImage($mod);
echo $mod;
?>

How to find a string in a variable using PHP and regular expressions

I am trying to find the word and add a number next to it. How could he do? I tried with the code below, but I could not. Could anyone help me?
Thank you!
$string = 'I220ABCD I220ABCDEF I220ABCDEFG'
if (preg_match("/I220.*/", $string, $matches)) {
echo $matches[0];
}
Expected result:
I220ABCD9
I220ABCDEF10
I220ABCDEFG11
Use preg_replace_callback instead like this:
$str = 'I220AB FRRRR CD I221ABCDEF I220AB DSFDSF CDEFG';
$repl= preg_replace_callback('~(I220[^\s]+)~', function($m) {
static $i=9;
return $m[1] . $i++;
}, $str);
echo $repl\n"; // I220AB9 FRRRR CD I221ABCDEF I220AB10 DSFDSF CDEFG
I dont know what your requirnments for adding the number at the end are so i just incremeneted during the loop;
$string = 'I220ABCD I220ABCDEF I220ABCDEFG';
$arrayStrings = explode(" ", $string);
$int = 9;
$newString = '';
foreach($arrayStrings as $stringItem)
{
if (preg_match("/I220.*/", $stringItem, $matches))
{
$stringItem = $stringItem.$int;
$newString = $newString.$stringItem." ";
$int++;
}
}
echo $newString;
Use preg_replace_callback():
$string = 'I220ABCD I220ABCDEF I220ABCDEFG';
// This requires PHP5.3+ since it's using an anonymous function
$result = preg_replace_callback('/I220[^\s]*/', function($match){
return($match[0].rand(0,10000)); // Add a random number between 0-10000
}, $string);
echo $result; // I220ABCD3863 I220ABCDEF5640 I220ABCDEFG989
Online demo.
You'll need to use a catch block in your regex e.g. "/I220([^ ]+)/" and if you want them all, you'll need to use preg_match_all, too.
preg_replace_callback with your needs:
$string = 'I220ABCD I220ABCDEF I220ABCDEFG';
class MyClass{
private static $i = 9;
private static function callback($matches){
return $matches[0] . self::$i++;
}
public static function replaceString($string){
return preg_replace_callback('/I220[^\s]+/',"self::callback",$string);
}
}
echo(MyClass::replaceString($string));
of course you can edit to class to initialize the way you want

PHP preg_quote in replacement string

I use preg_replace and I want to include a url inside the replacement string. How do I quote that string? It appears preg_quote is only for the search pattern.
$replace = '\1'.addslashes($url).'\3'.addslashes($title).'\4';
Escapes are needed
addslashes is not sufficient
preg_quote escapes too much
See this demo.
As Mario commented you can use addcslashes($str, "\\$").
Unfortunately there is no generic way to do this, but addslashes should be enough in most cases.
For maximum safety you can use the ${1} syntax. E.g.
$replace = '${1}'.addslashes($url).'${3}'.addslashes($title).'${4}';
If you really want to be totally bulletproof, use a callback replacement function with preg_replace_callback(). The string returned from the callback function is used entirely as-is, so you don't have to worry about mixing replacement syntax with normal text.
Example with preg_replace_callback():
class URLReplacer {
public $pattern = '/my regex/';
public $url;
public $title;
function __construct($url, $title) {
$this->url = $url;
$this->title = $title;
}
function _callback($matches) {
return $matches[1].$url.$matches[3].$title.$matches[4];
}
function replace($subject) {
return preg_replace_callback($this->pattern, array($this, '_callback'), $subject);
}
}
$repl = new URLReplacer($url, $title);
$replaced = $repl->replace($subject);
You did not provide an example, so I compiled one on my own. The working solution I came up with is using a simple callback function:
$url = 'http://example.com/';
$title = 'Make it Complex \4';
$subject = 'Call \\4 " $me an url';
$pattern = '/(.*)an()( )(url)/';
$replace = function($m) use ($url, $title)
{
return "$m[1]$url$m[3]$title$m[4]";
};
$result = preg_replace_callback($pattern, $replace, $subject);
Result:
Call \4 " $me http://example.com/ Make it Complex \4url
The callback function is a so called anonymous function Docs which makes it easy to edit the code in place.
In case you need this more often you can put that into a function of your own, probably to make it more re-useable. You can even go to that far and create yourself your own pattern to replace subgroup matches and variables. For examle {\1} stands for the subpattern 1 match, {$2} for the second variable. Wrapping this into a function of it's own:
$patternf = function()
{
$values = func_get_args();
$mask = $values ? array_shift($values) : NULL;
return function($matches) use ($mask, $values)
{
$parts = preg_split('/({[\\\\\\$][0-9]{1,3}})/', $mask, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($parts as &$part)
if (preg_match('/^{([\\\\\\$])([0-9]{1,3})}$/', $part, $p))
$part = $p[1] == '\\' ? $matches[(int)$p[2]] : $values[$p[2]-1];
return implode('', $parts);
};
};
Would allow you to make the replacement more handy:
$replace = $patternf('{\1}{$1}{\3}{$2}{\4}', $url, $title);
$result = preg_replace_callback($pattern, $replace, $subject);
Demo. Wrapping this into a function of it's own:
function preg_replace_subst($pattern, $replace, $subject)
{
$values = func_get_args();
$pattern = array_shift($values);
$mask = array_shift($values);
$subject = array_shift($values);
$callback = function($matches) use ($mask, $values)
{
$parts = preg_split('/({[\\\\\\$][0-9]{1,3}})/', $mask, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($parts as &$part)
if (preg_match('/^{([\\\\\\$])([0-9]{1,3})}$/', $part, $p))
$part = $p[1] == '\\' ? $matches[(int)$p[2]] : $values[$p[2]-1];
return implode('', $parts);
};
return preg_replace_callback($pattern, $callback, $subject);
}
Would give it an easy interface:
$url = 'http://example.com/';
$title = 'Make it Complex \4';
$subject = 'Call \\4 " $me an url';
$pattern = '/(.*)an()( )(url)/';
$replace = '{\1}{$1}{\3}{$2}{\4}';
$result = preg_replace_subst($pattern, $replace, $subject, $url, $title);
But with many substitution variables it should be possible to pass them as an array probably otherwise it gets a bit lengthy.
Using the e modifier with preg_replace (and why it does not work)
When using the e modifier, the matches get replaced in the replace string and it then get's evaluated. As other variables do not get escaped, the matches do interfere with PHP variable substitution, which is dangerous:
$url = 'http://example.com/';
$title = 'Make it Complex \4';
$subject = 'Call me an url.';
$pattern = '/(.*)an()( )(url)/e';
$replace = '"$1{$url}$3{$title}$4"';
$result = preg_replace($pattern, $replace, $subject);
Outputs:
Call me http://example.com/ Make it Complex \4url.
As written, the first e-modifier example is broken because $ won't get escape in $subject, so PHP would have looked for unset variables. That's dangerous, too. I came up with a variant, it solves that issue but it can't handle double-quotes in the subject:
$url = 'http://example.com/';
$title = 'Make it Complex \4';
$subject = 'Call \\4 " $me an url';
$pattern = '/(.*)an()( )(url)/e';
$replace = "'\$1'.\$url.'\$3'.\$title.'$4'";
Output:
Call \4 \" $me http://example.com/ Make it Complex \4url
^ problem, not in input.
So not really fool-proof, that's why it needs the callback function because it gets the matching sub-patterns unquoted.
To make it obvious one is escaping any potential back-references in the $replacement parameter of preg_replace(), use a function:
function preg_quote_replacement($input) {
return addcslashes($input, '\\$');
}
In OP's case:
$subject = preg_replace(
$pattern,
'\1'.preg_quote_replacement($url).'\3'.preg_quote_replacement($title).'\4',
$subject
);
You should use Prepared Patterns. It works like Prepared Statements in SQL:
Pattern::inject("\1#url\2#url\3", ['url' => $input]);

Categories