League route, container, and PDO

╄→гoц情女王★ 提交于 2021-02-11 14:41:55

问题


TL;DR;

How do I make a PDO connection available to the CardOnFile\Controller class so that it can make database queries? (I think I have to use the container, but not sure how).

Background

I want to avoid having multiple connections to the database each time I instantiate an object that needs database access. So, I think I need to instantiate ONE copy of a database connection (PDO) and then inject it into the classes where it will be needed using League\Route and League\Container.

I don't want to inject the container into the classes, because that's service location. But, I am completely unsure how to get the PDO object into the class that is going to need it so it can do work.

How to I make it so that the mapped callable has database access?

Code:

/* 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:


I figured it out.

The docs don't make this as obvious as they probably could, but the Container object requires that you have an interface defined AND that you use the ->add()->withArgument() methods.

So, putting it all together, we have this:

Instantiate your initial objects

The code below, uses a closure in order to add a PDO object with the correct database connection to the container. This is the most performant way of adding objects to your container because they are not instantiated until used.

//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;
});

Add your class to the container and specify the constructor*

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

At this point, the Container object is going to try to use type hints to figure out if it should add something to the constructor, so make sure your class has a type hint in its contstructor. In this case, we are using the PDO class, but we're also in the namespace of CardOnFile, so we need to add the use statement as well as the type hint:

<?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;
    }

    // ...
}

Create an interface so the Container can find / recognize that a PDO object should be injected into the instantiated object

<?php

namespace CardOnFile;

interface CardControllerInterface
{

}

Yep. It's blank. It is just used to help out the Container system.

Now, you have successfully injected a PDO dependecy object into your app and its classes.



来源:https://stackoverflow.com/questions/51486449/league-route-container-and-pdo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!