何时使用call_user_func_array

时间:2017-12-24 20:14:25

标签: php call-user-func-array

我已经阅读stack关于使用call_user_func_array与仅调用该函数的其他答案,但在使用前者时我仍然无法收集。我知道你可能想要使用call_user_func_array当你不知道有多少args通过时你可以这样做:$args = func_get_args(); ......但是你不需要知道如果要在函数中使用它们的参数?

以下两项工作,我认为第一项工作开销较少。

$format = new Foo;
$method = 'somemethod';
$arg = 'somevalue';
if (method_exists($format, $method)) {
    return $format->$method($arg);
}

VS

return call_user_func_array(array($format, $method), array($arg));

使用call_user_func_array时,人们何时才能真正受益?

4 个答案:

答案 0 :(得分:2)

call_user_func_array非常有用的示例

让我们说你想要访问一个对象,但是通过静态方法,比如:

Helper::load();

嗯,这本身不会起作用,因为如果你看一下具体类它就没有静态方法:

class Helper {

  public function load()
  {
      // Do some loading ...
  }

  public function aFunctionThatNeedsParameters( $param1, $param2 )
  {
      // Do something, and $param1 and $param2 are required ...
  }
}

所以在第二个类中,我们可以这样做,因为上面的Helper类被加载到依赖注入容器中(注意这两个Helper类的名称相同,但是在不同的名称空间中):

class Helper extends DIContainer {

  public static $helper_instance = NULL;

  public static function get_instance()
  {
    if( is_null( self::$helper_instance ) )
    {
      self::$helper_instance = parent::$container['helper'];
    }

    return self::$helper_instance;
  }

  public static function __callStatic( $method, $params )
  {
    $obj = self::get_instance();

    return call_user_func_array( [ $obj, $method ], $params );
  }
}

问题是,可能有另一种方法需要参数,即使我们的加载方法没有。

因此,在这种情况下,我们可以使用Helper::load(),还可以使用Helper::aFunctionThatNeedsParameters( $param1, $param2 )

我认为这在PHP框架中经常使用,它们知道静态类通常不合适,但是他们希望能够调用方法,就好像它们是静态的一样。我希望这是有道理的。

答案 1 :(得分:2)

David Sklar在他的call_user_func_array中解决了何时使用PHP Cookbook的问题。所以,要关注OP的一个评论:

  

" ...如果要使用它们,你总是需要知道这些论点   在一个函数?"

这是call_user_func()可以派上用场的实例:

<?php

function Test(){
  $args = func_get_args();
  call_user_func_array("printf",$args);
}

Test("Candidates 2014: %s %s %s %s\n","Tom","Debbie","Harry", "Sally");
Test("Candidates 2015: %s %s\n","Bob","Sam","Sarah");

请参阅live code

使用call_user_func_array()和func_get_args()对,用户定义的函数Test()可以获取可变数量的参数。

此外,对于聚合方法非常有用(请参阅PHP Cookbook p208-210),如以下简化示例所示:

<?php
class Address {
   protected $city;

   public function getCity() {
      return $this->city;
   }
   public function setCity($city) {
      $this->city=$city;
   }
}

class Person {
     protected $name="Tester";
     protected $address;

     public function __construct() {
            $this->address = new Address;
     }
     public function getName(){
            return $this->name;
     }
    public function __call($method, $args){
           if (method_exists($this->address,$method)) {
                return call_user_func_array( array($this->address,$method),$args);
           }
    }
}

  $sharbear = new Person;
  echo $sharbear->setCity("Baltimore");
  echo "Name: ",$sharbear->getName(),"\n";
  echo "City: ",$sharbear->getCity();

请参阅live code

<强>附录

自PHP 5.6起,PHP支持variadic functionsargument unpacking,因此call_user_func()和func_get_args()可以替换为变量参数,如下所示:

<?php

function Test(...$args){

   printf(...$args);
}
$namesT = ["Timmy","Teddy","Theo","Tad"];
$namesB = ["Bobby","Bill","Brad"];

Test("T Names: %s %s %s %s\n",...$namesT);
Test("B Names: %s %s %s\n",...$namesB);

请参阅live code

答案 2 :(得分:2)

<!-- begin snippet: js hide: false console: true babel: false -->

<pre>
I use call_user_func_array when I need to call a function or php function from my ajax enabled page. 

eg.
in html and javascript:

<form id='my-form'>

<input id='name' value='Wong, Billy'>
<input id='age' value='50'>

<a href='javascript;' onClick="xjx.query('helloWorld', $('#name').val(), $('#age').val())">Show name and age</a>

<a href='javascript;' onClick="xjx.query('showName', $('#name').val())">Show name</a>

<a href='javascript;' onClick="xjx.query('showAge', $('#age').val())">Show age</a>

<a href='javascript;' onClick="xjx.post('#my-form', 'showPost', 'live long and prosper')">Show age</a>

</form>

xjx.query and xjx.post, personal javascript functions of mine will then format and submit to the php page via ajax

in php
$method = $_POST['method'];
$args = $_POST['args'];

call_user_func_array($method, $args)

function helloWorld($name, $age) {
    ....
}

function showName($name) {
    ....
}

function showAge($age) {
    ....
}

function showPost($f, $message) {
   print_r($f);
   echo $message;
}

my libs are found in github with xjx as the project name
</pre>

答案 3 :(得分:0)

假设我们有几节课

class Request 
{
    private $req;

    public function __construct($req)
    {
        $this->req = $req;
    }

    public function __call($name, $arg)
    {
        return \call_user_func_array(array($this->req,$name), $arg);
    }
}

class Get 
{
    public function load($url)
    {
        // fire an http request
    }
}

class Post 
{
    public function load($url)
    {
        // fire an http request
    }

    public function attachHeader($header=[])
    {
        // attach an header to the request
    }
}

$request_1 = new Request(new Get());
$request_1->load($url);

$request_2 = new Request(new Post());
$request_2->attachHeader($header_data);
$request_2->load($url);

在这里您可以看到我们可以使用attachHeader()来调用call_user_func_array()方法 没问题。

我希望它将对您有帮助