【问题标题】:The correct implementation option is using the magic method __call()正确的实现选项是使用魔术方法 __call()
【发布时间】:2021-06-19 15:31:51
【问题描述】:

有一个Controller 类包含神奇的__call() 方法,该方法在传递参数时获取名称并创建相应名称的实例。将Controller 类的属性$this 传递给该类的构造函数,以便使用req() 函数。

例如,我使用 3 个类的示例重新创建了生产环境中的情况。

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);
    }
}

这一切都是正确的。但是,在创建类的实例时,您可以调用req() 函数,这仅在 PHPDoc 中预定义的类中允许。

好:

$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']); 

问:如何避免这种情况?为此创建一个特征以在预定义的类中使用,或者对Controller 类进行包装,并已经从它继承?同志们,在这种情况下你有什么建议?

【问题讨论】:

  • P.S. req() 函数是对 http 请求的模仿。

标签: php oop php-8


【解决方案1】:

您可以使用特征。 Traits 专门用于代码重用和控制,无需任何类继承。无需您扩展一个类并收集其所有特性(有些可能是不必要的),trait 可以帮助您控制此功能流,并从扩展您使用 trait 的类的类中收集信息。

性状示例:

namespace App;

trait Request
{
    public function req(Array $data): string
    {
        return sprintf("Call function %s (class: %s)\n", ...$data);
    }
}

在第一类和第二类中使用 trait,它应该可以工作:

use App\Request;

class One
{
   use Request;
}

class Two
{
   use Request;
}

如果你不使用自动加载,你也可以要求特征文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 2013-12-17
    • 1970-01-01
    • 2018-09-17
    • 2012-08-14
    相关资源
    最近更新 更多