我想知道如果创建一个类似下面的类是一个好习惯。
所以每次我需要做一些工作时我都会使用self :: $ mysqli对象,连接只会在__desctruct()上关闭。另外,扩展类仍然只保持一个连接,因为$ mysqli被声明为静态。
通过这种方式,我只想到一个连接思想脚本
class db {
protected static $mysqli;
function __contruct(){
$this->mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
// DB_HOST, DB_USER, DB_PASS, DB_DATABASE defined elsewhere
}
function __destruct(){
$this->mysqli->close();
}
}
我想了解您对此的见解。
答案 0 :(得分:3)
当PHP完成执行时,它将自动关闭所有连接,因此除非优化相当大的系统或必须将内存使用保持在绝对最小值,否则无需显式关闭连接。
您在上面设置的内容只会保持连接打开状态,您可以查看单例模式,但这对于这个基本用例来说是严重的过度杀伤。
话虽如此,最后关闭它并没有坏处:)
答案 1 :(得分:3)
我想知道如果创建一个类似下面的类是一个好习惯。
我认为这不是好习惯。这特别是出于一个原因:你描述了为什么你认为你需要它的问题:每个请求只有一个连接。
您无需编码任何内容。 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实例,这可能是你正在寻找的。但是 Singletons 被认为是有害的,因为它们会引入很多问题,请参阅相关问题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
对象的时候已经封装了逻辑,而不需要单例。您的代码现在独立于全局或静态上下文。