我想知道创建一个像下面这样的类是否是一个好习惯。
我认为这不是一个好习惯。这尤其是出于一个原因:您描述的问题是您认为需要它的原因:每个请求只有一个连接。
您无需编写任何代码。 mysqli 有一个很好的内置功能,默认连接。每次创建新实例时,它都会从 ini 设置(配置)中选择数据库连接参数:
$db = new mysqli;
由于脚本完成后所有数据库连接都将关闭,因此根本不需要关心太多。您唯一需要做的就是将连接实例化一次并将变量传递给所有需要该mysqli 对象的代码。
另一个不好的做法是你在这里引入Singleton Doc,类似于:
class MysqliSingleton extends mysqli
{
private static $instance;
/**
* @return MysqliSingleton
*/
public function getInstance()
{
if (NULL === self::$instance)
self::$instance = new self();
return self::$instance;
}
private function __construct()
{
}
public function __clone()
{
throw new RuntimeException('Clone is not allowed.');
}
public function __wakeup()
{
throw new RuntimeException('Unserializing is not allowed.');
}
}
它会像这样工作:
$mysqli = MysqliSingleton::getInstance();
并且总是会返回一个 mysqli 实例,这可能是您正在寻找的。然而,单身人士被认为是有害的,因为它们会带来很多问题,请参阅相关问题Who needs singletons?。
您自己创建一个包含数据库实例的变量会更容易。您还可以封装某种延迟加载,以防您的应用程序并不总是需要 mysqli 连接,例如有一个非常简单的上下文类:
interface ContextMysqli
{
/**
* @return mysqli
*/
public function getMysqli();
}
class Context implements ContextMysqli
{
private $mysqli;
public function getMysqli()
{
$this->mysqli || $this->mysqli = new mysqli();
return $this->mysqli;
}
}
当您的脚本启动时,只需实例化您的上下文并将其传递给您需要它的代码的每个部分:
$context = new Context();
...
$result = do_some_db_work($context);
...
function do_some_db_work(ContextMysqli $context)
{
$mysqli = $context->getMysqli();
...
}
这个建议也可能有点短视,但它比单例要好,而且不会引入太多麻烦。好处是您已经封装了何时创建 mysqli 对象而无需单例的逻辑。您的代码现在独立于全局或静态上下文。