如何寫一個(gè)屬于自己的數(shù)據(jù)庫(kù)封裝(1) - 基本思路(修訂版)

下一期 如何寫一個(gè)屬于自己的數(shù)據(jù)庫(kù)封裝(2) - 數(shù)據(jù)庫(kù)連接

寫在前頭

  1. 依然在前進(jìn)的菜鳥一只,錯(cuò)誤什么的請(qǐng)輕噴指出
  2. 對(duì)于數(shù)據(jù)庫(kù)連接由于較淺的工作經(jīng)驗(yàn)所以無法完全覆蓋棚蓄,較復(fù)雜的query可能會(huì)有意想不到的bug
  3. 所以本系列只提供思路败砂,成熟穩(wěn)定的數(shù)據(jù)庫(kù)封裝有請(qǐng)自行搜索
  4. 編寫該系列的初衷就是為了拋磚引玉昧诱, 在每一節(jié)的后端拥刻,我都會(huì)提出一些個(gè)人疑問(或無)抹竹,希望能引出大神為我解答迷惑
  5. 使用的php版本為7.0+线罕,該系列并不向下兼容,還在5.6版本的童鞋們快過來玩呀
  6. 數(shù)據(jù)庫(kù)封裝參考了laravel的源代碼柒莉, 如有雷同闻坚, 不是巧合

最終效果

假設(shè)我們有一個(gè)表,名'Actor', 經(jīng)過簡(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();

更多例子可以查看第4期 - 如何寫一個(gè)屬于自己的數(shù)據(jù)庫(kù)封裝(4) - 查詢 - 入門篇用法

本期知識(shí)點(diǎn)

【PHP】PDO操作數(shù)據(jù)庫(kù)

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

對(duì)php有一定了解的人都知道,相比已被淘汰的mysql或取而代之的mysqli兢孝, pdo 可以避免SQL注入式攻擊窿凤, 更安全, 而且面向?qū)ο螅?所以請(qǐng)看下方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)潔, 然而, 這么做真的好嗎?

很多菜鳥因?yàn)榻?jīng)驗(yàn)或自身的原因, 在實(shí)現(xiàn)業(yè)務(wù)邏輯時(shí)并未考慮過維護(hù)代碼, 要不重復(fù)性代碼全寫在一塊, 要不隨便寫個(gè)函數(shù)概括進(jìn)去, 這一類代碼, 是導(dǎo)致經(jīng)手人辭職的最大元兇

代碼太爛了我看不下去

因此, 考慮到一個(gè)項(xiàng)目長(zhǎng)遠(yuǎn)開發(fā), 我們需要一個(gè)封裝類來減少代碼的重復(fù)性跨蟹, 就像平時(shí)自行寫的一些輔助函數(shù)雳殊, 不過封裝類略微進(jìn)階而已。

基本思路

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

$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 - 入口文件澳厢,作為一個(gè)模型, 定義表的各種屬性(如主鍵, 表名等等), 并接受請(qǐng)求旨指, 返回?cái)?shù)據(jù)庫(kù)數(shù)據(jù)
  • 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)可能解釋得不太好,但沒關(guān)系搬素, 接下來會(huì)慢慢一個(gè)個(gè)的深入解釋

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

下一期 如何寫一個(gè)屬于自己的數(shù)據(jù)庫(kù)封裝(2) - 數(shù)據(jù)庫(kù)連接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市粱哼,隨后出現(xiàn)的幾起案子季二,更是在濱河造成了極大的恐慌,老刑警劉巖揭措,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胯舷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡绊含,警方通過查閱死者的電腦和手機(jī)桑嘶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躬充,“玉大人逃顶,你說我怎么就攤上這事〕渖酰” “怎么了以政?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)伴找。 經(jīng)常有香客問我妙蔗,道長(zhǎng),這世上最難降的妖魔是什么疆瑰? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任眉反,我火速辦了婚禮,結(jié)果婚禮上穆役,老公的妹妹穿的比我還像新娘寸五。我一直安慰自己,他們只是感情好耿币,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布梳杏。 她就那樣靜靜地躺著,像睡著了一般淹接。 火紅的嫁衣襯著肌膚如雪十性。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天塑悼,我揣著相機(jī)與錄音劲适,去河邊找鬼。 笑死厢蒜,一個(gè)胖子當(dāng)著我的面吹牛霞势,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播斑鸦,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼愕贡,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了巷屿?” 一聲冷哼從身側(cè)響起固以,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘱巾,沒想到半個(gè)月后憨琳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浓冒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年栽渴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稳懒。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闲擦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出场梆,到底是詐尸還是另有隱情墅冷,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布或油,位于F島的核電站寞忿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏顶岸。R本人自食惡果不足惜腔彰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一叫编、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧霹抛,春花似錦搓逾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至端逼,卻和暖如春朗兵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背顶滩。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工余掖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人诲祸。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓浊吏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親救氯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子找田,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容