【问题标题】:Dependency injection not working with League\Route and League\Container依赖注入不适用于 League\Route 和 League\Container
【发布时间】:2017-11-07 07:30:57
【问题描述】:

我现在正在构建一个 Web 应用程序,但我的控制器遇到了问题。

我想向我的控制器发送我的 League\Plate\Engine(在我的 Container 中注册),但我一直遇到同样的错误:Argument 3 passed to App\Controller\Main::index() must be an instance of League\Plates\Engine, array given

这是我的文件:
dependencies.php

use League\Container\Container;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Yajra\Pdo\Oci8;
use League\Container\ReflectionContainer;

$container = new Container();

// Active auto-wiring
$container->delegate(
    new ReflectionContainer
);

// Others dependencies
// ...

// Views
$container->add('view', function () {
    $templates = new League\Plates\Engine();

    $templates->addFolder('web', __DIR__ . '/templates/views/');
    $templates->addFolder('emails', __DIR__ . '/templates/emails/');

    // Extension
    //$templates->loadExtension(new League\Plates\Extension\Asset('/path/to/public'));
    //$templates->loadExtension(new League\Plates\Extension\URI($_SERVER['PATH_INFO']));

    return $templates;
});

return $container;

routes.php

use League\Route\RouteCollection;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

$route = new RouteCollection($container);

// Page index
$route->get('/', 'App\Controller\Main::index');

// Others routes...

return $route;

Main.php

namespace App\Controller;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use League\Plates\Engine;

class Main
{
    public function index(ServerRequestInterface $request, ResponseInterface $response, Engine $templates) {
        //return $response->getBody()->write($this->templates->render('web::home'));
        return $response;
    }
}

提前谢谢你


编辑
我已经取得了进展。 我扩展了 Main 类以扩展抽象类 BaseController,如下所示:

namespace App\Controller;

use League\Plates\Engine;

 class BaseController
{
    protected $templates;

    public function __construct(Engine $templates) {
        $this->templates = $templates;
    }
}

第一个错误消失了,但又出现了一个错误。在 Main 类中,我想使用我在容器中实例化的 view 对象,但是传递给构造函数的对象是空的:

Main.php

class Main extends BaseController
{
    public function index(ServerRequestInterface $request, ResponseInterface $response) {
        echo '<pre>'.print_r($this->templates,1).'</pre>'; // Return an empty Plate Engine object
        return $response->getBody()->write($this->templates->render('web::home'));
        //return $response;
    }
}

这并不能解释为什么会出现第一个错误


编辑 2
经过一番挖掘,我终于让它工作了,但我感觉出了点问题。 我将容器中的 view 替换为 Engine 类的命名空间:

$container->add('League\Plates\Engine', function () {
    // The same as before
});

Main.php 中我更新了 index 函数,如下所示:

public function index(ServerRequestInterface $request, ResponseInterface $response) {
        $body = $response->getBody();
        $body->write($this->templates->render('web::home'));
        return $response->withBody($body);
    }

并且页面没有抛出500错误,html文件显示正确。

但是,如果我想通过 Twig 来更改模板引擎怎么办?这意味着我需要将所有对 $container-&gt;get('League\Plate\Engine'); 的调用更改为 $container-&gt;get('What\Ever'); ?这不是很实用! 我可能错过了什么! 当我想使用我的 PDO 对象...或所有其他对象时,问题会再次出现。

【问题讨论】:

    标签: php dependency-injection containers thephpleague


    【解决方案1】:

    好的,我通过在容器本身中注册我的控制器类解决了我的问题。

    例如,为了显示索引页面,Main 类调用了index 函数。在我的容器中,我调用

    $container->add('App\Controller\Main')
        ->withArgument($container->get('view'));
    

    总结:

    bootstap.php(由index.php调用)

    require __DIR__ . '/../../vendor/autoload.php';
    
    $dotenv = new \Dotenv\Dotenv(__DIR__ . '/../');
    $dotenv->load();
    
    $config = new Config(__DIR__ . '/../config/');
    
    $container = require __DIR__ . '/../dependencies.php';
    
    $route = require __DIR__ . '/../routes.php';
    
    $response = $route->dispatch($container->get('request'), $container->get('response'));
    $container->get('emitter')->emit($response);
    

    dependencies.php

    $container = new Container();
    
    // activate auto-wiring
    $container->delegate(
        new ReflectionContainer
    );
    
    // Others dependencies...
    
    // Views
    $container->add('view', function () {
        $templates = new League\Plates\Engine();
    
        $templates->addFolder('web', __DIR__ . '/templates/views/');
        $templates->addFolder('emails', __DIR__ . '/templates/emails/');
    
        // Extension
        //$templates->loadExtension(new League\Plates\Extension\Asset('/path/to/public'));
        //$templates->loadExtension(new League\Plates\Extension\URI($_SERVER['PATH_INFO']));
    
        return $templates;
    });
    
    // THIS IS THE TRICK
    $container->add('App\Controller\Main')
        ->withArgument($container->get('view'));
    // others controllers...
    
    return $container;
    

    routes.php

    $route = new RouteCollection($container);
    
    // Page index
    $route->get('/', 'App\Controller\Main::index');
    
    // Others routes...
    
    return $route;
    

    我不知道为什么或如何工作!

    【讨论】:

      【解决方案2】:

      这是可行的,因为您正在向容器注册您的控制器类,并告诉容器在构造函数中依赖注入您的 View 类..

      您在此处添加的行是这样做的:

      $container->add('App\Controller\Main') ->withArgument($container->get('view'));

      Hello World 文档示例完美地解释了它。

      http://container.thephpleague.com/3.x/constructor-injection/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-26
        • 2012-12-31
        • 1970-01-01
        • 2017-06-16
        • 1970-01-01
        • 2021-11-19
        • 1970-01-01
        • 2019-09-11
        相关资源
        最近更新 更多