php computing a variable on the fly using anonymous functions - php

Sometimes while initializing variables, you want to pass them values that are too complex to be computed in a single command, so you usually either compute a dummy variable before and then pass its value, or define a function elsewhere, and pass it's return value to our variable.
My question (wish) is, is it possible instead compute to a variable on the fly using anonymous functions?
for example, instead of use this:
$post = get_post();
$id = $post->ID;
$array = array(
'foo' => 'hi!',
'bar' => $id
);
Lets use something like this:
$array = array(
'foo' => 'hi!',
'bar' => (function(){
$post = get_post();
return $post->ID;
})
);
Code is totaly random.

In your example, the following would do just fine:
$array = array('foo'=>'hi!','bar'=>(get_post()->ID));
However, with consideration to your question being a bit more open ended and not specific to your code snippet, you may find this stackoverflow answer acceptable.
$a = array('foo' => call_user_func(
function(){
$b = 5;
return $b;
})
);
var_dump($a);

Related

PHP: Strange effect when passing array into MongoCollection#insert()

In PHP arrays are assigned by value. Hence, when I do something like this:
$a = ['a' => 'ape'];
$b = $a;
$a['b'] = 'banana';
Only $a will have the key 'b', but $b won't be modified. That also applies when either array is assigned by reference into a function and that function modifies the array.
However, there's a strange thing happening if I try to insert a document using the PECL MongoDB extension. In the following unit test the second assertion fails for me:
public function testUpdateGeneratesId()
{
$doc1 = ['author' => 'j.henning', 'title' => 'My Blog Entry'];
$doc2 = $doc1;
$this->blog->insert($doc1, ['w' => 1]);
$this->assertNotNull($doc1['_id']);
$this->assertArrayNotHasKey('_id', $doc2);
}
The #insert() generates the key '_id' on the inserted document, but I would expect the key only to be added to $doc1. However, it's created on both arrays.
Can anybody reproduce this behavior or give any explanation for it?
This sounds like a bug related to https://jira.mongodb.org/browse/PHP-410 - can you please file a new bug at https://jira.mongodb.org/browse/PHP for this?

Calling anonymous function within anonymous function (Inception)

Simple question, but tough answer? I have the following anonymous function inside a class method:
$unnest_array = function($nested, $key) {
$unnested = array();
foreach ($nested as $value) {
$unnested[] = (object) $value[$key];
}
return $unnested;
};
In the same class method I have this array, where I save anonymous functions. I.e. I create a new anonymous function using the inline create_function() and I would want to use the already defined anonymous function $unnest_array(). Is it possible?
$this->_funcs = array(
'directors' => array(
'func' => create_function('$directors', 'return $unnest_array($directors, "director");'),
'args' => array('directors')
)
);
At the moment I am getting "Undefined variable: unnest_array". Help?
Why are you using create_function in the first place? Closures replace create_function entirely, leaving it essentially obsolete in all versions of PHP after 5.3. It seems like you're trying to partially apply $unnest_array by fixing the second argument as "director".
Unless I've misunderstood you, you should be able to achieve the same result by using a closure/anonymous function (untested):
$this->_funcs = array(
'directors' => array(
'func' => function($directors) use ($unnest_array)
{
return $unnest_array($directors, "director");
},
'args' => array('directors')
)
);
The use ($unnest_array) clause is necessary to access local variables in the parent scope of the closure.

Yii gridview use outside variable in value

I have a function in my Teacher model which returns categories array.
getCaterogies() {
return array('1' => 'short tempered', '2' => 'funny', '3' => 'visionary', ...);
}
I am storing indexes in database and displaying values everywhere using the value of the array corresponding to that..
$categories = $teacher->categories;
$category = $categories[$teacher->category];
I am doing this because once somebody suggested to me not to store strings in a database which are statuses, instead store integer values, and either store the conversion in the database or define it in ht model. The problem with strings is that they are more prone to human errors in comparisons. Maybe because of case sensitiveness.
Now the problem I am facing is that while displaying values in gridview, I need to write the 2 lines in a value field, but it is an expression, and outside variables also it doesn't take.
How can I get this working for gridview?
You can use anonymous function as value which can take $row, $data params where $row holds the row number (zero-based) and $data contains the data model for the row.
That way you can have it defined inside only.
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
array(
'name'=>'..',
'value'=>function($data,$row){
$categories = $teacher->categories;
return $categories[$data->category];
},
),
),
));
And if you want to use it from outside, you can rely on PHP's use:
$categories = $teacher->categories;
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
array(
'name'=>'..',
'value'=>function($data,$row) use ($categories){
return $categories[$data->category];
},
),
),
));
I would personally recommend second one, because that way the calculation of the array will be only once and will be used in all cases.
You can write
$categories = $teacher->categories;
$category = $categories[$teacher->category];
in one line:
$category = $teacher->categories[$teacher->category];
Also, I suggest you to use another solution:
class ModelClass
{
const STATUS_SHORT_TEMPERED = 1;
const STATUS_FUNNY = 2;
const STATUS_VISIONARY = 3;
}
This allow you to use a more semantic
ModelClass::STATUS_FUNNY;
instead of less semantic
2;
Also, you can compose your array in this way:
getCaterogies() {
return array(
ModelClass::STATUS_FUNNY => 'status funny',
...
);
}
'urlCreator' => function ($action, $model, $key, $index) use($under_category) {

PHP: Can anonymous functions inside an associative array access other members of the array?

In the following example, is it possible to access the 'str' value from within the anonymous function?
$foo = array(
'str' => 'THIS IS A STRING',
'fn' => function () {
// is it possible from within here to access 'str'?
}
);
if $foo is defined in the global namespace you should be able to access it via $GLOBALS['foo']['str'] (or make it available via the global $foo; construct). If it isn't (local var, parameter, member variable, …), you have to pass it (as reference!) to the anonymous function:
$foo = array(
'str' => 'THIS IS A STRING',
'fn' => function () use(&$foo) {
echo $foo['str'];
}
);
I have found a different way to do this without using global variables:
<?php
$arr = array("a" => 12,
"b" => function($num)
{
$c = $num * 2;
return $c;
});
echo $arr["b"]($arr["a"]);
?>
Note the weird syntax of ending the array index call with method parentheses. By passing $arr["a"] as a parameter you can have access to that value (I imagine you could pass by reference as well).If you were not to pass anything into the anonymous function, you would call it like this:
$arr["b"]();
If you don't include the method parentheses it won't work.

Passing variables to functions in PHP

I have the following PHP function:
function func_name($name = 'John', $country = 'USA')
{
do something;
}
And now, am trying to pass variable to the function as follows:
func_name($name = 'Jack', $country = 'Brazil');
I know, we can pass it easily as func_name('jack', 'Brazil'); but the above function is just an example. The actual function has around 20 arguments and all have default values, and some are not at all passed to the function
So I would like to know if its proper to pass arguments as func_name($name = 'Jack', $country = 'Brazil');
No, it's not the right way to do it. foo($bar = 'baz') means you're assigning 'baz' to the variable $bar as usual. This assignment operation results in the value that was assigned, so the expression $bar = 'baz' has the value 'baz'. This value 'baz' gets passed into the function. The functions doesn't have any clue that you have assigned to a variable $bar.
In other words, PHP doesn't support named arguments.
If your function accepts many parameters, all or most of which are optional, use arrays:
function foo(array $args = array()) {
// set default values for arguments not supplied
$args += array('name' => 'John', 'country' => 'USA', …);
// use $args['name'] etc.
// you could do extract($args), then use $name directly,
// but take care not to overwrite other variables
}
foo(array('country' => 'Japan'));
Could you pass in an array?
function something($arr) {
$name = $arr['name'];
}
function something(Array("name"=>"jack", "country"=>"UK"));

Categories