Using variables in preg_replace - php

i have following string in $subject variable
<p>{{headline}}</p>
And i have a variable$headline="Hello World"
As you guess i want to replace {{headline}} With Hello World using preg-replace.
Method must be dynamic, because it's just an example for headline.

$vars = array(
'headline' => 'foo'
);
echo preg_replace_callback('/\{\{(\w+)\}\}/', function (array $m) use ($vars) {
return $vars[$m[1]];
}, '<p>{{headline}}</p>');
You might really want to look into an existing templating system with a similar syntax but based on a proper parser though, like http://twig.sensiolabs.org. Mustache also basically already does the same thing.

Related

Get string from array via property lookup, but insert a variable

I want to use property look-up on an associative array of strings, but there's a catch - I need to be able to use a variable in the string. I came up with two solutions, but both seem hacky in PHP.
$foo = [
'someProp' => 'Some value here: $$value$$.'
];
$myProp = 'someProp';
$value = 'some value';
$myString = $foo[$myProp];
$myString = str_replace('$$value$$', $value, $myString);
echo $myString;
In JavaScript, I would probably use functions instead of strings and return the string including the variable. I've heard that this is bad practice in PHP.
$foo = array(
'someProp' => function($value) {
return "Some value here: {$value}.";
}
);
$myProp = 'someProp';
$value = 'some value';
$myString = $foo[$myProp]($value);
echo $myString;
To be sure this is not an X/Y problem, I will say that my goal is to abstract my error messages to one location in my code (the array mentioned here) and form what might be considered an error api for use throughout the application. For example:
try {
something(); //throws "MyException('someProp', 'someValue');
}
catch (MyException $e) {
$someClass->addError($e->getType(), $e->getValue());
//this function will get the string based on $type and add $value to it, then add the message to an array
}
Are either of these two approaches the way to go? The answer I'm looking for would include a more optimum solution if there is one and mature thoughts on my two proposed solutions.
From your example, is there only a single variable per message string or it could be many variables?
If there's only single variable, instead of role out your old string interpolation, you could use sprinf for this. This is more flexible in my opinion since it allows you to do many formatting types e.g. int, decimal etc
$foo = [
'someProp' => 'Some value here: %s.'
];
$myString = sprintf($myString, $value);

PHP: Specify argument variable names when calling a function?

This might seem like an academic or useless topic, but I'm curious.
When developing web pages with PHP, I often need to call functions that take several arguments. I frequently need to look up the spec for the function (on php.net or in my include files, if it's a function I defined) to remind myself what the variables are and what order they're in and what the defaults are, etc. I imagine many of you can relate to this.
A function defined like this:
function do_something_awesome ($people_array, $places_recordset, $num_cycles, $num_frogs,
$url = '?default=yes', $submit_name = 'default_submit_label') {
...
}
when called, might look like this:
$result = do_something_awesome($names, $rsTowns, $c, $f);
My question is this: I'd like to write my code in a way that reminds me of which argument corresponds to each variable, during function calls like this. Is it ever legal to call a function as follows?
$result = do_something_awesome($people_array = $names, $places_recordset = $rsTowns,
$num_cycles = $c, $num_frogs = $f);
If not in PHP, are there other languages where method calls can be made in this way?
To answer your first question:
My question is this: I'd like to write my code in a way that reminds me of which argument corresponds to each variable, during function calls like this.
AFAIK, many PHP coders do it by passing in an associative array as the only argument. However, you'll have to do your own variables checking inside the called function.
$result = do_something_awesome(array(
'people_array' => $names,
'places_recordset' => $rsTowns,
'num_cycles' => $c,
'num_frogs' => $f
));
As for:
Is it ever legal to call a function as follows?
It won't cause any PHP errors, but what you are effectively doing is:
$result = do_something_awesome( expression, expression, expression, expression );
See: PHP Functions arguments
PHP won't know to put $people_array = ... or $num_frogs = ... in their corresponding places when you decide to switch their order around. Furthermore, as DCoder said, these expressions actually take place in the current scope, and will change any pre-existing variables without letting you know.
What about using an object as the only argument:
function my_function($arguments) {
if (!is_object($arguments)) throw new Exception();
$default_values = array('arg1' => 'value1', 'arg2' => 'value2');
foreach ($default_values as $key => $default_value)
if (!isset($arguments->$key)) $arguments->$key = $default_value;
## do the job ##
}
## and then
$my_arguments = new stdClass();
$my_arguments->arg2 = 'some_value';
my_function($my_arguments);
You can try this out:
$bas = 'This is passed to the function.';
$bar = 'This will be modified.';
function foo($bar)
{
echo $bar;
}
foo($bar = $bas);
echo $bar;
The output from this script would be 'This is passed to the function.This is passed to the function.'. So like DCoder said, while you can use them and it's perfectly legal but if you had other variables with the same name as the function arguments, this will overwrite them (in this case the original $bar was overwritten).

adding the use of multiple variables to an ob_start function

I've got the following object start code; however, right now it only uses 1 variable ( $online ) .... I need to add a second variable ( $var2 ) to the code so that I can have "var2"=> $var2 under "online"=> $online. This needs to be added to the first line of code around where use (&$online) so the code knows the use this variable.
ob_start(function($c) use (&$online){
$replacements = array(
"online"=> $online
);
return preg_replace_callback("/{(\w+)}/",function($m) use ($replacements) {
return isset($replacements[$m[1]]) ? $replacements[$m[1]] : $m[0];
},$c);
});
How do I add this? Everything I try breaks the code completely.
You can add as many variables to a use as you like, just separate them as you would parameters:
function($c) use (&$online,&$var2)
Following the php documentation on closures, you should use commas. Following the php documentation on arrays, you should also use commas there. Next time try looking it up. The php manual has lots of resources on this subject.
ob_start( function($c) use (&$online, &$var2){
$replacements = array(
"online"=> $online,
"var2" => $var2,
);
// ...

Is there a php function that mimics the " " behavior?

i'm trying to create a table view helper in Zend Framework , it takes an array of models and generate an html table that displays the model properties.
The user can add extra columns to display operations like update ,delete models ,.
so the user can add a string like that
$columnContent = '<a href=\'update/$item[id]\'>update</a>' ;
note that i use simple quotes to cache the string to be evaluated later
my problem is , is there a way to evaluate that string in a context , later on ?
so i need to mimic the " " behavior of strings in Php , thanks.
something like :
// in the context , where $item is a row of an array of models :
$myVar = evaluatemyString($columnContent);
EDIT :
i'm not looking for the eval function which doesnt work in my case , ( i think ).
EDIT 2 :
i need to put the result of the in a variable too.
The eval function in PHP
eval($columnContent);
Use "templates" (the quotes are intended) instead. Have a look at intl, especially messageformatter. Also there are the good old printf()-functions (inlcuding sprintf() and so on)
Here is a simple UTF-8 safe string interpolation example. The regular expression forces variables with the following rules:
Prefixed with #
object:property notation (denotes an associative array key "object" whose value is also an associative array)
In other words, instead of variables like: $item[id]
You will have variables like: #user:id
<?php
// update
//$template = 'update';
// update
$template = 'update';
// fixture data
$db[499] = array('user' => array('id' => 499));
$db[500] = array('user' => array('id' => 500));
// select record w/ ID = 500
$context = $db[500];
// string interpolation
$merged = preg_replace_callback('/#(?:(?P<object>[^:]+):)(?P<property>[\w][\w\d]*){1}/iu', function($matches) use($context) {
$object = $matches['object'];
$property = $matches['property'];
return isset($context[$object][$property])
? $context[$object][$property]
: $matches[0];
}, $template);
echo "TEMPLATE: ${template}", PHP_EOL;
echo "MERGED : ${merged}", PHP_EOL;

Executing functions inside string

Everyone knows in PHP you can do this:
$m = "my string is {$string}";
But is taht possibile with function too? Like:
$m = "my string is {getStringValue()}";
The string expansion in {$..} goes a bit beyond just being able to execute functions. I for example used gettext with that. But you can also use tricks like that:
$html = "htmlentities"; // any callback function
// or just: $html = function($s){ return $s; }
print "even allows expressions {$html(2+3*5+rand(2,17))} here";
That's possible because PHP allows any variable expression there in order to support the simple object notation case:
print "this isn't just a {$obj->prop} string variable";
And for example I'm utilizing an object which implements ArrayAccess, where even this is a method invocation:
print "Makes some things {$_GET->ascii->html['input']} simpler";
We had a few such topics on SO, but for the life of me I can't find a good reference ...
This is not possible (and it wouldn't be very readable too, especially if the function had parameters).
You could use sprintf:
$m = sprintf("my string is %s", getStringValue());
Only variable names are expanded
http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.double
With concatenation, If I understand well what you're trying to do:
$m = "my string is {".getStringValue()."}";

Categories