问题描述
TL; DR;
如何使PDO连接可用于 CardOnFile \ Controller
类,以便它可以进行数据库查询?(我认为我必须使用容器,但不确定如何使用.)
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).
背景
我想避免每次实例化需要数据库访问的对象时都与数据库建立多个连接.因此,我认为我需要实例化数据库连接(PDO)的一个副本,然后使用League \ Route和League \ Container将其注入需要的类中.
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.
我不想将容器注入类中,因为那是服务位置.但是,我完全不确定如何将PDO对象放入需要它的类中,以便它可以正常工作.
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?
代码:
/* 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);
推荐答案
我知道了.
文档并没有使它们看起来那么明显可以,但是Container对象要求您定义一个接口,并且使用-> add()-> withArgument()
方法.
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:
实例化您的初始对象
下面的代码使用闭包以将具有正确数据库连接的PDO对象添加到容器.这是将对象添加到容器的最高效的方法,因为它们在使用之前不会实例化.
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;
});
将您的类添加到容器中并指定构造函数*
$container
->add('controller', 'CardOnFile\Controller')
->withArgument($container->get('pdo'));
这时,Container对象将尝试使用类型提示来确定是否应向构造函数添加某些内容,因此请确保您的类在其构造函数中具有类型提示.在这种情况下,我们使用PDO类,但是我们也在CardOnFile的命名空间中,因此我们需要添加 use
语句以及类型提示:
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;
}
// ...
}
创建一个接口,以便容器可以找到/识别应该将PDO对象注入到实例化对象中
<?php
namespace CardOnFile;
interface CardControllerInterface
{
}
是的.它是空白.它仅用于帮助Container系统.
Yep. It's blank. It is just used to help out the Container system.
现在,您已成功将PDO依赖对象注入到您的应用及其类中.
Now, you have successfully injected a PDO dependecy object into your app and its classes.
这篇关于联赛路线,集装箱和PDO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!