【问题标题】:Silex Controller Dependency InjectionSilex 控制器依赖注入
【发布时间】:2016-02-01 19:18:49
【问题描述】:

我正在尝试将依赖项注入到我的 Silex 控制器中,因为我需要在我的控制器中使用 user 类型的对象并用它处理一些东西。

$app->mount("/users", new \MyApp\Controller\Provider\User($user));

我通过实现ControllerProviderInterface实现了控制器:

class User implements ControllerProviderInterface{
    protected $user;

    public function __construct($user){
        //...
    }

    public function connect(Application $app)
    {
        //...
    }
}

路由和方法都在控制器中设置。没有依赖注入一切正常。但是只要我编辑代码并添加注入,我就会得到以下错误:

...::__construct() 缺少参数 1

当我创建对象时,我将该参数发送给它,但不知何故,Silex 在没有传递任何参数的情况下使用构造函数创建了一个实例。

【问题讨论】:

    标签: php api rest dependency-injection silex


    【解决方案1】:

    另一种方法是使用ServiceController 而不是ControllerProvider。您可以通过这种方式获得更熟悉的依赖注入感觉。

    $app->register(new Silex\Provider\ServiceControllerServiceProvider());
    
    $app["user"] = function () {
        return new User();
    };
    $app["user.controller"] = function () use ($app) {
        return new UserController($app["user"]);
    };
    
    $app->get("/users/{id}", "user.controller:get");
    

    ...

    class User implements UserInterface
    {
        // ...
    }
    

    ...

    class UserController
    {
        protected $user;
    
        public function __construct(UserInterface $user)
        {
            $this->user = $user;
        }
    
        public function get(Request $request, $id)
        {
            $this->user;
    
            // Do stuff
        }
    }
    

    参考:http://silex.sensiolabs.org/doc/providers/service_controller.html

    【讨论】:

    • 这看起来更熟悉。我想我会使用 ServiceController,因为它感觉更像是我们所知道的依赖注入。感谢您的回答和帮助!
    【解决方案2】:

    Silex 采用不同于您可能习惯或预期的依赖注入方法。 Silex\Application 是在 Silex 应用程序的几乎任何上下文中都可用的依赖注入容器。您使用 $app 注册您的依赖项,这些依赖项在您可能需要的任何上下文中通过 $app 注入。以下是您在您的情况下可能会做的事情的示例。

    $app["user"] = function () {
        return new \MyApp\Service\User();
    };
    
    $app->mount("/users", new \MyApp\Controller\Provider\User());
    

    ...

    class User implements ControllerProviderInterface
    {
        public function connect(Application $app)
        {
            $controller = $app["controller_factory"];
    
            $controller->get("/{id}", array($this, "get"));
    
            return $controller;
        }
    
        public function get(Application $app, Request $request, $id)
        {
            $user = $app["user"];
    
            // Do stuff
        }
    }
    

    Silex 中的依赖注入是不同的,它需要一点时间来适应,但是一旦你适应了它,就会很愉快地使用它并且它非常高效。

    【讨论】:

      【解决方案3】:

      这个接受的答案不是问题的答案。答案中描述的东西也不是依赖注入,也不是它的真正粗略形式。它更像是将 $app 硬编码到您的控制器中。

      问题中的代码无需更改即可工作。连接函数和构造函数中的代码可能有助于找出问题所在。我确定不是挂载电话。

      【讨论】:

      • 你有什么建议?我可以通过 $app 对象注入依赖项,但是是的,这不是最漂亮的方式。也许你可以举例说明它应该如何正确完成。我的代码不起作用,我无法弄清楚错误在哪里。谢谢
      • @bloodstix,我的目标是展示惯用的 Silex 方法。就像我在回答中所说的那样,Silex 采用不同的方法来注入依赖项。这不是大多数人在想到依赖注入时所想到的,但它具有相同的目的。你可能会说这不是严格的依赖注入,但这真的不是我的意思。
      • 不,它没有。它只是没有为您提供自动此功能。在 $app 中注册您的单个依赖项,并为需要依赖项的类提供 $app 上组件的具体索引。那将是依赖注入。要求具体的东西,而不是容器。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      • 2018-04-16
      • 2018-10-21
      • 2015-12-10
      • 1970-01-01
      相关资源
      最近更新 更多