惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
博客园_首页
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Vercel News
Vercel News
美团技术团队
D
Docker
WordPress大学
WordPress大学
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
The Cloudflare Blog
Y
Y Combinator Blog
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
G
Google Developers Blog
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
月光博客
月光博客
MongoDB | Blog
MongoDB | Blog
S
SegmentFault 最新的问题
GbyAI
GbyAI
Hugging Face - Blog
Hugging Face - Blog
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans

博客园 - yiyide266

[Express.js]next()函数的作用 [css]浏览器默认样式 have的实质 This comes after Chinese authorities announced an investigation against Mayday, in response to a viral video. [Linux]终端ssh远程连接如何保持 [PHP]PDO的dsn对mysql的连接影响 [javascript]端序(endian)和Buffer对象的read|write系列函数 vscode处理HTML标签两个光标的问题 intend,intent和indent [css]一个块格式化上下文(BFC)阻止外边距重叠的示例 [PHP_yaf]内部注册到spl_autoload的方法 [PHP_yaf]Yaf_Application [PHP_yaf]写在用户代码的配置项 [PHP_yaf]保存在php.ini中的配置项 [PHP]spl_autoload函数栈的向下遍历机制 [英语单词]关于战争 [MySql]1820错误码重置密码方法 [Linux]信号捕捉函数总是第一时间执行 [Linux]信号捕捉函数与exec
[PHP]回调函数参数(callable类型)的一些细节
yiyide266 · 2023-04-18 · via 博客园 - yiyide266
$foo = function(){
    echo "foo()\n";
};
$foo();
call_user_func($foo);

以上两种调用callable类型的语法是无问题的,函数可以正常运行

下面来说一下习惯上认为可行,但事实上不可行的两个调用方法
假设有以下代码,A实例的foo属性为一个callable:

class A{
    public $foo;
    public function bar(){
        echo "bar()\n";
    }
}
$t = new A();
$t->foo = function(){
    echo "foo()\n";
};

对对象调用方法的语法对callable类型无效,因为这个语法已经被php仅用于调用方法来解析,如果执行,php会提示:"Call to undefined method":

$t->foo(); //提示:"Call to undefined method"

调用call_user_func函数,第一个参数是callable有效:

call_user_func($t->foo); //正常调用

调用call_user_func函数,但使用重新指定上下文的形式无效,因为这种语法规定参数array的第二项是一个方法(或函数)名,而不是一个callable:

call_user_func(array($t, $t->foo)); //提示:"second array member is not a valid method"

想要实现重新定位上下文,只需要借助一下Closure :: bind()方法,它接受一个callable,重新返回一个指定了新的上下文的callable,然后再次用call_user_func函数普通的调用方式,就没问题:

call_user_func(Closure :: bind($t->foo, $t)); //Okay!