明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

如何寫一個(gè)屬于自己的數(shù)據(jù)庫(kù)封裝(1)

[摘要]寫在前頭依然在前進(jìn)的菜鳥一只,錯(cuò)誤什么的請(qǐng)輕噴指出對(duì)于數(shù)據(jù)庫(kù)連接由于較淺的工作經(jīng)驗(yàn)所以無(wú)法完全覆蓋,較復(fù)雜的query可能會(huì)有意想不到的bug所以本系列只提供思路,成熟穩(wěn)定的數(shù)據(jù)庫(kù)封裝有請(qǐng)自行搜索編寫該系列的初衷就是為了拋磚引玉, 在每一節(jié)的后端,我都會(huì)提出一些個(gè)人疑問(wèn)(或無(wú)),希望能引出大神為我...

寫在前頭

  1. 依然在前進(jìn)的菜鳥一只,錯(cuò)誤什么的請(qǐng)輕噴指出

  2. 對(duì)于數(shù)據(jù)庫(kù)連接由于較淺的工作經(jīng)驗(yàn)所以無(wú)法完全覆蓋,較復(fù)雜的query可能會(huì)有意想不到的bug

  3. 所以本系列只提供思路,成熟穩(wěn)定的數(shù)據(jù)庫(kù)封裝有請(qǐng)自行搜索

  4. 編寫該系列的初衷就是為了拋磚引玉, 在每一節(jié)的后端,我都會(huì)提出一些個(gè)人疑問(wèn)(或無(wú)),希望能引出大神為我解答迷惑

  5. 使用的php版本為7.0+,該系列并不向下兼容,還在5.6版本的童鞋們快過(guò)來(lái)玩呀

  6. 數(shù)據(jù)庫(kù)封裝參考了laravel的源代碼, 如有雷同, 不是巧合

最終效果

假設(shè)我們有一個(gè)表,名'Actor', 經(jīng)過(guò)簡(jiǎn)單設(shè)置, 可以直接如下調(diào)用

$a = Actor::select('first_name', 'last_name')
        ->where('first_name', 'NICK')
        ->where('last_name', 'WAHLBERG')
        ->first()
var_dump($a);

返回格式

object(Actor)[11]
  public 'first_name' => string 'NICK' (length=4)
  public 'last_name' => string 'WAHLBERG' (length=8)

返回的數(shù)據(jù)依然可操作(update/delete)

$a->update(...);
$a->delete();

常見(jiàn)的數(shù)據(jù)庫(kù)連接寫法

對(duì)php有一定了解的人都知道,相比已被淘汰的mysql或取而代之的mysqli, pdo 可以避免SQL注入式攻擊, 更安全, 而且面向?qū)ο?/a>, 所以以下以pdo作為例子

<?php
$driver='mysql'; //數(shù)據(jù)庫(kù)類型

$host='localhost'; //數(shù)據(jù)庫(kù)主機(jī)名

$db = 'sakila'; //數(shù)據(jù)庫(kù)名稱

$username='root'; //數(shù)據(jù)庫(kù)連接用戶名

$password=''; //數(shù)據(jù)庫(kù)密碼

$dsn="$driver:host=$host;dbname=$db";

try {    
    $pdo= new PDO($dsn, $username, $password); //初始化一個(gè)PDO對(duì)象   

    $sql = "select * from actor";

    $res = $pdo->query($sql); // 從actor中獲取所有數(shù)據(jù)

    foreach($res as $row) echo $row['first_name']."<br>";

} catch (PDOException $e) {    
    die($e->getMessage());
}

以上例子非常簡(jiǎn)潔, 當(dāng)一個(gè)項(xiàng)目逐漸成長(zhǎng),日漸復(fù)繁的時(shí)候,那么我們需要一個(gè)封裝類來(lái)減少代碼的重復(fù)性, 就像平時(shí)自行寫的一些輔助函數(shù), 不過(guò)封裝類略微進(jìn)階而已。

基本思路

那么,應(yīng)該怎么寫呢?
首先, 平時(shí)我們要簡(jiǎn)略一些代碼, 都會(huì)自行編寫一些輔助函數(shù),比如我個(gè)人有個(gè)不好的習(xí)慣,不喜歡用編輯器調(diào)試功能(畫外音:我用的是sublime text 3),那么debug的時(shí)候一開(kāi)始都是這么寫的

$a = "is bug";
die(var_dump($a)); // 輸出變量并且停止運(yùn)行之后的代碼
/***從xdebug得知bug出現(xiàn)在這一行,所以查看上一行的邏輯與數(shù)據(jù) ***/

die(var_dump())的出場(chǎng)率略高, 因此我將它們寫成了一個(gè)輔助函數(shù)

function dd($var) {
    die(var_dump($var));
}

同樣道理,在數(shù)據(jù)庫(kù)讀取的時(shí)候,select的出場(chǎng)率極高, 所以簡(jiǎn)單的包裹一下

function select($pdo, $table, $require, $where = []) {
    $w = [];

    // 將搜索條件轉(zhuǎn)化為數(shù)據(jù)庫(kù)命令能接受的格式
    foreach ($where as $key => &$val) 
        $w[] = "$key = '$val'";

    // 有時(shí)候并不需要條件,僅僅將所有數(shù)據(jù)取出,因此$where默認(rèn)為空
    if(!empty($w)) $w = "where ".implode(', ', $w);
    else $w = "";

    // 生成sql query
    $sql = "select $require from $table $w";

    // 將已生成的query帶入pdo實(shí)例
    $res = $pdo->query($sql);

    // 返回結(jié)果
    return $res->fetchAll();
}

例子

select($pdo, 'actor', '*', ['first_name'=>'PENELOPE'])
/** 
  * 生成sql query => select * from actor where first_name = 'PENELOPE'
**/

總結(jié)一下, 數(shù)據(jù)庫(kù)封裝淺顯的形容就是將參數(shù)帶入輔助函數(shù),讓其自動(dòng)生成SQL命令。

數(shù)據(jù)庫(kù)封裝的架構(gòu)

主要分成四個(gè)文件

  • Connector.php - 負(fù)責(zé)與數(shù)據(jù)庫(kù)的通信, 請(qǐng)求與返回?cái)?shù)據(jù)庫(kù)數(shù)據(jù)

  • Model.php - 入口文件,負(fù)責(zé)表的設(shè)置, 并接受請(qǐng)求, 返回回應(yīng)

  • Grammar.php - 將Builder存儲(chǔ)的請(qǐng)求轉(zhuǎn)化為SQL語(yǔ)句

  • Builder.php - 核心文件, 存儲(chǔ)Model的請(qǐng)求,調(diào)用Grammar以返回SQL語(yǔ)句, 與參數(shù)變量一并送往Connector以獲取數(shù)據(jù)庫(kù)數(shù)據(jù),再返還給Model

架構(gòu)可能解釋得不太好,但沒(méi)關(guān)系, 接下來(lái)會(huì)慢慢一個(gè)個(gè)的深入解釋

大致如此, 如果可以的話點(diǎn)個(gè)贊,或在下方評(píng)論區(qū)討論, 只有反饋才能推動(dòng)一個(gè)懶癌晚期病患繼續(xù)前行。

以上就是如何寫一個(gè)屬于自己的數(shù)據(jù)庫(kù)封裝(1)的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!


學(xué)習(xí)教程快速掌握從入門到精通的SQL知識(shí)。