将我的PDO连接保存为全局变量

Pru*_*rus 5 php design-patterns coding-style

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

以下是我通常使用PDO对象的方法:

function somefunction(){
    global $pdo;

    $statement = $pdo->prepare("some query");
    $statement->execute();
}
Run Code Online (Sandbox Code Playgroud)

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

但是,对于只有一个数据库的中小型项目,使用全局变量真的有缺点吗?我通常单独使用连接脚本和函数脚本,其中函数脚本require_once()连接脚本,我的PDO对象创建在那里.通过这种方式,我的连接始终建立,并且对PDO对象的所有修改都在我的连接脚本中完成.

使用这种方法有任何根本缺陷吗?

Yan*_*ang 10

使用这种方法有任何根本缺陷吗?

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

我们来看看你的代码,

function somefunction(){
    global $pdo;

    $statement = $pdo->prepare("some query");
    $statement->execute();
}
Run Code Online (Sandbox Code Playgroud)

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

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

function somefunction(){
    global $mongo;
    return $mongo->fetch(...);
}
Run Code Online (Sandbox Code Playgroud)

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

现在让我们来看看,

function somefunction($pdo){
    $statement = $pdo->prepare("some query");
    $statement->execute();
}
Run Code Online (Sandbox Code Playgroud)

这里,$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();
    }
}
Run Code Online (Sandbox Code Playgroud)

结论

  • 无论你的项目是小还是大都没关系,你应该总是避免所有形式的全局状态(全局变量,静态类,单例) - 为了代码可维护性

  • 您必须记住,这$pdo不是您的业务逻辑的一部分.它是存储逻辑的一部分.这意味着,在您开始使用业务逻辑(例如繁重的计算)之前,您应该真正抽象表访问(包括CRUD操作)

  • 汇集了您的桥梁data access abstraction,并computation logic通常被称为服务

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

  • 你最好不要担心你的代码并开始考虑抽象层.

  • 最后,在开始做任何事情之前,首先要初始化所有服务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);
}
Run Code Online (Sandbox Code Playgroud)