2009-05-05 6 views
0

PHP Funktionen wie ‚array_map‘ einen Rückruf nehmen, was eine einfache Funktion oder eine Klasse oder Objektmethode sein kann:Ist in PHP5 ein 'invoke'-Callback möglich?

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

oder

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

Aber gibt es eine Syntax, um eine Methode zu übergeben welche innerhalb der Iteration an das aktuelle Objekt gebunden ist (wie 'in Prototype.js' aufrufen)? So dass die folgenden verwendet werden:

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

mit der Wirkung von

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

Natürlich kann ich dieses Formular benutzen, oder ich kann eine Wrapper-Funktion, um den Anruf zu tätigen, schreiben und sogar die Inline . Aber da "myMethod" bereits eine Methode ist, scheint es um die Häuser herumzugehen, um eines davon zu tun.

Antwort

2
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); 
4

Derzeit nicht. Wenn PHP 5.3 herauskommt, könnten Sie die folgende Syntax verwenden:

+0

Welches ist länger und weniger offensichtlich als meine foreach-Methode. Vielen Dank. –

+0

Es ist hässlich in Ordnung, aber zumindest verwendet es keine temporären Variablen. Wenn Sie von einer funktionsorientierten Sprache wie Ruby oder Lisp kommen, erscheint es intuitiver. – troelskn

1

Grundsätzlich keine. Es gibt keine spezielle Syntax, um dies zu vereinfachen.

ich eine schicken Art und Weise denken kann dies 5.3 in PHP zu tun, da es immer mehr als ein Weg, die Dinge in PHP zu tun, aber ich würde sagen, es ist nicht unbedingt besser wäre als Ihre foreach Beispiel:

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

einfach mit Ihrem foreach gehen :)

+0

Der dritte Parameter von array_reduce() muss eine Ganzzahl sein, daher würde diese Lösung nicht funktionieren. $ ReasonsToHatePhp ++; – soulmerge

+0

Eigentlich scheint das ein Dokumentationsfehler zu sein. Der Prototyp in ext/standard/array.c: 4015 definiert es als "gemischt". – NSSec

+0

Versuchen Sie, den Code auszuführen. Sie werden bemerken, dass Sie in der ersten Rekursion 0 erhalten - und nicht ein leeres Array. – soulmerge

0
<?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!

0

Das ist ein bisschen eine dumme Antwort, aber man konnte Arrayobject und Verwendung, die anstelle eines normalen Array-Unterklasse:

<?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)); 

Gibt folgendes:

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

ich create_function() verwenden würde. .. naja ... erstelle eine temporäre Funktion für array_map beim Warten auf PHP 5.3

$func = create_function('$o', '$o->myMethod();'); 
array_map($func, $objects); 
+0

Ich kann wirklich keinen Punkt in create_function sehen und es nicht inline verwenden. Wenn Sie es der Variablen $ func zuweisen, können Sie auch eine benannte Funktion erstellen. –

+0

Inline verwenden, dann. Ich mag nicht, dass mein Quellcode zu lange (horizontal) wächst.Darüber hinaus macht es das Speichern in einer Variablen jedem, der den Quellcode betrachtet, klar, dass diese Funktion nirgendwo sonst verwendet wird. – soulmerge