【问题标题】:Using MySQLi methods via child class通过子类使用 MySQLi 方法
【发布时间】:2013-12-16 16:41:06
【问题描述】:

我正在尝试使用 MySQLi 类,但不想每次都写出连接详细信息。我一直在尝试做的是创建一个扩展类mysqli,称为database,它将返回一个连接处理程序,如果无法建立连接,最终会优雅地失败(我还没有这样做)。

但是,我遇到的问题是(如果这非常简单,我现在道歉)在实例化子类database 并将其传递给需要它的方法。

我走对路了吗?由于 MySQLi 可以实现 OOP,我认为编写一个全新的类只是为了使用它,而我可以在每个类中使用所需的方法,这有点违背了它的意义?

下面是我的database 类,它扩展了mysqli

class database extends mysqli{

    //set connection variables
    private $host = "localhost";
    private $username = "username";
    private $password = "password";
    private $db_name = "db_name"; //database name

    public function connect(){
        $mysqli = new mysqli($this->host, $this->username, $this->password, $this->db_name);

        if ($mysqli->connect_errno){//check if any connection error was encountered
            return false;
        } else {
            return $mysqli;
        }       
    }
}

这是我的注册类,可能会准备语句、执行查询等。

class registration{

private $email;
private $sec_email;
private $password;
private $sec_pass;
private $code;

function __construct($code, $email, $sec_email, $password, $sec_pass){
 //Sets all the vars above
}

public function check_vars(){//Check variables are set and valid.
 $mysqli = new database;
 if($mysqli){ 
  $code_check = $this->check_code($this->code, $mysqli);
  if($code_check == true){
   //Code checks out
  }
 }
}

private function check_code($code, $mysqli){
if($stmt = $mysqli->prepare("SELECT `code` FROM `code_list` WHERE `code` = ? LIMIT 1")){
//return true
  }
 }
}

提前致谢,如果我忽略了一个简单的答案,我深表歉意。

UPDATE

自从阅读了@Your Common Sense 留下的答案后,我做了以下事情:

index.php

require_once('config.php');
$mysqli = new mysqli($db['host'], $db['user'], $db['pass'], $db['dbname']);
$display = new dispaly($mysqli);
//Display methods...

config.php

$db = array('host' => 'host', 'user' => 'user', 'pass' => 'pass', 'dbname' => 'dbname')
require_once('lib/other.classes.php');
//More classes   

主要想补充的是,自从提供了这个答案后,我也开始对许多其他对象使用依赖注入,而不是每次需要它们时都实例化新对象。

感谢@Your Common Sense 和@Bill Karwin!

【问题讨论】:

    标签: php oop mysqli


    【解决方案1】:

    我走对了吗?

    绝对没有

    首先,您不需要专门的数据库类来优雅地失败。它必须集中在应用程序范围的错误处理程序中一次处理所有错误,而不是单独处理每个 API。

    其次,你在每个类中创建一个新的数据库类实例的想法太糟糕了。

    所以,这是正确的方向:

    1. 只创建普通和原始的 mysqli 类实例。 一次。
    2. 在其他类的构造函数中将它作为参数传递

    你的应用程序类就到这里

    class registration()
    {
        private $db;
        public $email;
        public $sec_email;
        public $password;
        public $sec_pass;
        public $code;
    
        function __construct($mysqli)
        {
            $this->db = $mysqli;
        }
    
        public function init($code, $email, $sec_email, $password, $sec_pass)
        {
            $code_check = $this->check_code($this->code);
        }
    
        private function check_code($code)
        {
            $sql  = "SELECT `code` FROM `code_list` WHERE `code` = ? LIMIT 1";
            $stmt = $this->db->prepare($sql);
        }
    }
    

    以后,那么你让自己熟悉 mysqli 及其缺点,考虑编写(或采用)mysqli 包装类。一个明智的一个。

    【讨论】:

    • 太棒了,所以不要写一个新类,而是按原样使用 MySQLi 类,在我的 index.php 中实例化,然后使用依赖注入将 MySQLi 对象传递给需要它的对象?
    【解决方案2】:

    几个建议:

    • 我会设计数据库类来从配置文件而不是从私有变量中读取参数。

      你可以编写一个 PHP 文件,它只声明一个数组 连接选项,然后包含()该文件。或者,写 配置文件作为一种“ini”格式文件,并使用 http://php.net/parse_ini_file 解析它。

    • 您检查了 $mysqli->connect_errno,但您既没有记录也没有输出错误消息。这将使找出连接失败的原因变得更加困难。

    • $mysqli 变量是您的 check_vars() 方法的本地变量。在该方法之外将无法访问它。

      $mysqli = new database;
      

      你应该让它成为一个类变量:

      $this->mysqli = new database;
      
    • 这是错误的:

      ...WHERE `code` = `?`
      

      参数占位符不得放在任何类型的引号内。就用这个吧:

      ...WHERE `code` = ?
      
    • 我有点同意@YourCommonSense,扩展 mysqli 类几乎没有什么好处。你可以简单地设计一个单例类:

      class Database
      {
        static $db = null;
        private __construct() { }
        public static getConnection()
        {
          if (!self::$db) {
            // read connect options from a config file
            self::$db = new mysqli(...);
            // check for errors, etc.
          }
          return self::$db;
        }
      }
      

      然后,当您需要数据库时,您可以调用静态方法Database::getConnection(),并确保每次请求只会创建一次新连接。

    【讨论】:

    • 当您说配置文件时,您的意思是在该配置文件中使用带有一组全局变量的include_once 吗?是的,connect_errno 正在进行中,我需要回到那个地方。那么我可以不将$mysqli 对象传递给check_code,还是让$mysqli 在整个课程中都可以访问,而不仅仅是方法?再次感谢@bill!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    • 2016-01-16
    相关资源
    最近更新 更多