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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19337676/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 19:18:49  来源:igfitidea点击:

Saving my PDO connection as a global variable

phpdesign-patternscoding-style

提问by Prusprus

While asking another questions about PDO queries, I've been told that saving my PDO connection object as global to use it in my various functions that call queries to my database is generally bad practice.

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

Here is how I generally use my PDO object:

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

function somefunction(){
    global $pdo;

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

The arguments I've read are more about code maintenance and debugging, where it's hard to trace who modified the PDO object and where in the code it would be. Other people just simply reject using global variables for storing the PDO object, but can't really explain why global variables are a bad approach.

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

However, for a small-medium projects with only one database, is there really a disadvantage to using a global variable? I usually have my connection script and my functions script separately, where the functions script will require_once() the connection script, where my PDO object is created. In this way, my connection is always established and all modifications to the PDO object are done in my connection script.

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

Is there any fundamental flaws in using this approach?

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

回答by Yang

Is there any fundamental flaws in using this approach?

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

The very first thing you have to understand, is that $pdois a part of storagelogic. That means, it should be only used inside classes that do abstract data access, be it a SQL table or a collection.

您首先要了解的是,这$pdo存储逻辑的一部分。这意味着,它应该只在进行抽象数据访问的类中使用,无论是 SQL 表还是集合。

Let's look at your code,

让我们看看你的代码,

function somefunction(){
    global $pdo;

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

What if you want to switch from MySQL to Mongo/MSSQL/PgSQL, in future? Then you will have to rewrite a lot of code.

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

And for each database vendor, you will have to create a separated file with different variable. Just like this

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

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.

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

Now let's look at this,

现在让我们看看这个,

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

Here, $pdois passed as an argument, thus there's no global state. But the problem still remains, you end up violating the Single-Responsibility Principle

在这里,$pdo作为参数传递,因此没有全局状态。但问题仍然存在,你最终违反了单一职责原则

If you really want something that is maintainable, clean and very readable, you'd better stick with DataMappers. Here's an example,

如果你真的想要一些可维护、干净且非常易读的东西,你最好坚持使用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();
    }
}

Conclusion

结论

  • It doesn't really matter if your project is small or large, you should always avoid global state in all it forms (global variables, static classes, Singletons) - For the sake of code maintainability

  • You have to remember, that $pdois not a part of your business logic. Its a part of storage logic. That means, before you even start doing something with business logic, like heavy computations, you should really abstract table access (including CRUD operations)

  • The bridge that brings together your data access abstractionand computation logicis usually called Service

  • You should always pass the things function's need as parameters

  • You'd better stop worrying about your code and start thinking about abstraction layers.

  • And finally, before you even start doing any stuff, you'd firstly initialize all your services in bootstrap.phpand then start querying storage according to user's input ($_POSTor $_GET).

  • 不管你的项目是大是小,你应该始终避免所有形式的全局状态(全局变量、静态类、单例)——为了代码的可维护性

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

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

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

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

  • 最后,在你开始做任何事情之前,你首先要初始化你的所有服务bootstrap.php,然后根据用户的输入($_POST$_GET)开始查询存储。

Just like,

就像,

public function indexAction()
{
    $id = $_POST['id']; // That could be $this->request->getPost('id')
    $result = $this->dataMapper->fetchById($id);

    return print_r($result, true);
}

回答by Galen

For a tiny tiny project it won't hurt much to use global. When the project size starts growing is when things start to get bad.

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

if your somefunction()had 300 lines in it using 5 global variables, someone looking at your code wouldn't know that the function uses outside variables unless they went through it looking for global variables.

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

Plus, it's so easy to not use global variables...so why do it

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

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


EDIT:

编辑:

show_profile.phpis your controller. Your controller collects all the data for the view and loads the view. This is a very simplified version.

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

require( 'functions.php' );
$db = new PDO();
$user = get_user( $db, $user_id );
require( 'view.php' );