此单例代码有问题,请参考下面的

在Mysql驱动的PHP网站中,MySql连接的一般都是利用脚本的结束来进行释放,在一些分层写的php网站中,若一个页面含有多个数据访问类,由于每个数据访问类都会有数据库的连接,导致这一个页面在脚本结束前会有多个数据库连接,在一些大型的页面连接可能多至数十上百,为此需要进行必要的控制,对于解释性的PHP语言,脚本是顺序执行的,也就是说数据库连接的利用同时只有一个,根据这个特点,可以用单例模式来进行改造。

<?php
  class ConnecToDB
  {
      private static $instance;
      private function _constuct()
      {
      } //私有构造函数,防止外界构造新对象,
      public static function GetConnec()
      {
          if (!self::$instance instanceof self) {
              self::$instance =new self;//若当前对象实例不存在
          }
          $temp=self::$instance; //获取当前单例
            return $temp::Con() ;  //调用对象私有方法连接 数据库
      }
      //连接到数据库
      private static function Con()
      {
          try {
              $connec=mysqli_connect("127.0.0.1", "root", "root");   //数据库地址和密码等
            mysqli_select_db($connec, "dbname");//选择数据库
          } catch (Exception $e) {
              echo $e->getMessage().'<br/>';
          }
          return $connec;
      }
  }
$db=new ConnecToDB();
$db->GetConnec();

 

 

 

这是正确的单例代码

<?php
  class Config1 {}
  class Config
  {
    /*
  * 必须先声明一个静态私有属性:用来保存当前类的实例
  * 1. 为什么必须是静态的?因为静态成员属于类,并被类所有实例所共享
  * 2. 为什么必须是私有的?不允许外部直接访问,仅允许通过类方法控制方法
  * 3. 为什么要有初始值null,因为类内部访问接口需要检测实例的状态,判断是否需要实例化
  */
  private static $instance = null;
  //保存用户的自定义配置参数
  private $setting = [];
  //构造器私有化:禁止从类外部实例化
  private function __construct(){}
  //克隆方法私有化:禁止从外部克隆对象
  private function __clone(){}
          //因为用静态属性返回类实例,而只能在静态方法使用静态属性
          //所以必须创建一个静态方法来生成当前类的唯一实例
  public static function getInstance()
  {
              //检测当前类属性$instance是否已经保存了当前类的实例
              if (self::$instance == null) {
                  //如果没有,则创建当前类的实例
                  //self::$instance = new self();
                  self::$instance= new mysqli(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
                  self::$instance->set_charset('utf8');
              }
              //如果已经有了当前类实例,就直接返回,不要重复创建类实例
              return self::$instance;
  }
  //设置配置项
  public function set($index, $value)
  {
  $this->setting[$index] = $value;
  }
  //读取配置项
  public function get($index)
  {
  return $this->setting[$index];
  }
  }
   
  //实例化Config类
  $obj1 = Config::getInstance();
  $obj2 = Config::getInstance();
  var_dump($obj1,$obj2);
  $obj1->set('host','localhost');
  echo $obj1->get('host');

 

 

当然这个代码中,数据库的账号、密码等连接信息都是硬编码,可以通过改造GetConnec()函数注入相应的信息。

通过这段脚本,就可以控制一个页面只有一次数据库连接。这就会减少mysql的连接数。但是虽然减少了单次请求的连接数,但是如果这个页面进行多次刷新的话,还是会生产大量mysql连接,降低性能,如图,页面进行多次刷新后,mysql连接数,出现很多:

如何解决多次刷新情况下的大量连接呢,答案是用mysql长连接;

我们把上面的代码的

$connec=mysqli_connect("127.0.0.1", "root", "root"); //数据库地址和密码等

改为

$connec=mysqli_connect("p:127.0.0.1", "root", "root"); //数据库地址和密码等

注意:上面的代码在IP地址前加了一个“p:”前缀,代表使用的是mysql长连接,修改完成后,我们再来多次刷新页面。

如上图,只有2个连接了。解决成功。

当然,除了用mysql的长连接外,还可以修改linux 内核参数的连接重用参数,也可以达到目的。

用mysql长连接能大大提升性能,所以请务必使用mysql长连接。

原创文章,转载请注明:来自Lenix的博客,地址http://blog.p2hp.com/archives/6131 

 

 

 

最后更新于 2022年11月4日

通过PHP单例模式与长连接减少MySql连接数
标签: