php框架如何编程,怎么一步步编写简单的PHP的Framework(十九)

上一次我说了一下怎么从ModelBase通过Sql parse将SQL拆分,也就是解析的过程,今天我详细的说一下。

首先,我们实现函数的链式操作,即如:$this->where()->table()->select()

我们知道,如果要实现这种函数链,需要return $this,所以我们要保证在调用select方法之前的所有函数都要返回$this,也就是这个对象,最简单的方法就是在每个方法的最后执行return $this,但是这样实在是一个麻烦的事情,我们都知道PHP有一系列的魔术方法可以实现非常强大的功能,今天我们就要用到其中的一个魔术方法:__call,这儿方法是调用了对象中一个不存在的方法时调用的,也就是系统在抛出错误之前进行最后一次挽救,如果有__call,那么就将决定权交给__call,否则直接抛出错误。

所以我们可以在ModelBase中定义一个__call方法,这个方法的内容如下:

public function __call($method,$args) {

if(in_array($method,array(

'where','field','distinct','table','order','group'

))) {

$this->_options[$method] = isset($args[0]) ? $args[0] : null;

return $this;

} else {

parent::__call($method,$args);

}

}

由于我们在Base中也定义了__call,所以如果我们在这个类中的__call中无法处理的话,我们需要将控制权交给Base。

由__call方法控制的方法是where,field,distinct,table,order,group,当然,这个不一定是全部的,我暂时就写这么几个,你们读了上次的文章应该知道这几个函数是处理什么内容了吧。

这个__call方法执行的也很简单,就是在$this->_options数组里面将调用的方法的参数存储起来,这样用来做什么呢,这是为了后面Sql  parse调用的。

我们把处理SQL的这个类称为SqlParser,那么SqlParser现在最少有以下几个方法:

private function _where($where){}

private function _field($field) {}

private function _distinct($distinct) {}

private function _table($table) {}

private function _order($order) {}

private function _group($group) {}

可能你们会问为什么我要把这些方法设置为private呢,因为直接和ModelBase打交道的不是这些方法,假设我们把和ModelBase交互的这个方法称为execute,那么我们在ModelBase中只需要调用:

$this->_sqlParser->execute($this->_options);

这个调用过程应该在哪儿调用呢,应该在select函数执行的时候。

public function select() {

$this->_sqlParser->execute($this->_options);

$this->_db->prepare($this->_sqlParser->getSql());

$this->_db->execute($this->_sqlParser->getParams());

}

这个就是ModelBase的select方法的代码,它实际上调用了sqlParser的实例的execute方法,然后在通过SqlParser的getSql和getParams方法获取SQL和参数分别交给驱动类的prepare和execute执行。

那么现在ModelBase的代码就变成如下了:

class ModelBase extends Base {

protected $_db = null;

private $_sqlParser = null;

private $_options = array(

'where' => '',

'field' => '',

'distinct' => '',

'table' => '',

'order' => '',

'group' => ''

);

public function __construct() {

$this->_db = ConnectionManager::getConnection();

$this->_sqlParser = new SqlParser();

}

public function execute($sql,Array $arr) {

$this->_db->prepare($sql);

$this->_db->execute($arr);

}

public function getAll() {

return $this->_db->getAllByAssocArray();

}

public function __call($method,$args) {

if(in_array($method,array(

'where','field','distinct','table','order','group'

))) {

$this->_options[$method] = isset($args[0]) ? $args[0] : null;

return $this;

} else {

parent::__call($method,$args);

}

}

public function select() {

$this->_sqlParser->execute($this->_options);

$this->_db->prepare($this->_sqlParser->getSql());

$this->_db->execute($this->_sqlParser->getParams());

}

}         那么SqlParser的代码是怎么样的呢,是这样的:

class SqlParser extends Base {

private static $_templateSql = 'SELECT :distinct :field FROM :table WHERE :where :order :group';

private $_sql = '';

private $_params = array();

public function execute(Array $options) {

$this->_sql = str_replace(array(

':distinct',':field',':table',':where',':group',':order'

),array(

$this->_distinct($options['distinct']),

$this->_field($options['field']),

$this->_table($options['table']),

$this->_where($options['where']),

$this->_group($options['group']),

$this->_order($options['order'])

),self::$_templateSql);

}

public function getSql() {

return $this->_sql;

}

public function getParams() {

return $this->_params;

}

private function _distinct($distinct) {

return 'distinct';

}

private function _field($field) {

return 'field';

}

private function _table($table) {

return 'table';

}

private function _where($where) {

return 'where';

}

private function _group($group) {

return 'group';

}

private function _order($order) {

return 'order';

}

}      在execute方法中,只需要按照SQL的模板(在变量templateSql中定义的)替换就行,比如对于templateSql中的:distinct(这个变量是用来占位的),当调用了$this->_distinct之后就会将templateSql中的:distinct替换成为相应的字符串。

现在为了方便查看,对这几个比较重要的方法,我们都返回了一个字符串,这种后面SQL执行的时候肯定会报错,由于暂时我们没有写这些函数的具体实现,所以暂时就这样吧。

好了,也差不多就这样吧,下次再继续了!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值