Question

Les fonctions PHP telles que 'array_map' prennent un rappel, qui peut être une simple fonction ou une méthode de classe ou d'objet:

$array2 = array_map('myFunc', $array);  

ou

$array2 = array_map(array($object, 'myMethod'), $array);

Mais existe-t-il une syntaxe permettant de transmettre une méthode liée à l'itération à l'objet actuel (comme "invoke" dans Prototype.js)? Pour pouvoir utiliser les éléments suivants:

$array2 = array_map('myMethod', $array);

avec l'effet de

foreach($array as $obj) $array2[] = $obj->myMethod();

Évidemment, je peux utiliser ce formulaire ou écrire une fonction wrapper pour effectuer l'appel, et même le faire en ligne. Mais puisque «maMéthode» est déjà une méthode, il semble que l'on fasse le tour des maisons pour en faire une.

Était-ce utile?

La solution

function obj_array_map($method, $arr_of_objects) {
    $out = array();
    $args = array_slice(func_get_args(), 2);
    foreach ($arr_of_objects as $key => $obj) {
        $out[$key] = call_user_func_array(Array($obj, $method), $args);
    }
    return $out;
}

// this code
$a = Array($obj1, $obj2);
obj_array_map('method', $a, 1, 2, 3);

// results in the calls:
$obj1->method(1, 2, 3);
$obj2->method(1, 2, 3);

Autres conseils

Pas actuellement. Lorsque php 5.3 sort, vous pouvez utiliser la syntaxe suivante:

$array2 = array_map(function($obj) { return $obj->myMethod(); }, $array);

En gros, non. Il n'y a pas de syntaxe spéciale pour rendre cela plus facile.

Je peux penser à une manière plus sophistiquée de faire cela en PHP 5.3, vu qu'il y a toujours plus d'une façon de faire les choses en PHP, mais je dirais que cela ne serait pas nécessairement mieux que votre foreach exemple:

$x = array_reduce(
    $array_of_objects, 
    function($val, $obj) { $val = array_merge($val, $obj->myMethod()); return $val; },
    array() 
);

Il suffit d'aller avec votre foreach:)

<?php

// $obj->$method(); works, where $method is a string containing the name of the
// real method
function array_map_obj($method, $array) {
    $out = array();

    foreach ($array as $key => $obj)
        $out[$key] = $obj->$method();

    return $out;    
}

// seems to work ...

class Foo {
    private $y = 0;
    public function __construct($x) {
        $this->y = $x;
    }
    public function bar() {
        return $this->y*2;
    }
}

$objs = array();
for ($i=0; $i<20; $i++)
    $objs[] = new Foo($i);

$res = array_map_obj('bar', $objs);

var_dump($res);

?>

voila!

C'est une réponse un peu bête, mais vous pouvez sous-classer ArrayObject et l'utiliser à la place d'un tableau normal:

<?php

class ArrayTest extends ArrayObject {
    public function invokeMethod() {
        $result = array();
        $args = func_get_args();
        $method = array_shift($args);
        foreach ($this as $obj) {
            $result[] = call_user_func_array(array($obj, $method), $args);
        }
        return $result;
    }
}

//example class to use
class a { 
    private $a;
    public function __construct($a) { 
        $this->a = $a; 
    }

    public function multiply($n) {
        return $this->a * $n;
    }
 }

//use ArrayTest instance instead of array
$array = new ArrayTest();
$array[] = new a(1);
$array[] = new a(2);
$array[] = new a(3);

print_r($array->invokeMethod('multiply', 2));

Affiche ceci:

Array
(
    [0] => 2
    [1] => 4
    [2] => 6
)

J'utiliserais create_function () pour ... eh bien ... créer une fonction temporaire pour array_map en attendant PHP 5.3

$func = create_function('$o', '$o->myMethod();');
array_map($func, $objects);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top