之前我们说了一下SqlParser这个类的execute怎么实现的,实际上这个函数叫execute是不合适的,因为它只能完成select操作,而update,insert,delete操作是不能完成的,最好将其修改为select,这样从名字上就很容易看出它的含义。
实际上我们现在只是实现了select的解析,而这种解析现在也很不完善,比如having,limit这种就没有加进来,如果有join操作,这种更完不成,如果你们有兴趣,可以自己下去再好好扩展一下,实际上基本思路还是不难的。
相对于select,update,insert,delete就不是很难了,一个基础的update为:UPDATE :table SET :condition :where,那么实际上这种函数只需要将update的SQL模板的:table,:condition部分的数据替换即可,:table部分可以使用SqlParser的_table这个方法,而:condition就需要重新编写了,:where复用SqlParser的_where方法。
insert也很类似,INSERT INTO :table :condition,:table还是复用SqlParser的_table方法,而:condition需要重写,对于delete,基本的为:DELETE FROM :table :where,这个地方的:table可以复用SqlParser的_table方法,:where可以复用SqlParser的_where方法。
假设现在select,insert,update,delete都完成了,那么一些基本操作就变得很简单了。
select:
$this->where(array( 'tid' => array('gt',2 ))->table('test')->select();
update:
$this->table('test')->where(array( 'tid' > array('gt',1)))->update(array( 'test' => 'aaaaa'));
insert:
$this->table('test')->insert(array( 'tid' => 2, 'test' => 'bbb'));
delete:
$this->table('test')->where(array( 'tid' => array('gt',2)))->delete();
我们知道,用户可访问的是DbTable,DbRelation,而这两个都是继承了ModelBase,分别为不同的模型实现了一些基础的功能,那么它是怎么弄的呢?
我们以DbTable举例,DbTable是一个表模型,那么它必须有一个字段唯一标识这个模型,这就是表的主键,当然,也存在那种多个字段为主键的情况,我们这儿就不讨论了。
之前我也说过了,DbTable有四个比较重要的变量,它们是protected的:
protected $_pk = null; protected $_tableInfo = array(); protected $_tablePrefix = ''; protected $_tableName = '';
$pk标识主键,$_tableInfo记录表的字段名,$_tablePrefix标示表的前缀,$_tableName是逻辑表名,也就是没有加前缀的表明,如果一个表的实际表名为t_test,那么$_tablePrefix为t_,$_tableName为test。
这儿我们定义一个useTable函数,它可以将逻辑表名转换为物理表名:
public function userTable($table) { return $this->_tablePrefix . $table; }然后我们来实现以下select,如果调用ModelBase,那么必须制定table,否则这个SQL就是错误的,但是在DbTable中,应该框架可以自动识别,那么一个简单的SQL就可以这么使用了:
$this->select();
这个就会被解析为:select * from test。
那么这个select函数怎么编写呢,其实就是判定一下$_options里面是否指定了table,如果没有,那么指定一下默认的表,然后就调用父类的select。
具体的实现如下:
public function select() { if('' === $this->_options['table']) { $this->_options['table'] = $this->_tablePrefix . $this->_tableName; } parent::select(); }
简单吧,但是注意哦,之前我们编写ModelBase的时候,$_options是设置为了private,现在需要将其修改为protected。
关于insert,update,delete实际上思路都很类似,由于这几个函数都需要使用到设置默认的表,所以可以将这句话独立为一个函数。
这样看来,DbTable实际上非常简单,它不做具体的实现,只是调用接口完成功能即可,刚才我们都是通过函数链执行SQL,而我个人感觉对于复杂的SQL,用这种方式效率很低下,所以我建议使用execute方法,这个方法会直接调用驱动类的execute方法,而不经过SqlParser这一层。当然,如果你觉得对于简单的SQL,这种方式也是不可忍受的,你也可以所有SQL都使用execute。
DbTable我就这样一笔带过了,DbRelation我就不讲了,关于模型我就说这么多了,我讲的比较快,实际上中间还是有很多问题需要考虑的,大家可以自己琢磨琢磨。
为什么我要这么讲这么快呢,因为我马上要离开公司,回家之后由于没有网络,就写不了这个了,那样最快更新也要下学期了,很麻烦,所以尽量在走之前搞定!!!