【问题标题】:Using Singleton to create single MySQLi Connection and using it across multiple objects?使用 Singleton 创建单个 MySQLi 连接并在多个对象中使用它?
【发布时间】:2010-12-18 10:25:30
【问题描述】:

大家早上好!

我对 PHP 并不完全陌生,但当谈到 PHP5 的 OO 时,我还是有点陌生​​。现在,我想到了这个小项目,我想在其中使用 HTML5 和一些 OO PHP。它应该是某一天可以水平滚动的时间线。

因此我创建了一个类Timeline。这是我的主要目标。在其他方法中,一种方法 ($timeline->createYearString();) 是创建我的年份字符串。我实现了另一个类 Year,该方法 createYearString(); 调用 X 次以创建我多年的 HTML 输出。

为了用事实填满我的岁月,我需要一个数据库连接。作为对 mysql 连接的 oop 方法的新手,我四处搜索,发现 Atli 关于 mysqli 单例的评论 (http://www.dreamincode.net/forums/topic/81496-connection-to-the-mysql-using-oop/page__view__findpost__p__1038512)。我实现了它并尝试在类 Year 的对象中使用它。有趣的是,$dbLink 为第一个对象返回,但不是第二个对象,它是立即创建的,与第一个对象完全一样。 $this->db 在第二年突然返回 NULL,因此我从 PHP 得到一个非对象致命错误

请看下面我的三个课程。我错过了什么?

class Year {
 private $year;
 private $db;

 function __construct($year) {
  $this->year=$year;
  $this->db=MyDB::Get();
 }

 function createHTML($last='') {
  $out=" <div class=\"year_outer".(($last) ? ' last_year' : '')."\" id=\"y".$this->year."\">
     <div class=\"year_inner\">
      <div class=\"year_above\">
       <span class=\"yearnr\">".$this->year."</span>
      </div>
      <div class=\"year_below\"></div>
     </div>
     <div class=\"months_wrapper\">\n";
  if(!$last) {
   for($i=1; $i<=12; $i++) {
    $fDoM = mktime(0,0,0,$i,1,$this->year);            // $fDoM = first Day of Month
    $lDoM = mktime(0,0,0,$i,date('t',mktime(0,0,0,$i,1,$this->year)),$this->year);  // $lDoM = last Day of Month
    $sql = $this->db->query("SELECT * FROM tp_together");
    //echo date('d.m.Y',$fDoM)." bis ".date('d.m.Y',$lDoM)."\n";

    $out.= " <div class=\"month_outer_l\" id=\"".$this->year."-".$i."\">
        <div class=\"month_outer_s\">
         <div class=\"month_inner\"><span>".date("M",mktime(0,0,0,$i,1,$this->year))."</span></div>
        </div>
       </div>\n";
    } 
  }  
  $out.= " </div>
    </div>\n";

  return $out;
 }
}

class Timeline {
 public $daysDating;
 public $startYear;
 public $endYear;
 public $numberOfYears;

 function __construct($start,$end='') {
  $this->startYear = $start;
  $this->endYear  = ($end=='') ? date("Y")+1 : $end;
  $this->daysDating = $this->calcDaysDating();
  $this->numberOfYears= $this->calcNumberOfYears();
 }

 function createYearString() {
  $x=new Year('2004');
  print $x->createHTML();
  $y=new Year('2005');
  print $y->createHTML();
  $z=new Year('2006');
  print $z->createHTML(true);

  // $j=$this->endYear;
  // for($i=$this->startYear; $i<=$j; $i++) {
  //  $x=new Year($i);
  //  ($i==$j) ?
  //   print $x->createHTML(true) :
  //   print $x->createHTML();
  // }
 }

 private function calcDaysDating() {
  $today=mktime(0,0,0,date("m"),date("d"),date("y"));
  $day1=mktime(0,0,0,7,11,2006);

  return $today-$day1;
 }

 private function calcNumberOfYears() {
  return $this->endYear - $this->startYear +1;
 }

 function createHNavigation() {
  $x=1;
  $out='<ul>';
  for($i=$this->startYear; $i<=$this->endYear; $i++) {
   $out.="<li><a class=\"navBubble\" id=\"navBubble$i\" accesskey=\"$x\" href=\"#y$i\" title=\"Go to $i\"></a></li>\n";
   $x++;
  }
  $out.="</ul>";
  return $out;
 }
}

class MyDB {
 private static $dbLink;

 private function __construct() {}
 private function __clone() {}

 public static function Get() {
  if(!self::$dbLink) {
   self::$dbLink = new mysqli(DB_HOST, DB_USER, DB_PWD, DB_NAME);
   if(mysqli_connect_errno()) {
    throw new Exception("Database connection failed: ".mysqli_connect_error());
   }
   return self::$dbLink;
  }
 }
}

如果我没有把我的问题说清楚。 $x 类似于 2004 ($x=new Year('2004')) 工作正常。但是随后的 $y ($y=new Year('2005') 返回 FATAL ERROR 并且 $this->db 返回 NULL - 为什么?

非常感谢,非常感谢您的帮助。

【问题讨论】:

  • 最好使用' 引用PHP 字符串,这样您就可以在HTML 中使用"。如果可以避免,逃避狂欢是可怕的。
  • 在 PHP 中使用 Singleton 是没有意义的。没有共享的应用程序内存。 Singleton 只会是它自己的请求中的 Singleton。三个同时请求仍将创建三个实例。如果要控制与数据库的连接数,configure the appropriate mysqli values
  • 这完全不是没有意义的,你一开始处理交易就会发现。
  • 当然。如您所知,在处理事务时,您需要对所有查询使用相同的连接。如果您的查询被拆分到多个函数中,您需要一种方法来访问每个函数中的 MySQLi 连接对象。您可以使对象成为全局对象,可以将其作为参数传递,也可以使用 Singleton。这些方法中的每一种都有其优点和缺点。我更喜欢单例。
  • 适合工作的正确工具。在我的工作中,我严重依赖 MySQL 的特定特性,所以依赖这个单例并不重要。与全局对象相比,它具有一个优点,即它不能被静默覆盖。依赖注入?当然 - 只要您可以用具有相同接口的其他对象替换 MySQLi 对象...嗯...知道吗?

标签: php oop singleton mysqli


【解决方案1】:
public static function Get() {
  if(!self::$dbLink) {
  self::$dbLink = new mysqli(DB_HOST, DB_USER, DB_PWD, DB_NAME);
  if(mysqli_connect_errno()) {
   throw new Exception("Database connection failed: ".mysqli_connect_error());
  }
  //was here
  }
   return self::$dbLink; //should be here
 }

【讨论】:

    【解决方案2】:

    如果已设置,您的 MyDB::Get 函数不会返回 self::$dbLink。

    原件返回:

    public static function Get() {
        if(!self::$dbLink) {
            self::$dbLink = new mysqli(DB_HOST, DB_USER, DB_PWD, DB_NAME);
            if(mysqli_connect_errno()) {
                throw new Exception("Database connection failed: ".mysqli_connect_error());
            }
            return self::$dbLink;
         }
    }
    

    返回以便它工作:

    public static function Get() {
        if(!self::$dbLink) {
            self::$dbLink = new mysqli(DB_HOST, DB_USER, DB_PWD, DB_NAME);
            if(mysqli_connect_errno()) {
                throw new Exception("Database connection failed: ".mysqli_connect_error());
            }
         }
         return self::$dbLink;
    }
    

    (PS,在缩进中使用多个字符会更容易检测到。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-01
      • 1970-01-01
      • 2022-12-07
      • 2015-07-23
      • 1970-01-01
      • 1970-01-01
      • 2021-09-27
      相关资源
      最近更新 更多