Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php MySQLi单例_Php_Mysqli_Singleton - Fatal编程技术网

Php MySQLi单例

Php MySQLi单例,php,mysqli,singleton,Php,Mysqli,Singleton,这是否足以在php中生成singleton public static function getInstance() { if (!isset(self::$intance)) { self::$instance = new mysqli(DB_HOST, DB_USER, DB_PWD, DB_NAME); } return self::$instance; } 我发现这是最简单的方法,比我在这里看到的任何东西都简单。这会有什么问题吗?用我自己的一个来整合评论中

这是否足以在php中生成singleton

public static function getInstance() {
   if (!isset(self::$intance)) {
     self::$instance = new mysqli(DB_HOST, DB_USER, DB_PWD, DB_NAME);
   }
   return self::$instance;
 }

我发现这是最简单的方法,比我在这里看到的任何东西都简单。这会有什么问题吗?

用我自己的一个来整合评论中的更改。不要依赖常量,而是将变量传递到getInstance/constructor中,这样您就可以以任何方式存储凭据,并将它们馈送到类中,而不必让类依赖于以某种方式存储的数据。增加了一点灵活性

您还可以使用代码将其交换出来,从配置文件中读取它们,或者从服务定位器类型模式中提取数据

Class MysqlConnection {
  private static $instance = null;
  private function __construct() {
    self::$instance = new mysqli(DB_HOST,DB_USER,DB_PASS,DB_DATABASE);
  }

  public static function getInstance() {
    if (!isset(self::$instance)) {
      $credentials = self::getCredentials();
      self::$instance = new MysqlConnection();
    }
      return self::$instance;
    }
  }

  function __clone() {
    //Throw exception/custom exception type here.
  }
}

编辑评论:这里的想法不是要概述一个完全100%使用原样的类,而是代表我的立场和方法。凭证位不是100%必需的,这只是我对使其更灵活一点的感觉,而不是硬编码为仅使用常量等。这可能会分散初始点的注意力,这就是单例的外观。很抱歉造成混淆。

您不能将最初的mysqli类设置为单例类-这实际上是一件好事,因为单例类是邪恶的(如果需要,我将详细介绍这一点)

您所做的在技术上称为静态工厂方法,它只返回数据库对象的第一个创建实例。事实上,这比使用单例要好得多,因为您还可以删除该实例进行测试以创建另一个实例,然后再创建另一个实例


但根据我的经验,您通常很高兴能够在代码中使用不止一个数据库连接。只需考虑使用两个用户帐户,一个用于管理,另一个用于常规使用。仅此一项就可以定义为两个数据库连接,如果您的代码只能处理“唯一一个实例”,而不选择登录凭据,这将是一件非常糟糕的事情。我建议不要这样做。

这是一门单身课程:

class DataBase
{
  private static $mysqli;

  final private function __construct() {}

  public static function getInstance()
  {
    if (!is_object(self::$mysqli)) self::$mysqli = new mysqli($H,$U,$P,$B);
    return self::$mysqli;
  }

  private function __destruct()
  {
    if (self::$mysqli) self::$mysqli->close();
  }

  private function __clone() {}
}
重要的是:

  • 变量(存储db连接)是静态的
  • 构造函数是私有的(不能调用)(不能重写的final)
  • 函数返回对象也是静态的(通常函数getInstance与此处相同)
  • 不允许克隆单例类,因此_clone()函数必须为空
  • 析构函数uu destruct由垃圾回收器调用,应该完成状态
因此,此数据库连接从其他类调用为:

$db=DataBase::getInstance();
不如

$db=new DataBase();

您也可以尝试持久连接。将
if(!isset(self::$intance)){
更改为
if(!isset(self:$instance)){
,除非它是一个打字错误。这对于用例单例来说已经足够了,如果您需要强制执行奇点,还可以将构造函数设置为私有,并在
\uu clone()中引发异常
,但是的,就是这样。如果你不需要强制执行它,你甚至可以使用一个普通函数,其中包含一个
静态
变量,避免了类变量的需要/可能的直接访问。你真的不想每次调用
getInstance时都传递主机、用户、密码和数据库名。此外,您的类缺少static
$instance
属性。此外,构造函数也不返回任何内容。所有方面都是正确的。我想我有点匆忙地完成了示例。编辑传入内容以修复此问题。