PHP convert preg_replace to preg_replace_callback - php

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%}!

Related

Can't convert preg_replace() with modifier /e to preg_replace_callback()

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]};
});

how can I add a function in the replacement of preg_replace in php?

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.

preg_match PHP suggestions

I'm not too great at preg_match yet and I was wondering if someone could give me a hand.
I have an array of values e.g. array("black*", "blue", "red", "grey*") I need to find the values with a * at the end then return the word before it.
I believe preg_match() is the best way of doing it but I'm open to suggestions.
Thanks in advanced!
If you must use a regex...
$words = array_map(function($word) {
return preg_replace('/\*\z/', '', $word);
}, $arr);
CodePad.
...but you're probably better off not using regex and using something like...
$words = array_map(function($word) {
return rtrim($word, '*');
}, $arr);
CodePad.
If you want to return only the words which have a trailing *, try something like this first...
$words = preg_grep('/\*\z/', $arr);
CodePad.
The only disadvantage with this (as mentioned in the comments) is PHP will iterate twice over the array. You can simply use a foreach loop to do both of these in one loop if you wish.
Also, it is worth mentioning anonymous functions are a PHP 5.3 thing. You can still most of this code, just separate the functions into their own named functions and pass a reference to them.
If you always have an array like that (i.e. no complex strings, just word*), you really shouldn't use regular expressions, it's an overkill.
Use string functions, like strpos for searching and str_replace or rtrim for removing *.
If you don't need fancy replacing rules (like regular expressions), you should always use this function instead of preg_replace().
— from str_replace manual
Don't need to use preg_match for this - simple char lookup on the string will work:
$words = array('red*', 'grey', 'white', 'green*');
$return = array();
foreach ($words as $word) {
if ($word[strlen($word) - 1] === '*') {
$return[] = substr($word, 0, -1);
}
}
var_dump($return);

filter specific string in php

$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).

PHP Regex Question

Would it be possible to make a regex that reads {variable} like <?php echo $variable ?> in PHP files?
Thanks
Remy
The PHP manual already provides a regular expression for variable names:
[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
You just have to alter it to this:
\{[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\}
And you’re done.
Edit   You should be aware that a simple sequential replacment of such occurrences as Ross proposed can cause some unwanted behavior when for example a substitution also contains such variables.
So you should better parse the code and replace those variables separately. An example:
$tokens = preg_split('/(\{[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\})/', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
for ($i=1, $n=count($tokens); $i<$n; $i+=2) {
$name = substr($tokens[$i], 1, -1);
if (isset($variables[$name])) {
$tokens[$i] = $variables[$name];
} else {
// Error: variable missing
}
}
$string = implode('', $tokens);
It sounds like you're trying to do some template variable replacement ;)
I'd advise collecting your variables first, in an array for example, and then use something like:
// Variables are stored in $vars which is an array
foreach ($vars as $name => $value) {
$str = str_replace('{' . $name . '}', $value, $str);
}
{Not actually an answer, but need clarification}
Could you expand your question? Are you wanting to apply a regex to the contents of $variable?
The following line should replace all occurences of the string '{variable}' with the value of the global variable $variable:
$mystring = preg_replace_callback(
'/\{([a-zA-Z][\w\d]+)\}/',
create_function('$matches', 'return $GLOBALS[$matches[1]];'),
$mystring);
Edit: Replace the regex used here by the one mentioned by Gumbo to precisely catch all possible PHP variable names.
(in comments) i want to be able to type {variable}
instead of <?php echo $variable ?>
Primitive approach: You could use an external program (e.g. a Python script) to preprocess your files, making the following regex substitution:
"{([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)}"
with
"<?php echo $\g<1> ?>"
Better approach: Write a macro in your IDE or code editor to automatically make the substitution for you.

Categories