I am using preg_replace() to replace {#page} with the actual value of the variable $page. Of course I have a lot of {#variable}, not just {#page}.
For example:
$uri = "module/page/{#page}";
$page = 3;
//preg_replace that its working now
$uri_to_call = $uri_rule = preg_replace('/\{\#([A-Za-z_]+)\}/e', "$$1", $uri);
And I get the result
"module/page/3";
After update to PHP 5.4 i get the error:
Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead
And I don't know how to rewrite the preg_replace() with preg_replace_callback().
I have try to follow the answer from SO Replace preg_replace() e modifier with preg_replace_callback
Like this:
public static function replace_vars($uri) { //$uri_rule = preg_replace('/\{\#([A-Za-z_]+)\}/e', "$$1", $uri);
return preg_replace_callback('/{\#([A-Za-z_]+)\}/',
create_function ('$matches', 'return $$matches[1];'), $uri);
}
But I also get a warning:
Notice: Undefined variable: page
Which is actually true because page variable it's not set runtime-created function.
Can anyone help me?
Your problem is as you already know, that your variables are out of scope in your anonymous functions and since you don't know which one you will replace you can't pass them to the function, so you have to use the global keyword, e.g.
$uri = "module/page/{#page}";
$page = 3;
$uri_to_call = $uri_rule = preg_replace_callback("/\{\#([A-Za-z_]+)\}/", function($m){
global ${$m[1]};
return ${$m[1]};
});
Related
I just updated PHP on my server from php 5 to php 7 and I'm getting these warnings:
Warning: preg_replace_callback() [function.preg-replace-callback0]: Requires argument 2, 'chr(\1)', to be a valid callback
Warning: preg_replace_callback() [function.preg-replace-callback0]: Requires argument 2, 'chr(0x\1)', to be a valid callback
Warning: preg_replace_callback() [function.preg-replace-callback0]: Requires argument 2, 'chr(\1)', to be a valid callback
Warning: preg_replace_callback() [function.preg-replace-callback0]: Requires argument 2, 'chr(0x\1)', to be a valid callback
This is the PHP code:
private function _decode( $source )
{
$source = html_entity_decode($source, ENT_QUOTES, 'UTF-8');
$source = preg_replace_callback('/&#(\d+);/me',"chr(\\1)", $source);
$source = preg_replace_callback('/&#x([a-f0-9]+);/mei',"chr(0x\\1)", $source);
return $source;
}
The Warning is come from:
$source = preg_replace_callback('/&#x([a-f0-9]+);/mei',"chr(0x\\1)", $source);
How i can fix this?
The /e modifier (PREG_REPLACE_EVAL) is no longer supported, as noted in the PHP 7.0 migration guide. You need to use a callable function, not a string that will be evaluated as a function. In your case, replace your string function -- chr(0x\\1) -- with a Closure:
$source = preg_replace_callback(
'/&#x([a-f0-9]+);/mi',
fn($m) => chr(hexdec('0x'.$m[1])),
$source
);
The inline string replacement of \\1 to yield a valid PHP hexadecimal, like 0x21, no longer works that way in the callable: you need a hexdec call to accomplish the same.
See it in action on 3v4l.org.
If you do not yet have PHP 7.4 with short closures, you need to write that as:
$source = preg_replace_callback(
'/&#x([a-f0-9]+);/mi',
function ($m) { return chr(hexdec('0x'.$m[1])); }, // Now a Closure
$source
);
Just wondering how I can convert the following preg_replace() to preg_replace_callback() - I am having difficulty converting to preg_replace_callback() as preg_replace() is been deprecated.
$tableData['query'] = preg_replace('/{%(\S+)%}/e', '$\\1', $tableData['query']);
Replace all $string with $string variable.
Thanks heaps in advance
You can do it this way. I am assuming you know the dangers of eval, so use this at your own risk.
$locals = get_defined_vars();
$tableData['query'] = preg_replace_callback('/{%(\S+)%}/', function ($match) use ($locals) {
if (!array_key_exists($match[1], $locals)) {
// the variable wasn't defined - do your error logic here
return '';
}
return $locals[$match[1]];
}, $tableData['query']);
Additional word of warning - any 'declared' variable is fair game! Nothing to stop me having something like this inside the $tableData['query'] variable:
I am evil and want to see {%super_secret_variable%}!
I would like to know if there is a simple way to use the matched pattern in a preg_replace as an index for the replacement value array.
e.g.
preg_replace("/\{[a-z_]*\}/i", "{$data_array[\1]}", $string);
Search for {xxx} and replace it with the value in $data_array['xxx'], where xxx is a pattern.
But this expression does not work as its invalid php.
I have written the following function, but I'd like to know if it is possible to do it simply. I could use a callback, but how would I pass the $data_array to it too?
function mailmerge($string, $data_array, $tags='{}')
{
$tag_start=$tags[0];
$tag_end =$tags[1];
if( (!stristr($string, $tag_start)) && (!stristr($string, $tag_end)) ) return $string;
while(list($key,$value)=each($data_array))
{
$patterns[$key]="/".preg_quote($tag_start.$key.$tag_end)."/";
}
ksort($patterns);
ksort($data_array);
return preg_replace($patterns, $data_array, $string);
}
From my head:
preg_replace_callback("/\{([a-z_]*)\}/i", function($m) use($data_array){
return $data_array[$m[1]];
}, $string);
Note: The above function requires PHP 5.3+.
Associative Array replacement - keep matched fragments if not found:
$words=array("_saudation_"=>"Hello", "_animal_"=>"cat", "_animal_sound_"=>"MEooow");
$source=" _saudation_! My Animal is a _animal_ and it says _animal_sound_ , _no_match_";
echo (preg_replace_callback("/\b_(\w*)_\b/", function($match) use ($words) { if(isset($words[$match[0]])){
return ($words[$match[0]]);}else{
return($match[0]);}
}, $source));
//returns: Hello! My Animal is a cat and it says MEooow , _no_match_
*Notice, thats although "_no_match_" lacks translation, it will match during regex, but
preserve its key.
you can use preg_replace_callback and write a function where you can use that array index, or else you can use the e modifier to evaluate the replacement string (though note that the e modifier is deprecated, so the callback function is better solution).
This seems to work ok:
function findImageTags($string) {
$pattern = '/<div(.*?)sourcefile="([^"]+)"(.*?)>(.*?)<\/div>/s';
return preg_replace($pattern, $this->generateImage("$2"), $string);
}
function generateImage($url){
return $url;
}
But when in the generateImage function I try to do something with the argument I can't because the value of the argument is $2 instead of the real value.
So this doesn't work:
function generateImage($url){
$array = explode('.', $url);
return $array;
}
by the way replacing s with e in the pattern doesn't seem to work as I think it's deprecated.
So how can I manipulate the value of the argument in generateImage() ?
What you want is probably preg_replace_callback instead of preg_replace. Here you can use a function which returns the replacement value.
The way you coded it now, the $this->generateImage("$2") code is executed at the moment you call preg_replace. It's not passed as a callback, but instead it's executed first, and the output is passed as the callback.
If you want to execute that function, you have to pass the PHP code as a string, and use the e modifier (http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php for more info).
return preg_replace($pattern, '$this->generateImage("$2")', $string);
Or use preg_replace_callback() of course.
$var="UseCountry=1
UseCountryDefault=1
UseState=1
UseStateDefault=1
UseLocality=1
UseLocalityDefault=1
cantidad_productos=5
expireDays=5
apikey=ABQIAAAAFHktBEXrHnX108wOdzd3aBTupK1kJuoJNBHuh0laPBvYXhjzZxR0qkeXcGC_0Dxf4UMhkR7ZNb04dQ
distancia=15
AutoCoord=1
user_add_locality=0
SaveContactForm=0
ShowVoteRating=0
Listlayout=0
WidthThumbs=100
HeightThumbs=75
WidthImage=640
HeightImage=480
ShowImagesSystem=1
ShowOrderBy=0
ShowOrderByDefault=0
ShowOrderDefault=DESC
SimbolPrice=$
PositionPrice=0
FormatPrice=0
ShowLogoAgent=1
ShowReferenceInList=1
ShowCategoryInList=1
ShowTypeInList=1
ShowAddressInList=1
ShowContactLink=1
ShowMapLink=1
ShowAddShortListLink=1
ShowViewPropertiesAgentLink=1
ThumbsInAccordion=5
WidthThumbsAccordion=100
HeightThumbsAccordion=75
ShowFeaturesInList=1
ShowAllParentCategory=0
AmountPanel=
AmountForRegistered=5
RegisteredAutoPublish=1
AmountForAuthor=5
AmountForEditor=5
AmountForPublisher=5
AmountForManager=5
AmountForAdministrator=5
AutoPublish=1
MailAdminPublish=1
DetailLayout=0
ActivarTabs=0
ActivarDescripcion=1
ActivarDetails=1
ActivarVideo=1
ActivarPanoramica=1
ActivarContactar=1
ContactMailFormat=1
ActivarReservas=1
ActivarMapa=1
ShowImagesSystemDetail=1
WidthThumbsDetail=120
HeightThumbsDetail=90
idCountryDefault=1
idStateDefault=1
ms_country=1
ms_state=1
ms_locality=1
ms_category=1
ms_Subcategory=1
ms_type=1
ms_price=1
ms_bedrooms=1
ms_bathrooms=1
ms_parking=1
ShowTextSearch=1
minprice=
maxprice=
ms_catradius=1
idcatradius1=
idcatradius2=
ShowTotalResult=1
md_country=1
md_state=1
md_locality=1
md_category=1
md_type=1
showComments=0
useComment2=0
useComment3=0
useComment4=0
useComment5=0
AmountMonthsCalendar=3
StartYearCalendar=2009
StartMonthCalendar=1
PeriodOnlyWeeks=0
PeriodAmount=3
PeriodStartDay=1
apikey=ABQIAAAAJ879Hg7OSEKVrRKc2YHjixSmyv5A3ewe40XW2YiIN-ybtu7KLRQiVUIEW3WsL8vOtIeTFIVUXDOAcQ
";
in that string only i want "api==ABQIAAAAJ879Hg7OSEKVrRKc2YHjixSmyv5A3ewe40XW2YiIN-ybtu7KLRQiVUIEW3WsL8vOtIeTFIVUXDOAcQ";
plz guide me correctly;
EDIT
As shamittomar pointed out, the parse_str will not work for this situation, posted the proper regex below.
Given this seems to be a QUERY STRING, use the parse_str() function PHP provides.
UPDATE
If you want to do it with regex using preg_match() as powertieke pointed out:
preg_match('/apikey=(.*)/', $var, $matches);
echo $matches[1];
Should do the trick.
preg_match(); should be right up your alley
people are so fast to jump to preg match when this can be done with regular string functions thats faster.
$string = '
expireDays=5
apikey=ABQIAAAAFHktBEXrHnX108wOdzd3aBTupK1kJuoJNBHuh0laPBvYXhjzZxR0qkeXcGC_0Dxf4UMhkR7ZNb04dQ
distancia=15
AutoCoord=1';
//test to see what type of line break it is and explode by that.
$parts = (strstr($string,"\r\n") ? explode("\r\n",$string) : explode("\n",$string));
$data = array();
foreach($parts as $part)
{
$sub = explode("=",trim($part));
if(!empty($sub[0]) || !empty($sub[1]))
{
$data[$sub[0]] = $sub[1];
}
}
and use $data['apikey'] for your api key, i would also advise you to wrpa in function.
I can bet this is a better way to parse the string and much faster.
function ParsemyString($string)
{
$parts = (strstr($string,"\r\n") ? explode("\r\n",$string) : explode("\n",$string));
$data = array();
foreach($parts as $part)
{
$sub = explode("=",trim($part));
if(!empty($sub[0]) || !empty($sub[1]))
{
$data[$sub[0]] = $sub[1];
}
}
return $data;
}
$data = ParsemyString($string);
First of all, you are not looking for
api==ABQIAAAAJ879Hg7OSEKVrRKc2YHjixSmyv5A3ewe40XW2YiIN-ybtu7KLRQiVUIEW3WsL8vOtIeTFIVUXDOAcQ
but you are looking for
apikey=ABQIAAAAJ879Hg7OSEKVrRKc2YHjixSmyv5A3ewe40XW2YiIN-ybtu7KLRQiVUIEW3WsL8vOtIeTFIVUXDOAcQ
It is important to know if the api-key property always occurs at the end and if the length of the api-key value is always the same. I this is the case you could use the PHP substr() function which would be easiest.
If not you would most probably need a regular expression which you can feed to PHPs preg_match() function. Something along the lines of apikey==[a-zA-Z0-9\-] Which matches an api-key containing a-z in both lowercase and uppercase and also allows for dashes in the key. If you are using the preg_match() function you can retrieve the matches (and thus your api-key value).