正确的实现选项是使用魔术方法 __call()
The correct implementation option is using the magic method __call()
有一个Controller
class 包含神奇的__call()
方法,它在传递参数时获取名称并创建相应名称的实例。 Controller
class 的属性 $this
传递给此 class 的构造函数,以便使用 req()
函数。
例如,我使用 3 classes 的示例从生产中重新创建了这种情况。
class One
{
public function __construct(
protected Controller $controller
) {}
public function oneTestFunc(): void {
echo $this->controller->req([__FUNCTION__, __CLASS__]);
}
}
class Two
{
public function __construct(
protected Controller $controller
) {}
public function twoTestFunc(): void {
echo $this->controller->req([__FUNCTION__, __CLASS__]);
}
}
在PHPDoc中,我已经定义了可以调用的方法。
/**
* Class Controller
* @method One one()
* @method Two two()
*/
class Controller
{
public function __call(string $name, array $args): mixed {
$name = ucfirst($name);
return new $name($this);
}
public function req(array $data): string {
return sprintf("Call function %s (class: %s)\n", ...$data);
}
}
这一切都是正确的。但是,当创建 class 的实例时,您可以调用 req()
函数,这仅在 PHPDoc 的预定义 class 中允许。
好:
$x = new Controller();
$x->one()->oneTestFunc(); // Good: Call function oneTestFunc (class: One)
$x->two()->twoTestFunc(); // Cood: Call function twoTestFunc (class: Two)
// Unacceptable! Not directly possible, the req() function is only for predefined classes.
$x->req(['click', 'clack']);
问:如何避免这种情况?为此创建一个特征以在预定义的 classes 中使用,或者对 Controller
class 进行包装并从中继承?战友们,这种情况有什么建议呢?
你可以使用特质。 Traits 专门用于代码重用和控制,没有任何类型的 class 继承。无需扩展 class 并收集其所有功能(有些可能是不必要的),特征可以帮助您控制此功能流,以及从扩展 class 的 class 收集信息=] 你使用了特征。
特征示例:
namespace App;
trait Request
{
public function req(Array $data): string
{
return sprintf("Call function %s (class: %s)\n", ...$data);
}
}
在 classes 一和二中使用特征,它应该有效:
use App\Request;
class One
{
use Request;
}
class Two
{
use Request;
}
如果您不使用自动加载,您也可以要求特征文件。
有一个Controller
class 包含神奇的__call()
方法,它在传递参数时获取名称并创建相应名称的实例。 Controller
class 的属性 $this
传递给此 class 的构造函数,以便使用 req()
函数。
例如,我使用 3 classes 的示例从生产中重新创建了这种情况。
class One
{
public function __construct(
protected Controller $controller
) {}
public function oneTestFunc(): void {
echo $this->controller->req([__FUNCTION__, __CLASS__]);
}
}
class Two
{
public function __construct(
protected Controller $controller
) {}
public function twoTestFunc(): void {
echo $this->controller->req([__FUNCTION__, __CLASS__]);
}
}
在PHPDoc中,我已经定义了可以调用的方法。
/**
* Class Controller
* @method One one()
* @method Two two()
*/
class Controller
{
public function __call(string $name, array $args): mixed {
$name = ucfirst($name);
return new $name($this);
}
public function req(array $data): string {
return sprintf("Call function %s (class: %s)\n", ...$data);
}
}
这一切都是正确的。但是,当创建 class 的实例时,您可以调用 req()
函数,这仅在 PHPDoc 的预定义 class 中允许。
好:
$x = new Controller();
$x->one()->oneTestFunc(); // Good: Call function oneTestFunc (class: One)
$x->two()->twoTestFunc(); // Cood: Call function twoTestFunc (class: Two)
// Unacceptable! Not directly possible, the req() function is only for predefined classes.
$x->req(['click', 'clack']);
问:如何避免这种情况?为此创建一个特征以在预定义的 classes 中使用,或者对 Controller
class 进行包装并从中继承?战友们,这种情况有什么建议呢?
你可以使用特质。 Traits 专门用于代码重用和控制,没有任何类型的 class 继承。无需扩展 class 并收集其所有功能(有些可能是不必要的),特征可以帮助您控制此功能流,以及从扩展 class 的 class 收集信息=] 你使用了特征。
特征示例:
namespace App;
trait Request
{
public function req(Array $data): string
{
return sprintf("Call function %s (class: %s)\n", ...$data);
}
}
在 classes 一和二中使用特征,它应该有效:
use App\Request;
class One
{
use Request;
}
class Two
{
use Request;
}
如果您不使用自动加载,您也可以要求特征文件。