【问题标题】:Symfony __construct usageSymfony __construct 用法
【发布时间】:2018-11-14 04:18:33
【问题描述】:

我对 Symfony(第 4 版)相对较新,并尝试实现 __construct 依赖注入方法。

目前,我正在通过自己的实现“注入”依赖项(在我知道 __construct 方法之前),如下所示:

routes.yaml

fetch:
    path: /fetch/{req}
    controller: App\Controller\Fetch::init
    requirements:
    req: ".+"

/fetch 路由调用init() 方法,该方法作为构造函数。

控制器类

namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;

use App\Services\Utilities; // a bunch of useful functions

class Fetch extends BaseController {

    private $u;

    public function init(Utilities $u) {

        $this->u = $u; // set the $u member with an instance of $u
    }

    private function do_fetch(){

        $this->u->prettyprint('hello service'); // use one of $u's methods
    }
}

如果你愿意的话,我在阅读the docs 之前提出了这个临时方案,它几乎完全详细地说明了这一点(我得到了一个 cookie)。

一个区别是文档使用__construct() 代替我的init() 方法。以下是上面链接的文档页面的示例:

// src/Service/MessageGenerator.php

use Psr\Log\LoggerInterface;

class MessageGenerator
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function getHappyMessage()
    {
        $this->logger->info('About to find a happy message!');
        // ...
    }
}

但是,当我将 init() 换成 __construct(),并更新 routes.yaml 时,我得到了一个错误。

// .....

class Fetch extends BaseController {

    private $u;

    public function __construct(Utilities $u) {

        $this->u = $u; // set the $u member with an instance of $u
    }
    // ....

fetch:
    path: /fetch/{req}
    controller: App\Controller\Fetch::__construct
    requirements:
    req: ".+"

它要求我向 __construct 提供一个参数,因为该方法需要一个参数 ($u),但是当 init() 充当构造函数时,情况并非如此。

此外,我觉得__construct() 方法是一个内置的钩子,Symfony 应该知道使用它,而无需我在 routes.yaml 中明确告诉它。但是,排除它也会引发错误。

routes.yaml(__construct 未明确指出)

fetch:
    path: /fetch/{req}
    controller: App\Controller\Fetch
    requirements:
    req: ".+"

我在这里错过了什么?

【问题讨论】:

  • 控制器是在调用动作之前创建的。因此,您不能将构造函数用作您的操作。添加一个操作方法并在您的路线中指向它。构造函数和动作最终都会被调用。奇怪地类似于文档中的示例。实际上,您可以有一个名为 __invoke() 的方法,这将使您的最后一个示例工作。

标签: php symfony constructor symfony4 php-7.1


【解决方案1】:

__construct 是 PHP 中的一种神奇方法。 init 方法的问题在于它不强制对象 必须 具有构建所需的对象的实例。有时不需要对象属性。在这种情况下,我建议创建一个 setter 作为可选设置该属性的一种方式。尝试将您的类属性设为私有,并且只允许它们通过 setter 和 getter 进行变异或检索...这将提供标准 API到您的对象,并避免随机状态操作。

您可以在 Symfony 的路由器中使用 DIC 来构建您的控制器,而不是通过 registering your controllers as services 扩展基本控制器类。这极大地解耦了您的代码并允许各种额外的灵活性。您应该始终支持组合而不是继承。

【讨论】:

    猜你喜欢
    • 2019-11-02
    • 2018-01-22
    • 2020-02-14
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-11
    • 1970-01-01
    相关资源
    最近更新 更多