phalapi-进阶篇4(notrom进阶以及事务操作)
前言
先在这里感谢phalapi框架创始人@dogstar为我们提供了这样一个优秀的开源框架。
写本篇教程的起因是因为在交流的时候有位童鞋提出了fetchPairs有BUG,之前一直没有仔细了解过notorm的细节,借此机会把notorm中的一些方便快捷的操作,以及notorm中有关事务的操作和使用,具体地作一下分析。附上:
喵了个咪的博客:w-blog.cn
开源中国Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release
1. 进一步了解notorm
notorm中很多操作在PhalApi官方文档中并没有非常详细的介绍,这里把一些常用到的notorm函数作一下相关的介绍。
1.1 fetchPairs
fetchPairs的使用和fetchAll相似但不尽相同,fetchPairs需要传递一个参数,这个参数是字符串类型的key值(比如:name 、id),当参数传递之后会出现这样的对比效果:
DI()->notorm->user->fetchPairs('name');
DI()->notorm->user->fetchAll('name');
大家有看到区别吗?
嗯!是fetchPairs在返回的时候把在之前定义的key值放到了返回数组的key中。
提示:在老版本中,使用过程中 Result.php 会有一句 821行的报错,需要把
$values = array_values(iterator_to_array($row));
改成
$values = array_values($row);
1.2 lock
lock操作是一种锁的行为,对整表进行锁定,在当前用户释放锁之前此表不能再被操作。lock接受一个bool参数,默认是true,即锁表,使用如下:
$userdb = DI()->notorm->user->lock(); //锁定表
$rs = $userdb->fetchAll();
生成的sql语句如下:
SELECT * FROM user FOR UPDATE;
1.3 加操作
在很多时候,我们会遇到数据库表里面的某个值需要+1操作,我们不能简单地在update的时候写入array('key' => 'key+1'),因为在解析sql的时候,key+1 会带上引号作为一个字符串被处理,所以,这样的操作并没有达到我们想要的效果,当然,这是有解决方法的。具体操作如下:
DI()->notorm->user->where('id', 1)->update(array('sum' => new NotORM_Literal("sum + 1")));
这样就可以生成不带引号的操作了:
UPDATE user SET phone = sum + 1 WHERE (id = 1);
1.4 group
group是去重操作,在notorm里面也有封装,我们可以使用group来统计比如有多少同名的用户等一些统计操作,或者是找出库里面不重复的城市名等。
DI()->notorm->user->select('name , count(*) as count')->group('name')->fetchAll();
会获得如下结果
1.5 快速函数sum,count,max,min
在我们使用notorm快速函数的过程中,虽然此类函数使用频率不高,但是使用起来却是很方便:
return DI()->notorm->user->sum('id'); //做加法
return DI()->notorm->user->max('id'); //获取这个key中最大的值
return DI()->notorm->user->min('id'); //获取这个key中最小的值
return DI()->notorm->user->count(); //统计一共几条数据
2. 事务操作
其实,很大一部分使用事务的原因是因为害怕在并发的情况下导致对数据库造成的重复操作,比如如下场景:
两个管理者对同一应用进行审核。他们同一时间查询到应用的状态都是未审核,然后都进行了审核操作,这时,返回的审核操作状态是成功的。但这时,会有一个管理者会发现审核状态和自己的审核结果不同,这就有问题了。大部分在解决此类问题时,都会考虑使用数据库的事务操作。其实,对于事务操作,我的建议是:能不用尽量不用。我简单聊一下我的几个观点:
是否真的那么重要?对于上面的问题,也许乍一看觉得:这怎么可能呢?但是仔细一想,这两个操作都是属于两个管理者的正常操作。对于业务来说,我认为是没有问题的。当然这是因为影响不大;如果是付款,一个订单从两个地方同时付款,然后都发现是未付款,然后都进行了付款,这种业务就必须有处理方式了,所以是否使用事务要看业务是否非常重要。
概率是怎么样的?对于一个程序来说,两个请求刚好通过了查询过程,并一同到了修改的操作,不管是什么场景,发生这种并发冲突的可能性是极其微小的,我觉得几乎可以忽略(当然前提是重要性没有那么的高,我们不能 以偏概全 )。
曲线救国,其实,我们可以使用其他方式避免这类问题。我们可以把我们需要验证条件加入到Update的条件中,这样两条语句终归会有一条语句执行失败。
notorm中使用到的事务操作方式:
notorm提供了常规的事务操作如下:
//第一步:先指定待进行事务的数据库(通过获取一个notorm表实例来指定;否则会提示:PDO There is no active transaction)
$user = DI()->notorm->user;
//第二步:开启事务开关(此开关会将当前全部打开的数据库都进行此设置)
DI()->notorm->transaction = 'BEGIN';
//第三步:进行数据库操作
$user->insert(array('name' => 'test3',));
$user->insert(array('name' => 'test4',));
//第四:提交/回滚
DI()->notorm->transaction = 'COMMIT';
//DI()->notorm->transaction = 'ROLLBACK';
还有一种处理方式就是在操作之前进行lock锁表
$user = DI()->notorm->user;
$user->lock();
$user->insert(array('name' => 'test3',));
$user->insert(array('name' => 'test4',));
这两种方式大家可以自行取舍。
注:在phalapiV1.31版本后有自带提供事务操作可参考文档。
3. 总结
在本小节中,对于notorm中的一些特别的封装函数进行了介绍,对于事务提出了自己的看法和观点以及使用notorm的解决方案。希望看了这篇教程的童鞋,在日常开发中对你有所帮助。
注:笔者能力有限,有说的不对的地方,希望大家能够指出,也希望多多交流!
官网QQ交流群:421032344 欢迎大家的加入!