将类从mysql迁移到mysqli

时间:2016-08-11 10:23:24

标签: mysql mysqli

您好我有一个简单的问题。我有用mysql扩展编写的类我的问题是如何将该类从mysql迁移到mysqli面向对象的样式而不是程序。 我是这个mysqli扩展的新手。

<?php
    class DBController {
        private $host = "";
        private $user = "";
        private $password = "";
        private $database = "";

        function __construct() {
            $conn = $this->connectDB();
            if(!empty($conn)) {
                $this->selectDB($conn);
            }
        }

        function connectDB() {
            $conn = mysql_connect($this->host,$this->user,$this->password);
            return $conn;
        }

        function selectDB($conn) {
            mysql_select_db($this->database,$conn);
        }

        function runQuery($query) {
            $result = mysql_query($query);
            while($row=mysql_fetch_assoc($result)) {
                $resultset[] = $row;
            }       
            if(!empty($resultset))
                return $resultset;
        }

        function numRows($query) {
            $result  = mysql_query($query);
            $rowcount = mysql_num_rows($result);
            return $rowcount;   
        }
    }
?>

1 个答案:

答案 0 :(得分:0)

拥有这样的类确实是个好主意,但是不幸的是,从mysql_* API转移到mysqli类并不是那么简单。它需要重写大量代码并改变思维方式。

如果您计划从mysql_* API进行升级,则可能意味着您到目前为止一直在使用PHP 4。如果您使用的是PHP 5,那么您将使用PHP 4的思维方式。自那时以来,PHP已经走了很长一段路。现在,我们有了适当的类,命名空间,更好的错误报告等。在数据库交互方面,我们现在有了两个新扩展:mysqli和PDO。在这两个中,您应该使用PDO。。但是,如果您使用的是包装类,那么尝试创建从mysqli到PDO的更改应该非常容易。仅出于这个原因,这样的包装器类是一个好主意。

mysqli扩展的主要原因是保持旧扩展的熟悉语法并添加必要的新功能,例如准备好的语句和正确的错误报告。 如果您习惯于将PHP变量直接放入SQL查询中,则必须改变思维方式。现在,您应该使用参数化查询并分别绑定值。

一个简单的示例,说明您的改进类是什么样的:

<?php

class DBController {
    /**
     * mysqli instance
     *
     * @var \mysqli
     */
    private $mysqli;

    public function __construct(
        $host = null,
        $username = null,
        $passwd = null,
        $dbname = null,
        $charset = 'utf8mb4',
        $port = null,
        $socket = null
    ) {
        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
        $this->mysqli = new \mysqli($host, $username, $passwd, $dbname, $port, $socket);
        $this->mysqli->set_charset($charset);
    }

    public function runQuery(string $sql, array $params = []): ?array {
        $stmt = $this->mysqli->prepare($sql);
        if ($params) {
            $stmt->bind_param(str_repeat("s", count($params)), ...$params);
        }
        $stmt->execute();
        if ($result = $stmt->get_result()) {
            return $result->fetch_all(MYSQLI_BOTH);
        }
        return null;
    }
}

警告::这不是此类包装器类的完整实现。您很可能需要实现其他方法,并根据需要添加更多逻辑。这仅是出于演示目的。

首先,在构造方法中,我们应该执行3个步骤。启用错误报告,创建mysqli类的实例,并设置正确的字符集(使用utf8mb4,它是MySQL 5.5中添加的,现在是标准字符集)。

您的runQuery()方法现在接受2个参数。第一个是使用占位符而不是插值的SQL查询,第二个是要绑定的值的数组。

很可能您不需要selectDB(),而且您绝对不需要numRows()。如果您想知道检索到的数组中的行数,可以使用count()在PHP中对其进行计数。

使用此类非常简单。

$db = new DBController('localhost', 'username', 'password', 'db_name');
$result = $db->runQuery('SELECT Id, Name FROM table1 WHERE uuid=?', ['myuuid']);
if ($result) {
    // Get the name of found record
    echo $result[0]['Name'];
} else {
    echo 'No records found';
}

如果您想将实现切换到PDO,则可以在不更改使用方式的情况下替换该类。

class DBController {
    /**
     * PDO instance
     *
     * @var \PDO
     */
    private $pdo;

    public function __construct(
        $host = null,
        $username = null,
        $passwd = null,
        $dbname = null,
        $charset = 'utf8mb4',
        $port = null,
        $socket = null
    ) {
        $dsn = "mysql:host=$host;dbname=$dbname;charset=$charset;port=$port;socket=$socket";
        $options = [
            \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
            \PDO::ATTR_EMULATE_PREPARES => false,
        ];
        $this->pdo = new PDO($dsn, $username, $passwd, $options);
    }

    public function runQuery(string $sql, array $params = []): ?array {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll();
    }
}

警告::这不是此类包装器类的完整实现。您很可能需要实现其他方法,并根据需要添加更多逻辑。这仅是出于演示目的。