[英]Migrate class from mysql to 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;
}
}
?>
擁有這樣的類是一個非常好的主意,但不幸的是,從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;
}
}
警告:這不是此類包裝器類的完整實現。 您很可能需要實現其他方法並根據需要添加更多邏輯。 這僅用於演示目的。
首先,在construct方法中,我們應該執行3個步驟。 啟用錯誤報告,創建mysqli
類的實例並設置正確的字符集(使用 MySQL 5.5 中添加的utf8mb4
,現在是標准字符集)。
您的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();
}
}
警告:這不是此類包裝器類的完整實現。 您很可能需要實現其他方法並根據需要添加更多邏輯。 這僅用於演示目的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.