我在 StackOverflow 上找到了以下解决方案,以从对象数组中获取特定对象属性的数组:PHP - Extracting a property from an array of objects
建议的解决方案是使用array_map
并在其中创建一个函数,create_function
如下所示:
$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);
会发生什么?:array_map
在这种情况下,遍历每个数组元素是一个stdClass
对象。首先它创建一个这样的函数:
function($o) {
return $o->id;
}
其次,它为当前迭代中的对象调用此函数。它有效,它的工作原理几乎与这个类似的解决方案相同:
$catIds = array_map(function($o) { return $o->id; }, $objects);
但是这个解决方案只在 PHP 版本 >= 5.3 中运行,因为它使用了这个Closure
概念 => http://php.net/manual/de/class.closure.php
现在真正的问题:
第一个解决方案create_function
增加了内存,因为创建的函数将被写入内存并且不会被重用或销毁。在第二个解决方案中Closure
它会。
因此,这些解决方案给出了相同的结果,但在内存方面具有不同的行为。
以下示例:
// following array is given
$objects = array (
[0] => stdClass (
[id] => 1
),
[1] => stdClass (
[id] => 2
),
[2] => stdClass (
[id] => 3
)
)
坏的
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
...
好的
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
...
我花了很多时间来找出这个问题,现在我想知道,这是垃圾收集器的错误还是我犯了一个错误?为什么将已经创建和调用的函数留在内存中是有意义的,而它永远不会被重用?
这是一个运行示例:http: //ideone.com/9a1D5g
更新:当我递归搜索我的代码和它的依赖项时,例如 PEAR 和 Zend,我发现这种糟糕的方式太频繁了。
更新:当两个函数嵌套时,我们从内到外进行以评估这个表达式。换句话说,它是第一次启动create_function
(一次),返回函数名是单次调用的参数array_map
。但是因为 GC 忘记将其从内存中删除(没有指向内存中函数的指针)并且 PHP 无法重用已经位于内存中的函数,让我认为存在错误,而不仅仅是“性能不佳”的东西. 这个特定的代码行是 PHPDoc 中的一个示例,并在许多大型框架中重用,例如 Zend 和 PEAR 等等。再多写一行,您就可以解决这个“错误”,检查一下。但我不是在寻找解决方案:我在寻找真相。这是一个错误还是只是我的方法。后者我还不能决定。