依赖注入不能与League \ Route和League \ Container

时间:2017-06-06 10:18:03

标签: php dependency-injection containers thephpleague

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

我想向我的控制器发送我的League \ Plate \ Engine(注册在我的容器中),但我一直有同样的错误: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 中,我更新了索引函数,如下所示:

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->get('League\Plate\Engine');的所有电话号码更改为$container->get('What\Ever');?那不太实用! 我可能错过了什么! 当我想要使用我的PDO对象......或其他所有对象时,问题会再次出现。

2 个答案:

答案 0 :(得分:2)

好的,所以我通过在容器本身注册我的Controllers类来解决我的问题。

例如,为了显示索引页面,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;

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

答案 1 :(得分:0)

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

您在此处添加的行正在执行此操作:

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

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

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