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,
);
// ...
Related
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).
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.
I have used PHP for a very long time, but not really used callbacks very much until quite recently. In the following code, the callback (the example is QueryPath, in case you're wondering, but it could be anything that accepts a callback) will add some link to an array:
// parse any product links out of the html
$aProducts = array();
qp( $html, 'a' )->each(function($index, $element){
global $aProducts;
$link = qp($element)->attr('href');
$pregMatch = preg_match('#(.*)-p-(.*)\.html#i', $link, $matches);
if( $pregMatch ) {
$product_id = (int)$matches[2];
if( !in_array($product_id, $aProducts) ) {
$aProducts[] = $product_id;
}
}
});
// print out our product array
print_r( $aProducts );
What's the alternative to using global $aProducts (if there is one)?
use use:
qp( $html, 'a' )->each(function($index, $element) use(&$aProducts) {
Note the &. This is needed, for otherwise you would be using a copy of the array. You can also use multiply values, just list them separated with a ,. E.g: use(&$aProducts, $someObj, &$someInt)
PHP.net: http://www.php.net/manual/en/language.namespaces.importing.php
I Recommend you To Don't Use global variable, instead put your code on a Class and Use $this instead global variable. it must Work
I'm using a template engine that inserts code in my site where I want it.
I wrote a function to test for something which is quite easy:
myfunction() { return '($this->data["a"]["b"] ? true : false)'; }
The problem is, $this->data is private, and I can't access it everywhere, so I have to use getData(); which causes my problem.
$this->getData()['a']['b']
does not work, and assigning the value first doesn't either because it will be used directly in an if() block.
Any ideas?
Since PHP 5.4 it's possible to do exactly that:
getSomeArray()[2]
Reference: https://secure.php.net/manual/en/language.types.array.php#example-62
On PHP 5.3 or earlier, you'll need to use a temporary variable.
You cannot use something like this :
$this->getData()['a']['b']
ie, array-access syntax is not possible directly on a function-call.
Youy have to use some temporary variable, like this :
$tmp = $this->getData();
$tmp['a']['b'] // use $tmp, now
In your case, this probably means using something like this :
function myfunction() {
$tmp = $this->getData();
return ($tmp['a']['b'] ? true : false);
}
You have to :
first, call your getData() method, and store its return value in a temporary varibale
then, use that temporary variable for your test
You don't have much choice about that, actually...
Ok... apparently there really isn't a better way, so I'm going to answer myself with a not so beautiful solution:
I created the function:
arrayGet($array, $index) { return $array[$index]; }
And used it like this:
myfunction() { return '(arrayGet(arrayGet($this, "a"), "b") ? true : false)' }
This is not pretty but works.
$this->data is always accessible, if it is protected. $object->data is not accessible from everywhere, so if you're returning $this in your code, and it is evaluated as such, it should be ok.
Btw, there is a bug in your code: The quotes need to be escaped.
myfunction() { return '($this->data[\'a\'][\'b\'] ? true : false)'; }
It is possible from PHP version 5.4.
If you don't want a temporary variable for that and your PHP version is less, than 5.4, than you still can use a few built in functions to get the first or the last element:
$x = 'first?last';
$first = array_shift(explode('?', $x));
$last = end(explode('?', $x));
$last2 = array_pop(explode('?', $x));
Edit:
!!! Please note, that in later versions( 5.4+ ) PHP will throw a notice, because end only expects variables as parameter.
I want to trigger a function based on a variable.
function sound_dog() { return 'woof'; }
function sound_cow() { return 'moo'; }
$animal = 'cow';
print sound_{$animal}(); *
The * line is the line that's not correct.
I've done this before, but I can't find it. I'm aware of the potential security problems, etc.
Anyone? Many thanks.
You can do that, but not without interpolating the string first:
$animfunc = 'sound_' . $animal;
print $animfunc();
Or, skip the temporary variable with call_user_func():
call_user_func('sound_' . $animal);
You can do it like this:
$animal = 'cow';
$sounder = "sound_$animal";
print ${sounder}();
However, a much better way would be to use an array:
$sounds = array('dog' => sound_dog, 'cow' => sound_cow);
$animal = 'cow';
print $sounds[$animal]();
One of the advantages of the array method is that when you come back to your code six months later and wonder "gee, where is this sound_cow function used?" you can answer that question with a simple text search instead of having to follow all the logic that creates variable function names on the fly.
http://php.net/manual/en/functions.variable-functions.php
To do your example, you'd do
$animal_function = "sound_$animal";
$animal_function();
You can use curly brackets to build your function name. Not sure of backwards compatibility, but at least PHP 7+ can do it.
Here is my code when using Carbon to add or subtract time based on user chosen type (of 'add' or 'sub'):
$type = $this->date->calculation_type; // 'add' or 'sub'
$result = $this->contactFields[$this->date->{'base_date_field'}]
->{$type.'Years'}( $this->date->{'calculation_years'} )
->{$type.'Months'}( $this->date->{'calculation_months'} )
->{$type.'Weeks'}( $this->date->{'calculation_weeks'} )
->{$type.'Days'}( $this->date->{'calculation_days'} );
The important part here is the {$type.'someString'} sections. This will generate the function name before executing it. So in the first case if the user has chosen 'add', {$type.'Years'} becomes addYears.
For PHP >= 7 you can use this way:
function sound_dog() { return 'woof'; }
function sound_cow() { return 'moo'; }
$animal = 'cow';
print ("sound_$animal")();
You should ask yourself why you need to be doing this, perhaps you need to refactor your code to something like the following:
function animal_sound($type){
$animals=array();
$animals['dog'] = "woof";
$animals['cow'] = "moo";
return $animals[$type];
}
$animal = "cow";
print animal_sound($animal);
You can use $this-> and self:: for class-functions. Example provided below with a function input-parameter.
$var = 'some_class_function';
call_user_func(array($this, $var), $inputValue);
// equivalent to: $this->some_class_function($inputValue);
And yet another solution to what I like to call the dog-cow problem. This will spare a lot of superfluous function names and definitions and is perfect PHP syntax and probably future proof:
$animal = 'cow';
$sounds = [
'dog' => function() { return 'woof'; },
'cow' => function() { return 'moo'; }
];
print ($sounds[$animal])();
and looks a little bit less like trickery as the "string to function names" versions.
JavaScript devs might prefer this one for obvious reasons.
(tested on Windows, PHP 7.4.0 Apache 2.4)