Is it possible to make something like that:
$array = array('id' => '5', 'something_else' => 'hi');
function some_function($id, $something_else)
{
echo $something_else;
}
some_function(extract($array));
This code is giving me true/false and not $id,$something_else, etc..
It is important for me to do something like that, because I have different list of variables for each function ( I'm working on my ( let's call it ) "framework" and I want to pass list of variables instead of array with variables. This code is actually going in my router so it's not quite that simple, but in the end it comes to that ).
I assume you know how your array is built. So, why do not you just pass an array as a parameter and then use it in your function ?
If you do something like this you can access to your array's values :
echo $array['something_else'];
And build your function like this :
$array = array('id' => '5', 'something_else' => 'hi');
function some_function($an_array)
{
echo $an_array['something_else']; // value for something_else
}
some_function($array);
Or if you don't want to change function's parameters, call it like this :
some_function($array['id'], $array['something_else']);
Related
In the past few years I've used this formula to read parameters in my methods inside my php classes:
$params = func_get_args();
if(is_array($params[0])){
foreach($params[0] as $key => $value){
${$key} = $value;
}
}
And it works fine, as if I pass something like this:
$class->foo(array('bar' => 'hello', 'planet' => 'world'));
I will have in my foo method the variables bar and planet with their relative values.
But what I'm asking is: Is there any better way to do it? Something that maybe I can encapsulate in another method for example?
UPDATE
So, taking in consideration rizier123 comment, and after a chat with a friend of mine, I nailed down what I think is the better way pass parameters to function. As I know that I will always pass just one parameter to the function, which is always going to be an array, there's no need to call the func_get_args() function, but I better to expect an array all the time and by default I set an empty array, like in the following example:
class MyClass{
public function MyMethod(array $options = array()){
extract($options);
}
}
$my = new MyClass();
$my->MyMethod(array('name' => 'john', 'surname' => 'doe'));
// Now MyMethod has two internal vars called $name and $surname
Yes you can use extract() to convert your arrays to variables, like this:
extract($params[0]);
There is a new feature from PHP 5.6, it's called Variadic functions
http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list
function foo(...$arguments) {
foreach ($arguments as $arg) {
var_dump($arg);
}
}
foo('1', 2, true, new DateTime('now'));
You can do this with PHP built-in function extract().
Use it this way:
$var_array = array("color" => "blue",
"size" => "medium",
"shape" => "sphere");
extract($var_array);
When you run echo $color, $size, $shape; it outputs:
blue, medium, sphere
Hi all i have a function in a class which will print all the variable pass for this function
Class Code :
<?php
class MyPrintClass {
public function printVaraible() {
var_dump(func_get_args())
}
}
$printVar = new MyPrintClass;
?>
if i use like below its correctly working and printing all the values pass.
$print->printVaraible('value1','Value2',20);
The output i got for above cmd
array (size=1)
0 => string 'value1' (length=6)
1 => string 'value2' (length=6)
2 => string 'value3' (length=6)
if i use like blow its showing as a single array.. i want the value seperated.. how its possible ?
function getVal(){
global $printVar;
$print->printVaraible(func_get_args());
}
I need to pass the value like below
getVal('value1','Value2',20);
and i need the output as
array (size=1)
0 => string 'value1' (length=6)
1 => string 'value2' (length=6)
2 => string 'value3' (length=6)
Currently i get NULL as the output
Updated Question Based On the Answer Given By deceze
** I Also had a small change in my code**
Class Code :
<?php
class MyPrintClass {
public function printVaraible($tag,$value) {
echo $tag.' == '.$value;
var_dump(func_get_args());
}
}
$printVar = new MyPrintClass;
?>
Converted Class To Function By
<?php
function getVal($tag,$value) {
global $printVar;
call_user_func_array([$printVar, 'printVariable'], $tag,$value,func_get_args());
}
?>
If i try to use it as below i get error
<?php getVal('first','second','third,'fourth'); ?>
Warning: call_user_func_array() expects exactly 2 parameters, 4 given
call_user_func_array([$print, 'printVariable'], func_get_args());
This calls the function with separate parameters from an array. I'd question the usefulness of this though, since you'll just end up with an array from func_get_args anyway. Why not pass arrays around in the first place?
Your getting null in the return because you never return anything, from the functions above.
if you want to call a class method I suggest you look into Refection or you can also do
$a = 'printVaraible';
$class->$a(1,3); //
besides using call_user_func_array, I would also suggest looking into closures (php > 5.3 ), which will let you write them this way.
$a = function foo(){ echo 'foo'};
$a();
Last thing I would generally avoid using global, as it obscures in your code where the values come from. It is always better to inject values into the function scope and not mix that with the global, imaging hunting that global down in a large project, I just avoid them at all cost and forget they exist.
I have an Eventbus that takes a filter name as its first parameter and a Closure as second parameter. Like this:
$this->EventBus->subscribe('FilterTestEvent', function(){/*Do Something*/});
It's called like this:
$filteredValue = $this->EventBus->filter('FilterTestEvent', $anyValue);
What I want now is to pass an array as reference to the Closure that then is changed in any way (here: add elements) and then return something as the filtered value:
$item_to_change = array('e1' => 'v1', 'e2' => 'v2');
$this->EventBus->subscribe('FilterTestEvent', function(&$item){
$item['new'] = 'LoremIpsum';
return true;
});
$filtered = $this->EventBus->filter('FilterTestEvent', $item_to_change);
Now I would a print_r($item_to_change) expect to look like the following:
Array
(
[e1] => v1
[e2] => v2
[new] => LoremIpsum
)
But instead it looks like the original array:
Array
(
[e1] => v1
[e2] => v2
)
The eventbus internally stores all closures and calls them if needed through call_user_func_array() with the closure as first argument and the value as the only argument array element.
How can I achieve what it's meant to do?
Source Code to the Eventbus: http://goo.gl/LAAO7B
Probably this line:
$filtered = $this->EventBus->filter('FilterTestEvent', $item_to_change);
is supposed to return a new filtered array, not modify the original one.
So check it:
print_r($filtered);
Passing by reference is possible by modifying a function (adding &):
function filter(&$array){ //Note & mark
$array['new_index'] = "Something new" ;
}
$array = array("a"=> "a");
filter($array); //The function now receives the array by reference, not by value.
var_dump($array); //The array should be modified.
Edit:
Make your callback return the filtered array:
$this->EventBus->subscribe('FilterTestEvent', function(&$item){
$item['new'] = 'LoremIpsum';
return $item ;
});
Passing by reference should not work here, because in the source code that $value variable is swapped with another value and returned after.
Ok. I found the answer. The filter function needs to be changed so that it accepts arrays as value, in which I can save the reference. For details see difference Revision 1 and Revision 2 of the Eventbus source code, here: goo.gl/GBocgl
With Smarty 3.0, I would like to do, in order to avoid code repetition:
{$assocArray = ['param1' => 'value1', 'param2' => 'value2', ...]}
{magicFunction name='someHelper' params=$assocArray}
instead of
{$assocArray = ['param1' => 'value1', 'param2' => 'value2', ...]}
{someHelper param1=$assocArray['value1'] param2=$assocArray['value2'] ...}
I've found {call} but is not exactly what I'm looking for.
I will try to do it myself, but I'm open to suggestions (or even a code snippet to copy/paste :-p)
You could create a wrapper function named unroll_parameters defined as below.
function unroll_params ($params, &$smarty) {
return call_user_func_array ($params['name'], $params['args']);
}
That will make you able to use the following:
{unroll_params name='someFunction' args=$assocArray}
If you'd like to access $smarty inside the called function, append the value to $params['args'] before calling call_user_func_array.
return call_user_func_array (
$params['name'], array_merge ($params['args'], array ($smarty))
);
Note: If the function declaration is like: function foo ($var1,$var2, ..., $smarty)
To pass variables into functions, I do the following (as other people I'm sure):
function addNums($num1, $num2)
{
$num1 + $num2;
}
addNums(2, 2);
My question is how would I structure a function to act like Wordpress:
wp_list_categories('title_li=');
Essentially I am looking for a way to create a key/value pair in my functions.
Any advice is appreciated.
parse_str() should do what you want: http://www.php.net/parse_str
You can use parse_str to parse the string for arguments. The tricky thing is that you may not want to just allow any and all parameters to get passed in. So here's an example of only allowing certain parameters to be used when they're passed in.
In the following example, only foo, bar and valid would be allowed.
function exampleParseArgs($arg_string) {
// for every valid argument, include in
// this array with "true" as a value
$valid_arguments = array(
'foo' => true,
'bar' => true,
'valid' = true,
);
// parse the string
parse_str($arg_string, $parse_into);
// return only the valid arguments
return array_intersect_key($parse_into,$valid_arguments);
}
baz will be dropped because it is not listed in $valid_arguments. So for this call:
print_r(exampleParseArgs('foo=20&bar=strike&baz=50'));
Results:
Array
(
[foo] => 20
[bar] => strike
)
Additionally, you can browse the Wordpress Source code here, and of course by downloading it from wordpress.org. Looks like they do something very similar.