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。

相关文章
相关标签/搜索