php - funcion - ¿Llamar a métodos de objetos en una matriz usando array_map?
php array_walk use (2)
En PHP 5.3 puedes hacer:
$props = array_map(function($obj){ return $obj->getProp(); }, $objs);
(ver funciones anónimas )
Por supuesto, esto seguirá siendo más lento que usar un bucle for
ya que tiene una invocación de función por elemento, pero creo que esto se acerca más a lo que desea.
Alternativamente, que también funciona antes de PHP 5.3 y podría ajustarse mejor a sus pautas de estilo:
function map($obj) {
return $obj->getProp();
}
$props = array_map(''map'', $objs);
O (de nuevo a PHP 5.3) podría crear una función de envoltura como esta (pero esta será la posibilidad más lenta, creo):
function callMethod($method) {
return function($obj) use ($method) {
return $obj->{$method}();
};
}
$props = array_map(callMethod(''getProp''), $objs);
Supongamos que tengo clase simple como:
class MyClass {
private $_prop;
public function getProp() {return $this->_prop;}
[....]
}
Ahora lo que quiero hacer en algún lugar que no esté en el alcance de MyClass
es obtener una matriz de $ _prop desde una matriz de objetos de MyClass
( $objs
). Esto, por supuesto, se puede hacer con un código como este:
$props = array();
foreach ($objs as $obj) {
$props[] = $obj->getProp();
}
Sin embargo, esto toma algunas líneas, especialmente cuando se formatean de esta forma (y tengo que usar dicho formato). Entonces la pregunta es: ¿si es posible hacer esto usando array_map? Una forma sería usar create function, pero realmente no me gusta en php (lambdas en php es al menos incómodo y si lo entiendo correctamente su rendimiento es como el del código evacuado, pero el rendimiento no es el punto aquí). Me cansé de buscar bastante y no pude encontrar ninguna respuesta definitiva. Pero tengo la sensación de que no es posible. Intenté cosas como array_map(array(''MyClass'', ''getProp''), $objs)
, pero eso no funciona porque el método no es estático.
Editar: estoy usando php 5.3.
Pruebe este código y vea por qué querrá usar foreach
lugar de la estructura array_map
(es una prueba muy simplista, pero muestra el punto):
error_reporting(E_ALL ^ E_STRICT);
ini_set(''display_errors'', ''on'');
class MyClass
{
private $_prop;
public function getProp() {
return $this->_prop;
}
}
$objects = array();
for ($i = 0; $i <= 1000; $i += 1) {
$array[] = new MyClass;
}
// using foreach
$start = microtime(true);
for ($i = 0; $i <= 1000000; $i += 1) {
$props = array();
foreach ($objects as $object) {
$props[] = $object->getProp();
}
}
printf(''%.5fs'', microtime(true) - $start);
// using inline anonymous function
$start = microtime(true);
for ($i = 0; $i <= 1000000; $i += 1) {
$props = array_map(function ($object) {
return $object->getProp();
}, $objects);
}
printf(''<br />%.5fs'', microtime(true) - $start);
// using stored anonymous function
$start = microtime(true);
$propGetter = function ($object) {
return $object->getProp();
};
for ($i = 0; $i <= 1000000; $i += 1) {
$props = array_map($propGetter, $objects);
}
printf(''<br />%.5fs'', microtime(true) - $start);