micro activerecord library in PHP(一個微型的PHP實現的AR庫)

一個微型的PHP實現的AR庫

體積很小帶詳盡的註釋總共只有400行
支持鏈式調用
支持關係php

前言

最開始接觸ActiveRecord是在學習Yii的時候,那個時候以爲用AR操做數據庫真的是太方便了。以致於後來轉向其餘的一些框架的時候,感受沒有了AR彷佛就不能操做數據庫了同樣!!!特別是中間本身使用一些簡單的說不上框架的東西來寫微型的PHP站點的時候,感受手寫SQL太難看。
後來也接觸過一些優秀的獨立的ORM的庫,好比我最喜歡的idiorm. 甚至曾經萌生了想要把Yii的AR單獨拿出來用的想法!可是後來仍是沒有實現。。。
在13年的時候,有一段時間上班時間太悠閒,因此當時就想本身實現一個ActiveRecord類,一來打算練練手,而來也打算本身之後用的上。git

準備

在開始動手寫以前,在github,以及stackoverflow上面尋找了一大堆的php的AR庫或者ORM的庫。github

  1. https://github.com/j4mie/idiorm數據庫

  2. https://github.com/vrana/notorm安全

  3. https://github.com/PrimalPHP/Recordcomposer

  4. https://github.com/spadgos/Record框架

  5. https://github.com/sgoen/php.pdo.orm函數

  6. https://github.com/jaceju/example-my-orm學習

固然其中最好的就是idiorm以及notorm,在github上門分別有1600+和600+的star。
拿idiorm來講,我的很是喜歡它提供的接口以及使用方式。並且整個庫也就單個文件,雖然文件將近2500行。可是已經算是一個小型的庫了。固然文件有點長,看起來有點費勁。
相對而言notorm設計得更加OO一些。不過在其中的NotORM_Result這個class中明顯看到一大片字符串拼接SQL的方式,仍是讓人以爲看起來不是很好。測試

設計

在看了一堆這樣的ORM的庫以後,很是反感那種直接拼接SQL的方式,可是這又是一個沒法避開的問題,最後老是須要生成一個SQL字符串的。
關鍵在於須要找出一種比較」優雅「的方式來完成這個拼接的工做。

表達式

有一天在看拼接的SQL的時候偶然間感受SQL裏面where後面的那些查詢條件老是一個一個的表達式(一個操做數加上一個操做符再加上一個操做數,例如:name='demo' and email='demo@demo.com')。

這個表達式的結構看起來和數學裏面的(1+1)*(2+2)是那麼的相像。

甚至連and,or也是一個一個的操做符而已。再提煉一下除了二元表達式,還有一元表達式(只有一個操做數的表達式,相似數學裏面的-1)。這樣算起來SQL裏面的select,from,where,delete,update這樣的關鍵詞均可以算成是」操做符「了。

那麼一個簡單的SQL就能夠分解成一個一個的表達式:

select email, password from `user` where email = 'demo@demo.com';
  1. select email, password

  2. from user

  3. where email = 'demo@demo.com'

  4. email = 'demo@demo.com'

上面的SQL總共拆分出來了4個表達式,其中where部分是嵌套的一個表達式。

實現

Expressions

因此,我專門定義了一個Expressions類用來表示SQL中的各個部分。這個類只有一個__toString方法在最後須要的時候生成SQL

class Expressions extends Base {
    public function __toString() {
        return $this->source. ' '. $this->operator. ' '. $this->target;
    }
}

固然還有比較特殊的表達式就是"()",這個表達式特殊在於操做符是分開的。

接口

當提煉出來了表達式的類以後,那麼在使用ActiveRecord查詢數據庫的時候,每輸入一個動詞,都只是在適當的地方插入一個表達式而已。只有在最後的時候纔會一次性的調用每個表達式的__toString方法組合SQL,爲了安全考慮,使用了PDO的綁定參數的形式防止SQL注入的風險!
好比:

$user->equal('id', 1);
只是在where子句裏面生成了一個 "id=:ph1"的表達式,同時保存了一個array(':ph1'=>1)的參數而已。一樣的還提供了簡寫的」eq「以及」ne「,」ge「等接口函數。另外還有」select「,」from「,」group「,」order「,」limit「,」top「以及」where「等接口函數。

魔術方法

爲了減小代碼量,因此這裏使用了__call魔術方法避免了爲每個動做都去定義個method。

關係

除了實現SQL的基本操做,還實現了一下相似Yii的ActiveRecord法讓Relation的方法能夠簡單的經過主外鍵關係查詢數據。
定義了」HAS_ONE「,」HAS_MANY「和」BELONGS_TO「三種關係。
能夠在定義關係以後,能經過簡單的的訪問屬性的方式得到關聯的數據。

項目

項目地址:https://github.com/lloydzhou/activerecord
文檔地址:https://lloydzhou.github.io/activerecord
已經提交到packagist.org能夠經過composer安裝

composer require lloydzhou/activerecord

DEMO

爲了一邊測試,一邊完善這個庫。因此使用這個庫結合另一個RouterMicroTpl 寫了一個簡單的 博客 ,裏面基本涵蓋了這幾個庫的API。

相關文章
相關標籤/搜索