我遇到了这段代码,该代码应该确保每个浏览器只创建一个数据库连接,以便应用程序由于减少了对数据库的调用次数而获得更高的性能。
我相信我确实理解如何确保这一点的逻辑,但我只需要确认我对此的理解是正确且完整的。所以,请帮我解释细节。
在进行数据库连接/调用时还有比这更好的做法吗?
class Database {
private static $dsn = 'mysql:host=localhost;dbname=mydatabase';
private static $username = 'dbuser';
private static $password = 'dbpass';
private static $db;
private function __construct() {}
public static function getDB ()
{
if (!isset(self::$db)) {
try {
self::$db = new PDO(self::$dsn,
self::$username,
self::$password);
} catch (PDOException $e) {
$error_message = $e->getMessage();
include('../errors/database_error.php');
exit();
}
}
return self::$db;
}
}
最佳答案
正如 @raina77ow 在评论中指出的那样,这称为 Singleton pattern 。这里有一些解释:
成为单例的要点是,任何调用代码都不能创建多个 $db
。并提供从代码中任何位置对创建的 $db
的全局访问。
静态类变量仅作为每个类的一个实例而存在。因此,即使您可以将此类实例化为对象,也无法创建多个 $db
连接。
由于没有将类实例化为对象的目的(只有当该类具有每个对象实例存在的非静态变量时才有用),因此不需要类构造函数。为了防止调用代码被诱惑去调用new
,构造函数被设为私有(private)。 (严格来说,这样做不会有什么坏处,因为无论如何唯一的类变量都是静态的。)
请注意,您的实现缺少神奇的 __clone
和 __wakeup
方法。如果没有这些,您的 Singleton 仍然可以被克隆和反序列化。因此从技术上讲,您的 Singleton 没有正确执行奇点。
这里有一些额外的想法:
单例类(或任何静态使用的类)很难集成到自动化测试中。由于它们是静态的,因此您可以将它们初始化一次,并且它们在测试套件的持续时间内保留其状态。如果您使用非静态类,则每次使用
new
实例化新对象时都可以重新初始化它们。另一种设计是使用 Registry pattern ,以及为您的应用程序创建非静态数据库实例并将其存储在注册表中的某种 Bootstrap 。
如果您确实使用 Singleton,有时建议声明 Singleton 类
final
因此任何子类都不能覆盖该行为或访问私有(private)数据。您的数据库凭据在类定义中被硬编码为私有(private)数据。我不会那样做。如果您的 Apache PHP 处理程序配置错误,用户可以看到您的 PHP 源代码,然后他们就会获得您的数据库密码。将数据库连接参数放入配置文件中,并将配置文件存储在 Apache 文档根目录之外。
逐字输出数据库连接错误消息可以向用户泄露信息。记录 PDO 错误消息,但向用户发出一条友好的消息,例如“我们遇到问题,请通知网站管理员。”
您不需要在类定义文件中使用
?>
终止 PHP block 。它增加了一个风险,即关闭后可能会有空格或换行符,这将成为应用程序中的空白并破坏布局。这些类型的错误很难追踪。
关于php - 下面的代码如何确保每个浏览器只创建一个与数据库的连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13498969/