php - 联盟路线、集装箱和 PDO
问题描述
TL;博士;
如何使 PDO 连接对CardOnFile\Controller
类可用,以便它可以进行数据库查询?(我想我必须使用容器,但不确定如何使用)。
背景
每次实例化需要数据库访问的对象时,我都希望避免与数据库建立多个连接。所以,我认为我需要实例化一个数据库连接 (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);
解决方案
我想到了。
文档并没有使这一点尽可能明显,但是 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
{
}
是的。它是空白的。它只是用来帮助容器系统。
现在,您已经成功地将 PDO 依赖对象注入到您的应用程序及其类中。
推荐阅读
- python - 统计所有数据库中所有表中的所有行
- javascript - vue组件外的访问方法
- java - 原因:java.sql.SQLException:连接已关闭
- javascript - 我尝试使用 Js 和 CSS 创建选项卡,但它们不起作用
- python - 从 s3 Bucket 下载文件到 EC2 根路径
- node.js - Solidity:ParserError:预期的编译指示、导入指令或合同/接口/库定义
- android - RecyclerView 不显示项目
- mysql - 为什么 sqlite .dump 加密数据到 x'2384934..' 而不是原始数据?
- javascript - 画布到图像 base64 编码的 url 不显示图像
- android - 测试 ION 驱动程序时,libion 中的 DMAReadCached 失败