联赛路线,集装箱和PDO

时间:2018-07-23 20:03:43

标签: php dependency-injection routes containers

TL; DR;

如何为CardOnFile\Controller类提供PDO连接,以便它可以进行数据库查询? (我认为我必须使用容器,但不确定如何使用。)

背景

我想避免每次实例化需要数据库访问的对象时都与数据库建立多个连接。因此,我认为我需要实例化数据库连接(PDO)的一个副本,然后使用League \ Route和League \ Container将其注入需要的类中。

我不想将容器注入类中,因为那是服务位置。但是,我完全不确定如何将PDO对象放入需要它的类中,以便它可以正常工作。

如何使映射的可调用对象具有数据库访问权限?

代码:

/* Connect to a MySQL database using driver invocation */
$dsn = 'mysql:dbname=foo;host=localhost';
$user = 'bar';
$password = 'supersecret';

try {
    $pdo = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
    die(__FILE__ . ":" . __LINE__);
}

$container = new League\Container\Container;

$container->share('response', Zend\Diactoros\Response::class);
$container->share('request', function () {
    return Zend\Diactoros\ServerRequestFactory::fromGlobals(
        $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES
    );
});

$container->share('emitter', Zend\Diactoros\Response\SapiEmitter::class);

//DI PDO instance and connection.
$container->share('PDO', $pdo);

$route = new League\Route\RouteCollection($container);

$route->map('GET', '/cards/', 'CardOnFile\Controller::requestEmail' );
$route->map('GET', '/cards/emails/confirm', 'CardOnFile\Controller::getUserController' );
$route->map('GET', '/cards/emails/', 'CardOnFile\Controller::getCardController' );

$response = $route->dispatch($container->get('request'), $container->get('response'));

$container->get('emitter')->emit($response);

1 个答案:

答案 0 :(得分:1)

我知道了。

docs并没有使其看起来那么明显,但是Container对象要求您定义了一个接口,并且必须使用->add()->withArgument()方法。

因此,综上所述,我们拥有以下优势:

实例化您的初始对象

下面的代码使用闭包以将具有正确数据库连接的PDO对象添加到容器。这是将对象添加到您的容器中最有效的方法,因为它们在使用之前不会实例化。

//DI PDO instance and connection.
$container->add('pdo', function() {
    /* Connect to a MySQL database using driver invocation */
    $dsn = 'mysql:dbname=foo;host=localhost';
    $user = 'bar';
    $password = 'supersecret';

    try {
        $pdo = new PDO($dsn, $user, $password);
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
        die(__FILE__ . ":" . __LINE__);
    }

    return $pdo;
});

将您的类添加到容器中并指定构造函数*

$container
    ->add('controller', 'CardOnFile\Controller')
    ->withArgument($container->get('pdo'));

这时,Container对象将尝试使用类型提示来确定是否应向构造函数添加某些内容,因此请确保您的类在其构造函数中具有类型提示。在这种情况下,我们使用PDO类,但是我们也在CardOnFile的名称空间中,因此我们需要添加use语句以及类型提示:

<?php

namespace CardOnFile;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
**use \PDO;**

class Controller implements CardControllerInterface
{
    public $content = '';
    protected $pdo = null;

    public function __construct(**PDO** $pdo) {
        $this->pdo = $pdo;
    }

    // ...
}

创建一个接口,以便容器可以找到/识别应该将PDO对象注入到实例化对象中

<?php

namespace CardOnFile;

interface CardControllerInterface
{

}

是的。是空白它仅用于帮助Container系统。

现在,您已成功将PDO依赖对象注入到您的应用及其类中。