我已经阅读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
时,人们何时才能真正受益?
答案 0 :(得分:2)
让我们说你想要访问一个对象,但是通过静态方法,比如:
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 functions和argument 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()
方法
没问题。
我希望它将对您有帮助