【问题标题】:Extending the MySQLi class扩展 MySQLi 类
【发布时间】:2010-12-21 16:22:35
【问题描述】:

我希望能够创建扩展 MySQLi 类以执行其所有 SQL 查询的类。

$mysql = new mysqli('localhost', 'root', 'password', 'database') or die('error connecting to the database');

如果不将 $mysql 对象全球化以在我的其他方法或类中使用,我不知道该怎么做。

class Blog {

public function comment() {
    global $mysql;

    //rest here
}

}

任何帮助将不胜感激。

谢谢。

【问题讨论】:

    标签: php class mysqli


    【解决方案1】:

    我正在做类似的事情。我很高兴这个封装了数据库登录的单例类。

    <?php
    class db extends mysqli
    {
        protected static $instance;
        protected static $options = array();
    
        private function __construct() {
            $o = self::$options;
    
            // turn of error reporting
            mysqli_report(MYSQLI_REPORT_OFF);
    
            // connect to database
            @parent::__construct(isset($o['host'])   ? $o['host']   : 'localhost',
                                 isset($o['user'])   ? $o['user']   : 'root',
                                 isset($o['pass'])   ? $o['pass']   : '',
                                 isset($o['dbname']) ? $o['dbname'] : 'world',
                                 isset($o['port'])   ? $o['port']   : 3306,
                                 isset($o['sock'])   ? $o['sock']   : false );
    
            // check if a connection established
            if( mysqli_connect_errno() ) {
                throw new exception(mysqli_connect_error(), mysqli_connect_errno()); 
            }
        }
    
        public static function getInstance() {
            if( !self::$instance ) {
                self::$instance = new self(); 
            }
            return self::$instance;
        }
    
        public static function setOptions( array $opt ) {
            self::$options = array_merge(self::$options, $opt);
        }
    
        public function query($query) {
            if( !$this->real_query($query) ) {
                throw new exception( $this->error, $this->errno );
            }
    
            $result = new mysqli_result($this);
            return $result;
        }
    
        public function prepare($query) {
            $stmt = new mysqli_stmt($this, $query);
            return $stmt;
        }    
    }
    

    要使用你可以有这样的东西:

    <?php
    require "db.class.php";
    
    $sql = db::getInstance();
    
    $result = $sql->query("select * from city");
    
    /* Fetch the results of the query */ 
    while( $row = $result->fetch_assoc() ){ 
        printf("%s (%s)\n", $row['Name'], $row['Population']); 
    } 
    ?>
    

    【讨论】:

    • 我喜欢这个类作为 Singleton 的一个例子,但我会怀疑是否需要覆盖 query()prepare(),因为 mysqli OO API 已经提供了这些。
    【解决方案2】:

    我的建议是创建一个 Singleton DataAccess 类,在全局配置文件中实例化该类,然后在您的 Blog 类中调用它,例如 $query = DataAccess::query("SELECT * FROM blog WHERE id = ".$id)

    看看 Singleton 模式,它是一个很容易理解的设计模式。非常适合这种情况。

    您的 DataAccess 类可以有几种方法,例如 queryfetchAssocnumRowscheckUniqueValuetransactionStarttransactionCommittransactionRollback 等。这些函数也可以设置为接口它由 DataAccess 类实现。这样,您可以轻松地为多个数据库管理系统扩展 DataAccess 类。

    上面几乎描述了我的 DataAccess 模型。

    【讨论】:

    • 如果我使用单例,它会在每次调用时创建一个到数据库的新连接吗?
    • 不,这就是 Singleton 的想法。您创建一个实例,并通过将其称为静态来继续使用该实例。因此,所有类/控制器/视图等都有 1 个数据库连接。
    【解决方案3】:

    您可以将 PHP 的 extends 关键字用于任何其他类:

    class MyCustomSql extends mysqli {
    
        public function __construct($host, $user, $password, $database) {
            parent::__construct($host, $user, $password, $database);
        }
    
        public function someOtherMethod() {
        }
    }
    
    $sql = new MyCustomSql('localhost', 'root', 'password', 'database') or die('Cannot connect!');
    

    或者更好地使用对象聚合而不是继承:

    class MySqlManipulator {
    
        private $db;
    
        public function __construct($host, $user, $password, $database) {
            $this->db   = new mysqli($host, $user, $password, $database);
        }
    
        public function someOtherMethod() {
            return $this->db->query("SELECT * FROM blah_blah");
        }
    }
    
    $mysqlmanipulator = new MySqlManipulator('localhost', 'root', 'password', 'database') or die('Cannot connect!');
    

    【讨论】:

    • 这是一个糟糕的解决方案,因为博客绝不是 mysqli 类的扩展。它只是使用它,而不是使用为数据访问提供的新功能来扩展它。
    • 很明显Blog本身不能是数据库对象的子类,我是用来回答问题的,不是判断应用设计的。
    【解决方案4】:

    我的标准方法是创建一个充当数据库访问器的singleton 类,以及一个继承所有需要此类访问权限的基类。

    所以:

    class Base {
    
      protected $db;
    
      function __construct(){
        $this->db= MyDBSingleton::get_link();
        //any other "global" vars you might want 
      }
    
    }
    
    
    class myClass extends Base {
    
      function __construct($var) {
         parent::__construct();// runs Base constructor
         $this->init($var);
      }
    
      function init($id) {
        $id=(int) $id;
        $this->db->query("SELECT * FROM mytable WHERE id=$id");
        //etc.
      }
    }
    

    【讨论】:

      【解决方案5】:

      看看PDO,如果查询失败,它会抛出异常供您捕获。它得到了广泛的使用和测试,因此您在使用它的同时找到现有的解决方案应该不会有问题。

      将其注入您的博客类:

      class Blog {
      
          private $_db;
      
          public function __construct(PDO $db) {
              $this->_db = $db
          }
      
          public function comment() {
              return $this->_db->query(/*something*/);
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2013-08-30
        • 1970-01-01
        • 2011-01-29
        • 2011-04-29
        • 2011-10-07
        • 2013-05-21
        • 1970-01-01
        • 2016-01-08
        • 2014-06-08
        相关资源
        最近更新 更多