I found following solution here on StackOverflow to get an array of a specific object property from array of objects: PHP - Extracting a property from an array of objects
The proposed solution is to use array_map
and within create a function with create_function
as following:
$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);
What happens?: array_map
runs through each array element in this case a stdClass
object. First it creates a function like this:
function($o) {
return $o->id;
}
Second it calls this function for the object in the current iteration. It works, it works nearly same like this similar solution:
$catIds = array_map(function($o) { return $o->id; }, $objects);
But this solution is only running in PHP version >= 5.3 because it uses the Closure
concept => http://php.net/manual/de/class.closure.php
Now the real problem:
The first solution with create_function
increases the memory, because the created function will be written to the memory and not be reused or destroyed. In the second solution with Closure
it will.
So the solutions gives the same results but have different behaviors with respect to the memory.
Following example:
// following array is given
$objects = array (
[0] => stdClass (
[id] => 1
),
[1] => stdClass (
[id] => 2
),
[2] => stdClass (
[id] => 3
)
)
BAD
while (true)
{
$objects = array_map(create_function('$o', 'return $o->id;'), $objects);
// result: array(1, 2, 3);
echo memory_get_usage() ."\n";
sleep(1);
}
4235616
4236600
4237560
4238520
...
GOOD
while (true)
{
$objects = array_map(function($o) { return $o->id; }, $objects);
// result: array(1, 2, 3);
echo memory_get_usage() ."\n";
sleep(1);
}
4235136
4235168
4235168
4235168
...
I spend so many time to find this out and now I want to know, if it's a bug with the garbage collector or do I made a mistake? And why it make sense to leave the already created and called function in memory, when it'll never be reuse?
Here is a running example: http://ideone.com/9a1D5g
Updated: When I recursively search my code and it's dependencies e.g. PEAR and Zend then I found this BAD way too often.
Updated: When two functions are nested, we proceed from the inside out in order to evaluate this expression. In other words, it is first starting create_function
(once) and that returning function name is the argument for the single call of array_map
. But because GC forget to remove it from memory (no pointer left to the function in memory) and PHP not be able to reuse the function already located in memory let me think that there is an error and not only a thing with "bad performance". This specific line of code is an example in PHPDoc and reused in so many big frameworks e.g. Zend and PEAR and more. With one line more you can work around this "bug", check. But I'm not searching for a solution: I'm searching for the truth. Is it a bug or is it just my approach. And latter I could not decide yet.
create_function()
does not return a lambda-style function, it only returns the name of that function in a string. See the manual: nl3.php.net/manual/en/function.create-function.php It states: Returns a unique function name as a string, or FALSE on error. – Donyadoodad