Pass a closure to an array value - php

Please forgive me if I'm way off here but I'm trying to create a simple template parser and to do this I'm using regular expressions to find template tags and replace them with dynamic text.
I want to be able to use a closure to return the replacement text. For example:
// Example 1
$tag['\{{title:(.*)}}\'] = function($1)
{
return $1;
};
// Example 2
$tag['\{{title:(.*)}}\'] = function($1)
{
$something = ['One', 'Two', 'Three'];
return $1 . implode($something);
};
// Now do the replacements
foreach($tag as $pattern=>$replacement)
{
preg_replace($pattern, $replacement, $template);
}
I've included example 2 to explain that the result maybe dynamic and this is why I can't simply use strings.
I also feel like I need to explain why I'd need such functionality. The patterns are meant to be expandable, so other developers can add their own patterns easily.
If I've completely off the mark and this isn't going to be achievable, could you point me in the direction to achieve the same/similar functionality?
also, side note - not my main question - but is there a way to do multiple preg_replace in one go instead of looping through, seems inefficient.

Related

Is there a simple way to return WHAT is similar between 2 strings in PHP?

I've looked into the similar_text() and levenshtein() functions, but they only seem to return THAT there are similarities and the percentage of those similarities.
What I am trying to do is compare 2 strings to determine WHAT is actually similar between the two.
Basically:
<?php
$string1 = "IMG_1";
$string2 = "IMG_2";
echo CompareTheseStrings($string1,$string2); // returns "IMG_";
If this wonderful function doesn't exist, what would be the best way to accomplish this?
My end game plan is to read through a list of file names and then replace the similar text with something user defined or just remove it all together, but I don't want to replace each files unique identifier.
Reading your 'end goal' I think you're going about this completely the wrong way I think you should really be looking at str_replace
$string1 = "IMG_1";
$string2 = "IMG_2";
// you would create a loop here to insert each string
str_replace("IMG", "NEW_TERM", $string1);
If you want to remove the text altogether then just pass an empty string in as the 2nd parameter

an elegant way to matching a route

im stuck on a piece of code which is looking terrible.
i got an route as string like /people/12/edit and i want to compare it with routes in my dataset.
in the dataset there are routes like:
/people
/people/:id
/people/new
/people/:id/edit
i need to know, that my route /people/12/edit goes to the internal action for /people/:id/edit
so i had the following condition to check this:
if(preg_match("/^".preg_replace('/:id/','([0-9]*)?',preg_replace('/\//','\/',$_route['route']))."$/", $route)){
// ...
}
but it seems to be a bad solution. i have to escape the slashes, i have to replace the :id parameter, and after this, i can check if the route is matching.
but it looks terrible and has a big problem. it doenst work if the parameter is not named :id.
can you give me some hint or show a better way?
thanks in advance
update:
im not using any mvc framework. its an "build your own framework and learn task"
the routes stored on a route table:
people_index get /people people#index
people_show get /people/:id people#show
people_edit get /people/:id/edit people#edit
people_update put /people/:id people#update
people_new get /people/new people#new
people_create post /people people#create
people_delete delete /people/:id people#delete
if i call link_to 'people_index' it will display /people. the condition above is part of the routing parser. it just looking for the correct uri and return (for the edit link) people#edit. after this, i know there is an resource PeoplesController and call the edit action.
i know there are lots of great mvc frameworks for php. but i want to get more experience and rebuild some rails logic into php :)
first of all I would split this up some, preferable in a reusable way, say a function to parse the mapping first.
function createpattern( $map ) {
$map = preg_replace('/:id/', '([0-9]+|new)', $map );
//add other mappings here for example.
$map = preg_replace('/:name/', '([a-z])', $map );
return $map;
}
Or just use rusty trusty str_replace for this part.
function createpattern( $map ) {
$search = array( ':id', ':name' );
$replace = array( '([0-9]+|new)', '([a-z]+)?');
$map = preg_quote($map); //maybe use it here.
$map = str_replace($search, $replace, $map );
return $map;
}
So this
/people/:id
becomes
/people/([0-9]+|new)
Somewhere you should use preg_quote, but not after adding in the regx bits.
essentially your regx is now
\/people\/([0-9]+|new)\/... etc.
preg_quote would be used to prevent a user from adding in regular expressions of there own and messing up yours, unintentional and otherwise.

evaluate string with array php

I have a string like
"subscription link :%list:subscription%
unsubscription link :%list:unsubscription%
------- etc"
AND
I have an array like
$variables['list']['subscription']='example.com/sub';
$variables['list']['unsubscription']='example.com/unsub';
----------etc.
I need to replace %list:subscription% with $variables['list']['subscription'],And so on
here list is first index and subscription is the second index from $variable
.Is possible to use eval() for this? I don't have any idea to do this,please help me
Str replace should work for most cases:
foreach($variables as $key_l1 => $value_l1)
foreach($value_l1 as $key_l2 => $value_l2)
$string = str_replace('%'.$key_l1.':'.$key_l2.'%', $value_l2, $string);
Eval forks a new PHP process which is resource intensive -- so unless you've got some serious work cut out for eval it's going to slow you down.
Besides the speed issue, evals can also be exploited if the origin of the code comes from the public users.
You could write the string to a file, enclosing the string in a function definition within the file, and give the file a .php extension.
Then you include the php file in your current module and call the function which will return the array.
I would use regular expression and do it like that:
$stringWithLinks = "";
$variables = array();
// your link pattern, in this case
// the i in the end makes it case insensitive
$pattern = '/%([a-z]+):([a-z]+)%/i';
$matches = array();
// http://cz2.php.net/manual/en/function.preg-replace-callback.php
$stringWithReplacedMarkers = preg_replace_callback(
$pattern,
function($mathces) {
// important fact: $matches[0] contains the whole matched string
return $variables[$mathces[1]][$mathces[2]];
},
$stringWithLinks);
You can obviously write the pattern right inside, I simply want to make it clearer. Check PHP manual for more regular expression possibilities. The method I used is here:
http://cz2.php.net/manual/en/function.preg-replace-callback.php

Is it possible to render the content of a file without using eval in PHP?

I'm trying to create a simple framework in PHP which will include a file (index.bel) and render the variables within the file. For instance, the index.bel could contain the following:
<h1>{$variable_name}</h1>
How would I achieve this without using eval or demanding the users of the framework to type index.bel like this:
$index = "<h1>{$variable_name}</h1>";
In other words: Is it possible to render the content of a file without using eval? A working solution for my problem is this:
index.php:
<?php
$variable_name = 'Welcome!';
eval ('print "'.file_get_contents ("index.bel").'";');
index.bel:
<h1>{$variable_name}</h1>
I know many have recommended you to add template engine, but if you want to create your own, easiest way in your case is use str_replace:
$index = file_get_contents ("index.bel");
$replace_from = array ('$variable_a', '$variable_b');
$replace_to = array ($var_a_value, $var_b_value);
$index = str_replace($replace_from,$replace_to,$index);
Now that is for simple variable replace, but you soon want more tags, more functionality, and one way to do things like these are using preg_replace_callback. You might want to take a look at it, as it will eventually make possible to replace variables, include other files {include:file.bel}, replace text like {img:foo.png}.
EDIT: reading more your comments, you are on your way to create own framework. Take a look at preg_replace_callback as it gives you more ways to handle things.
Very simple example here:
...
$index = preg_replace_callback ('/{([^}]+)}>/i', 'preg_callback', $index);
...
function preg_callback($matches) {
var_dump($matches);
$s = preg_split("/:/",$matches[1]); // string matched split by :
$f = 'func_'.strtolower($s[0]); // all functions are like func_img,func_include, ...
$ret = $f($s); // call function with all split parameters
return $ret;
}
function func_img($s) {
return '<img src="'.$s[1].'" />';
}
From here you can improve this (many ways), for example dividing all functionalities to classes, if you want.
Yes, this is possible, but why are you making your own framework? The code you provided clearly looks like Smarty Template. You could try to look how they did it.
A possible way to run those code is splitting them into pieces. You split on the dollar sign and the next symbol which is not an underscore, a letter or an number. Once you did that. You could parse it into a variable.
$var = 'variable_name'; // Split it first
echo $$var; // Get the given variable
Did you mean something like this?

Using ereg_replace in PHP?

How do I replace using the following code?
ereg_replace("%Data_Index\[.\]%", $this->resultGData[$key ][\\1], $var)
I want to replace the number in [] %Data_Index
to $this->resultGData[$key ][\\1] same %Data_Index
and how ex %Data_Index[1] = $this->resultGData[$key][1], $var);
replace number in %Data_Index[...........] in []
to $this->resultGData[$key ][............]
same number
Try the preg_replace() function with the e modifier instead:
preg_replace('/%Data_Index\[(\d+)\]%/e', '$this->resultGData[$key][\1]', $var);
Note that this function uses Perl-compatible regular expressions instead of POSIX-extended regular expression.
your question is a little bit hard to understand
the smartest way to replace what you are asking I believe would be using a cycle
for example if you know that $this->resultGData[$key ][] has 10 elements on them you could simply do this, asuming %Data_Index[1] (are you sure it isn't $Data_Index? i'll asume that) you can try the following
$total = count($this->resultGData[$key ]); //we get the total of elements in that key
for($i=0;$i<$total;$i++)
{
$Data_Index[$i] = $this->resultGData[$key][$i];
}
now if the $key changes, you'd need to do this for every $key :)
keep practicing your english, it's a really useful tool in the IT field :) (not that i'm very a good at it either :P)

Categories