首页 > 解决方案 > Symfony __construct 用法

问题描述

我对 Symfony(第 4 版)比较陌生,并试图实现__construct依赖注入的方法。

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

路线.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
    }
}

如果你愿意的话,我在阅读文档之前想出了这个临时方案,它几乎完全详细地说明了这一点(我得到了一个 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: ".+"

在此处输入图像描述

我在这里想念什么?

标签: phpsymfonyconstructorsymfony4php-7.1

解决方案


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

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


推荐阅读