在询问有关 PDO 查询的另一个问题时,我被告知将我的 PDO 连接对象保存为全局对象以在调用数据库查询的各种函数中使用它通常是不好的做法。
以下是我通常如何使用我的 PDO 对象:
function somefunction(){
global $pdo;
$statement = $pdo->prepare("some query");
$statement->execute();
}
我读过的论点更多是关于代码维护和调试,很难追踪谁修改了 PDO 对象以及它在代码中的位置。其他人只是简单地拒绝使用全局变量来存储 PDO 对象,但无法真正解释为什么全局变量是一种糟糕的方法。
但是,对于只有一个数据库的中小型项目,使用全局变量真的有缺点吗?我通常有我的连接脚本和我的函数脚本,其中函数脚本将 require_once() 连接脚本,我的 PDO 对象是在其中创建的。通过这种方式,我的连接始终建立并且对 PDO 对象的所有修改都在我的连接脚本中完成。
使用这种方法有什么根本性的缺陷吗?
Is there any fundamental flaws in using this approach?
您首先要了解的是,$pdo
是存储 逻辑的一部分。这意味着,它应该只在执行抽象数据访问的类中使用,无论是 SQL 表还是集合。
让我们看看你的代码,
function somefunction(){
global $pdo;
$statement = $pdo->prepare("some query");
$statement->execute();
}
如果您将来想从 MySQL 切换到 Mongo/MSSQL/PgSQL 怎么办?
然后你将不得不重写很多代码。
对于每个数据库供应商,您都必须创建一个包含不同变量的单独文件。就这样
function somefunction(){
global $mongo;
return $mongo->fetch(...);
}
By using a global state, you end up with mass code duplication, because you cannot pass parameters and thus cannot change function's behavior at runtime.
现在让我们看看这个,
function somefunction($pdo){
$statement = $pdo->prepare("some query");
$statement->execute();
}
此处,$pdo
作为参数传递,因此没有全局状态。但是问题依然存在,你最终违反了单一职责原则
如果您真的想要可维护、干净且可读性强的东西,您最好坚持使用 DataMappers .这是一个例子,
$pdo = new PDO(...);
$mapper = new MySQL_DataMapper($pdo);
$stuff = $mapper->fetchUserById($_SESSION['id'])
var_dump($stuff); // Array(...)
// The class itself, it should look like this
class MySQL_DataMapper
{
private $table = 'some_table';
private $pdo;
public function __construct($pdo)
{
$this->pdo = $pdo;
}
public function fetchUserById($id)
{
$query = "SELECT * FROM `{$this->table}` WHERE `id` =:id";
$stmt = $this->pdo->prepare($query);
$stmt->execute(array(
':id' => $id
));
return $stmt->fetch();
}
}
结论
不管你的项目是大是小,你应该始终避免所有形式的全局状态(全局变量、静态类、单例)-为了代码的可维护性
您必须记住,$pdo
不是您业务逻辑的一部分。它是存储逻辑的一部分。这意味着,在您开始使用业务逻辑(例如繁重的计算)之前,您应该真正抽象表访问(包括 CRUD 操作)
将您的数据访问抽象
和计算逻辑
结合在一起的桥梁通常称为服务
您应该始终将事物函数的需要作为参数传递
您最好停止担心您的代码并开始考虑抽象层。
最后,在开始做任何事情之前,您首先要在 bootstrap.php
中初始化所有服务,然后根据用户的输入开始查询存储 ($ _POST
或 $_GET
)。
就像,
public function indexAction()
{
$id = $_POST['id']; // That could be $this->request->getPost('id')
$result = $this->dataMapper->fetchById($id);
return print_r($result, true);
}