代码之家  ›  专栏  ›  技术社区  ›  Colin Fine

在php5中是否可以进行“invoke”样式的回调?

  •  0
  • Colin Fine  · 技术社区  · 15 年前

    “array_map”等PHP函数接受回调,回调可以是简单的函数,也可以是类或对象方法:

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

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

    但是是否有语法来传递在迭代中绑定到当前对象的方法(比如prototype.js中的“invoke”)?以便可以使用以下内容:

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

    具有

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

    显然,我可以使用这个表单,或者编写一个包装函数来进行调用,甚至可以在内联中进行调用。但由于“我的方法”已经是一种方法,它似乎是围绕房子做这些之一。

    6 回复  |  直到 8 年前
        1
  •  2
  •   jmucchiello    15 年前
    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);
    
        2
  •  4
  •   troelskn    15 年前

    目前没有。当php 5.3出现时,可以使用以下语法:

    $array2 = array_map(function($obj) { return $obj->myMethod(); }, $array);
    
        3
  •  1
  •   NSSec    15 年前

    基本上,没有。没有特殊的语法可以使这变得更容易。

    在php 5.3中,我可以想到一种更高级的方法来实现这一点,因为在php中总是有不止一种方法可以实现这一点,但我认为这不一定是 更好的 比你 前额 例子:

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

    用你的前臂走吧:)

        4
  •  0
  •   stefs    15 年前
    <?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);
    
    ?>
    

    哇!

        5
  •  0
  •   Tom Haigh    15 年前

    这是一个有点愚蠢的答案,但是您可以将ArrayObject子类化,并使用它而不是普通数组:

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

    输出:

    Array
    (
        [0] => 2
        [1] => 4
        [2] => 6
    )
    
        6
  •  0
  •   soulmerge    15 年前

    我会用 create_function() 为了…好。。。在等待php 5.3时为数组映射创建一个临时函数

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