5

在询问有关 PDO 查询的另一个问题时,有人告诉我,将我的 PDO 连接对象保存为全局对象,以便在调用数据库查询的各种函数中使用它通常是不好的做法。

以下是我通常如何使用我的 PDO 对象:

function somefunction(){
    global $pdo;

    $statement = $pdo->prepare("some query");
    $statement->execute();
}

我读过的论点更多的是关于代码维护和调试,很难追踪谁修改了 PDO 对象以及它在代码中的位置。其他人只是简单地拒绝使用全局变量来存储 PDO 对象,但不能真正解释为什么全局变量是一种不好的方法。

但是,对于只有一个数据库的中小型项目,使用全局变量真的有缺点吗?我通常有我的连接脚本和我的函数脚本,其中函数脚本将 require_once() 连接脚本,我的 PDO 对象是在其中创建的。这样,我的连接总是建立起来的,对 PDO 对象的所有修改都在我的连接脚本中完成。

使用这种方法有什么根本缺陷吗?

4

2 回答 2

12

使用这种方法有什么根本缺陷吗?

您必须了解的第一件事是,这$pdo存储逻辑的一部分。这意味着,它只能在执行抽象数据访问的类中使用,无论是 SQL 表还是集合。

让我们看看你的代码,

function somefunction(){
    global $pdo;

    $statement = $pdo->prepare("some query");
    $statement->execute();
}

如果你将来想从 MySQL 切换到 Mongo/MSSQL/PgSQL 怎么办?然后你将不得不重写很多代码。

对于每个数据库供应商,您必须创建一个具有不同变量的单独文件。像这样

function somefunction(){
    global $mongo;
    return $mongo->fetch(...);
}

通过使用全局状态,您最终会出现大量代码重复,因为您无法传递参数,因此无法在运行时更改函数的行为。

现在让我们看看这个,

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 操作)

  • 将您data access abstractioncomputation logic通常称为服务的桥梁

  • 您应该始终将 things 函数的需要作为参数传递

  • 你最好停止担心你的代码,开始考虑抽象层。

  • 最后,在你开始做任何事情之前,你首先要初始化你的所有服务,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);
}
于 2013-10-13T03:49:18.797 回答
3

对于一个很小的项目,使用 global 不会有太大的伤害。当项目规模开始增长时,事情就会开始变得糟糕。

如果您somefunction()使用 5 个全局变量在其中有 300 行,那么查看您的代码的人不会知道该函数使用外部变量,除非他们通过它寻找全局变量。

另外,不使用全局变量很容易……那为什么要这样做

function somefunction( PDO $pdo ){
    $statement = $pdo->prepare("some query");
    $statement->execute();
}

编辑:

show_profile.php是你的控制器。您的控制器收集视图的所有数据并加载视图。这是一个非常简化的版本。

require( 'functions.php' );
$db = new PDO();
$user = get_user( $db, $user_id );
require( 'view.php' );
于 2013-10-12T18:40:22.447 回答