在 DB_Connector class 中将 PDO 准备好的语句放在哪里 - 在构造函数或函数中?
Where to put PDO prepared statements in a DB_Connector class - in the constructor or the functions?
我的 Web 项目有一个名为 DB_CONNECTOR
的 class,其中捆绑了与 mysql 数据库交互的所有功能。这些将是 get_user()
、add_user()
、change_user_attribute()
等函数。在这些函数中的每一个中,都会执行一个 sql 查询,作为一种好的做法,我使用准备好的语句(带有命名参数)。
目前与数据库的连接是在class的构造函数中建立的,并且所有语句都在那里准备。我认为这是个好主意,所以这些语句都可以立即执行。
现在我意识到我的用例通常是创建一个 db_connector 对象,执行一个或两个函数,然后对象生命周期结束,在稍后的步骤中可能会构造(或不构造)一个新的).因此,我不再确定将准备好的语句放入构造函数中是否明智,因为可以预见我最终会得到至少 20 条或可能更多的准备好的语句。
所以我的问题是:
- 在构造函数中准备所有语句是否是个好主意,即使只使用一两个?
- 或者我应该在执行前在函数中准备它们以避免不必要的准备给数据库造成压力吗?
这个答案是基于我的经验和拙见,但我会尽力阐述我的论点,所以它不仅仅是一些随机的人的意见。
我认为数据库连接不一定是你应用程序中的核心对象,更不用说唯一的了。它希望为用户看到一个完全不同的 class,因此您以后可以为其他所有内容提供更多的 class。否则,您的应用程序最终将由一个 5000 行文件中的 class 组成,并且您的 class 不适合在实例级别跟踪实体数据,您需要在方法调用中传递变量.这几乎是面向对象编程的程序代码。
此外,我认为让您的 User
class 继承自 Database
(尽管如此,这很常见)一点也不实用。将数据库连接和业务逻辑对象交织在一起并不能真正简化应用程序设计,反而会使某些部分变得更难。
数据库层本身的设计相当标准化:
- 每个应用程序一个连接(或更多...您可能需要连接到多个来源!)
- 每个查询一条语句。
这正是 PDO 的工作原理。
鉴于此,使数据库更容易 classes 只是您实体的一个依赖项,而不是它们的祖父项。这个依赖的注入可以通过不同的方式完成:
设为 class 属性:
public function __construct(\PDO $connection)
{
$this->connection = $connection;
}
传递给他们实际需要的方法(如果不是很多的话):
public function getOrders(\PDO $connection)
{
$stmt = $connection->prepare('SELECT ...');
}
... 或使用您可以在 Packagist 找到的奇特的依赖注入容器之一。
请注意,还有 object-relational mapping (ORM), active record pattern... 这些是完全不同的解决方案系列,它们可能适合或不适合您的需求,具体取决于您的用例,但不是我在这里描述的内容。
话虽如此,很明显您是在需要它们的确切位置准备语句的。这种设计甚至不允许 ;-)
我的 Web 项目有一个名为 DB_CONNECTOR
的 class,其中捆绑了与 mysql 数据库交互的所有功能。这些将是 get_user()
、add_user()
、change_user_attribute()
等函数。在这些函数中的每一个中,都会执行一个 sql 查询,作为一种好的做法,我使用准备好的语句(带有命名参数)。
目前与数据库的连接是在class的构造函数中建立的,并且所有语句都在那里准备。我认为这是个好主意,所以这些语句都可以立即执行。
现在我意识到我的用例通常是创建一个 db_connector 对象,执行一个或两个函数,然后对象生命周期结束,在稍后的步骤中可能会构造(或不构造)一个新的).因此,我不再确定将准备好的语句放入构造函数中是否明智,因为可以预见我最终会得到至少 20 条或可能更多的准备好的语句。
所以我的问题是:
- 在构造函数中准备所有语句是否是个好主意,即使只使用一两个?
- 或者我应该在执行前在函数中准备它们以避免不必要的准备给数据库造成压力吗?
这个答案是基于我的经验和拙见,但我会尽力阐述我的论点,所以它不仅仅是一些随机的人的意见。
我认为数据库连接不一定是你应用程序中的核心对象,更不用说唯一的了。它希望为用户看到一个完全不同的 class,因此您以后可以为其他所有内容提供更多的 class。否则,您的应用程序最终将由一个 5000 行文件中的 class 组成,并且您的 class 不适合在实例级别跟踪实体数据,您需要在方法调用中传递变量.这几乎是面向对象编程的程序代码。
此外,我认为让您的 User
class 继承自 Database
(尽管如此,这很常见)一点也不实用。将数据库连接和业务逻辑对象交织在一起并不能真正简化应用程序设计,反而会使某些部分变得更难。
数据库层本身的设计相当标准化:
- 每个应用程序一个连接(或更多...您可能需要连接到多个来源!)
- 每个查询一条语句。
这正是 PDO 的工作原理。
鉴于此,使数据库更容易 classes 只是您实体的一个依赖项,而不是它们的祖父项。这个依赖的注入可以通过不同的方式完成:
设为 class 属性:
public function __construct(\PDO $connection) { $this->connection = $connection; }
传递给他们实际需要的方法(如果不是很多的话):
public function getOrders(\PDO $connection) { $stmt = $connection->prepare('SELECT ...'); }
... 或使用您可以在 Packagist 找到的奇特的依赖注入容器之一。
请注意,还有 object-relational mapping (ORM), active record pattern... 这些是完全不同的解决方案系列,它们可能适合或不适合您的需求,具体取决于您的用例,但不是我在这里描述的内容。
话虽如此,很明显您是在需要它们的确切位置准备语句的。这种设计甚至不允许 ;-)