可能重复:
What is the best method for getting a database connection/object into a function in PHP?
Database and OOP Practices in PHP
我正在尝试建立一个OOP购物车。
目前,它是一半OOP,一半程序......例如
function removeFromCart() {
require_once('/.../.../connectPDO.php');
$db = connectPDO();
$sql = 'DELETE FROM Quotes WHERE User = :user and ProductId = :pid';
$stmt = $db->prepare($sql);
$stmt->execute(array(':user' => $user, ':pid' => $pid));
}
我的问题是,如果我想添加到购物车,那么在我的函数addToCart中,我将需要再次要求数据库连接。
这似乎完全是浪费,考虑到每个功能都需要包含以下内容:
require_once('/.../.../connectPDO.php');
$db = connectPDO();
我知道这完全没有效率,并且想知道是否有人可以帮我写一个使用上述连接连接到DB的骨架OOP购物车类?
这是否在构造函数中?当用户从前端的一个页面导航到另一个页面时,它会保持活着吗?
我是OOP的新手并且完全迷失了。
非常感谢提前。
答案 0 :(得分:4)
以下内容应该让您入门:
$pdo = new PDO('your dsn');
$cartData = new CartData($pdo);
$cart = new Cart($cartData);
class CartData
{
private $dbConnection;
public function __construct(PDO $dbConnection)
{
$this->dbConnection = $dbConnection;
}
public function removeItem($userId, $productId) {
$sql = 'DELETE FROM Quotes WHERE User = :user and ProductId = :pid';
$stmt = $this->dbConnection->prepare($sql);
$stmt->execute(array(':user' => $userId, ':pid' => $productId));
}
}
class Cart
{
private $cartData;
public function __construct(CartData $cartData)
{
$this->cartData = $cartData;
}
public function removeItem($userId, $productId) {
$this->cartData->removeItem($userId, $productId);
}
}
请注意,我已从实际的Cart
类中删除了数据库调用,因为这样只会使某些时候很难/无法交换到另一个数据库引擎。或许您可能想要介绍一种完整的其他方式来存储您的数据(ahum单元测试)。还要注意我已经使用依赖注入为类提供了他们需要能够执行它们负责的任何对象。
我已经为正在注入的类对象使用了类型提示,但是最好在接口上键入提示,因为这样可以很容易地为其他类换出类。我强烈建议你使用接口(我上面写的只是一个例子来获得这个想法)。这也使得为代码创建单元测试变得非常容易。
答案 1 :(得分:1)
在每个页面请求中,您都建立一个新的数据库连接。您无法在请求之间共享连接。
有几种不同的设计模式(最佳实践)可用于处理此问题。对于所有这些,您需要一个DB抽象层(如PDO,Doctrine DBAL或其他)。
最常用的设计模式是依赖注入:
class Foo
{
/**
* @var DatabaseAbstractionLayer
*/
private $dbal;
public function __construct(DatabaseAbstractionLayer $dbal)
{
$this->dbal = $dbal;
}
public function methodThatUsesTheDbal()
{
$this->dbal->query(...);
}
}
$db = new DatabaseAbstractionLayer();
$foo = new Foo($db); // constructor injection
$bar = new Bar();
$bar->setDbal($db); // setter injection
$baz = new Baz();
$baz->dbal = $db; // property injection (almost never used)
您可以使用服务容器轻松处理此问题(例如pimple):
$container = new Pimple();
$container['db'] = $container->share(function ($c) {
return new DatabaseAbstractionLayer();
});
$container['foo'] = function ($c) {
return new Foo($c['db']);
};
$foo = $container['foo']->methodThatUsesDbal();
class DatabaseAbstractionLayer
{
private static $_instance;
// ...
private function __construct()
{
// ...
}
// ...
public static function getInstance()
{
if (null === self::$_instance) {
self::$_instance = new static();
}
return self::$_instance;
}
}
class Foo
{
public function methodThatUsesDbal()
{
$db = DatabaseAbstractionLayer::getInstance();
// ...
}
}
Registery::set('db', new DatabaseAbstractionLayer());
class Foo
{
public function methodThatUsesRegistery()
{
Registery::get('db');
// ...
}
}