PHP Magic _;在类的对象属性上调用
考虑这个类的安排,特别是神奇的函数调用:PHP Magic _;在类的对象属性上调用,php,class,invoke,magic-methods,chainability,Php,Class,Invoke,Magic Methods,Chainability,考虑这个类的安排,特别是神奇的函数调用: class Barman { public function __construct() { // .. .constructor stuff - whatever } public function makeDrink() { return "vodka martini, shaken"; } } class Bar { private $arr_barmen =
class Barman {
public function __construct() {
// .. .constructor stuff - whatever
}
public function makeDrink() {
return "vodka martini, shaken";
}
}
class Bar {
private $arr_barmen = array();
public function __construct() {
$this->arr_barmen['john'] = new Barman();
}
public function __invoke($barman_id) {
echo "I have been invoked";
return $this->arr_barmen[$barman_id];
}
public function aBarFunc($param) {
return "yes it worked ," .$param;
}
}
class Foo {
public $myBar;
public function __construct() {
$this->myBar = new Bar();
}
}
我想写这样的语法
$company = new Foo();
$company->myBar('john')->makeDrink();
首选结果:
伏特加马提尼,摇一摇
实际结果:“调用未定义的方法Foo::myBar()” 使用magic方法调用myBar()应该返回一个barman对象,您可以在该对象上调用barman的任何公共方法
但是现在考虑这个(确实有用)< /P> 发生了什么事?我不喜欢那种变通方法——它不光滑。 我需要它以这种方式工作:
$company->myBar('john')->makeDrink()请帮忙?:-) 要获得链接,必须在invoke中返回Barman对象
class Barman {
public function __construct() {
// .. .constructor stuff - whatever
}
public function makeDrink() {
return "vodka martini, shaken";
}
}
class Bar {
private $arr_barmen = array();
public function __construct() {
$this->arr_barmen['john'] = new Barman();
}
public function __invoke($barman_id) {
echo "I have been invoked";
return $this->arr_barmen[$barman_id] = new Barman();
}
public function aBarFunc($param) {
return "yes it worked ," . $param;
}
}
class Foo {
public $myBar;
public function __construct() {
$this->myBar = new Bar();
}
// create a function with variable name to invoke the object
public function myBar($name) {
$mybar = $this->myBar;
return $mybar($name);
}
}
这是由您试图拨打的电话中的歧义引起的:
$company->myBar('john')->makeDrink();
因为myBar
是一个属性,PHP解释器不希望它是可调用的。它正在解析它,试图调用一个名为myBar()
的方法,该方法不存在,因此抛出错误
解决这一问题的直接方法是为口译员澄清歧义。可以通过在属性周围添加大括号来完成此操作,如下所示:
$company->{myBar}('john')->makeDrink();
class Barman {
public function __construct() {
}
public function makeDrink() {
return "vodka martini, shaken";
}
}
class Bar {
private $arr_barmen = array();
public function __construct() {
$this->arr_barmen['john'] = new Barman();
}
public function getBarman($barman_id) {
return $this->arr_barmen[$barman_id];
}
public function __invoke($barman_id) {
echo "I have been invoked \n";
return $this->arr_barmen[$barman_id];
}
}
class Foo {
private $_myBar;
public function __construct() {
$this->_myBar = new Bar();
}
// The fix
public function myBar($barman_id) {
return $this->_myBar->getBarman($barman_id);
}
}
代码现在明确表示,myBar
是一个属性,应该这样访问,但它包含一个可调用的值,并且您希望进行该调用
由于PHP5.x和PHP7.x在默认情况下处理此类歧义的方式不同,整个主题变得复杂(稍微复杂)。PHP7更改了默认值,以纠正语言内部的一些不一致。其结果是,在这样的情况下,如果您想让代码在PHP5.x和7.x之间工作,那么应该始终使用大括号来明确定义它的工作方式,而不管没有大括号的代码是否适用于您
虽然给出的示例没有涵盖您的具体情况,但有一些文档说明了中的此更改。感谢您的回复。我设计了一个可爱的解决方案,如下所示:
$company->{myBar}('john')->makeDrink();
class Barman {
public function __construct() {
}
public function makeDrink() {
return "vodka martini, shaken";
}
}
class Bar {
private $arr_barmen = array();
public function __construct() {
$this->arr_barmen['john'] = new Barman();
}
public function getBarman($barman_id) {
return $this->arr_barmen[$barman_id];
}
public function __invoke($barman_id) {
echo "I have been invoked \n";
return $this->arr_barmen[$barman_id];
}
}
class Foo {
private $_myBar;
public function __construct() {
$this->_myBar = new Bar();
}
// The fix
public function myBar($barman_id) {
return $this->_myBar->getBarman($barman_id);
}
}
用法:
$company = new Foo();
$drink = $company->myBar('john')->makeDrink();
echo $drink; // vodka martini, shaken
它是如何工作的?
Foo->myBar变为私有(Foo->$\u myBar)
我们在Foo中创建了一个名为myBar的公共函数
我们在酒吧里创建了一个“getBarman”函数,这个函数从Foo->myBar('john')调用
再多几个步骤——现在没有歧义了——Foo->myBar()始终是一个函数
干杯
M我相信你可以在它周围加上大括号:
$company = new Foo();
$drink = ($company->myBar)('john')->makeDrink();
echo $drink; // vodka martini, shaken
你能澄清一下你使用的是什么PHP版本吗?\(这与此相关)。PHP7.2在这种情况下你是正确的,这是他将遇到的下一个问题。然而,他遇到的错误是试图访问
myBar
属性;ie在它尝试执行\uu invoke()
调用之前抛出错误。是的,正确,这就是为什么创建了一个具有相同名称(属性)的函数。感谢@Harish的响应。不幸的是,这并不能解决这个问题,因为“return$this->arr_barman[$barman_id]=new barman();”只是覆盖了以前由myBar构造函数创建的barman。