当前位置:K88软件开发文章中心网站服务器框架ThinkPHP → 文章内容

高级模型

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-26 15:33:28

由 AdairSweet 创建, 最后一次修改 2016-02-24 高级模型提供了更多的查询功能和模型增强功能,利用了模型类的扩展机制实现。如果需要使用高级模型的下面这些功能,记得需要继承Think\Model\AdvModel类或者采用动态模型。namespace Home\Model;use Think\Model\AdvModel;class UserModel extends AdvModel{ }我们下面的示例都假设UserModel类继承自Think\Model\AdvModel类。字段过滤基础模型类内置有数据自动完成功能,可以对字段进行过滤,但是必须通过Create方法调用才能生效。高级模型类的字段过滤功能却可以不受create方法的调用限制,可以在模型里面定义各个字段的过滤机制,包括写入过滤和读取过滤。字段过滤的设置方式只需要在Model类里面添加 $_filter属性,并且加入过滤因子,格式如下:protected $_filter = array( '过滤的字段'=>array('写入过滤规则','读取过滤规则',是否传入整个数据对象), )过滤的规则是一个函数,如果设置传入整个数据对象,那么函数的参数就是整个数据对象,默认是传入数据对象中该字段的值。举例说明,例如我们需要在发表文章的时候对文章内容进行安全过滤,并且希望在读取的时候进行截取前面255个字符,那么可以设置:protected $_filter = array( 'content'=>array('contentWriteFilter','contentReadFilter'), )其中,contentWriteFilter是自定义的对字符串进行安全过滤的函数,而contentReadFilter是自定义的一个对内容进行截取的函数。通常我们可以在项目的公共函数文件里面定义这些函数。序列化字段序列化字段是新版推出的新功能,可以用简单的数据表字段完成复杂的表单数据存储,尤其是动态的表单数据字段。 要使用序列化字段的功能,只需要在模型中定义serializeField属性,定义格式如下:protected $serializeField = array( 'info' => array('name', 'email', 'address'), );Info是数据表中的实际存在的字段,保存到其中的值是name、email和address三个表单字段的序列化结果。序列化字段功能可以在数据写入的时候进行自动序列化,并且在读出数据表的时候自动反序列化,这一切都无需手动进行。下面还是是User数据表为例,假设其中并不存在name、email和address字段,但是设计了一个文本类型的info字段,那么下面的代码是可行的:$User = D("User"); // 实例化User对象 // 然后直接给数据对象赋值$User->name = 'ThinkPHP';$User->email = 'ThinkPHP@gmail.com';$User->address = '上海徐汇区'; // 把数据对象添加到数据库 name email和address会自动序列化后保存到info字段$User->add();查询用户数据信息$User->find(8); // 查询结果会自动把info字段的值反序列化后生成name、email和address属性 // 输出序列化字段echo $User->name;echo $User->email;echo $User->address;文本字段ThinkPHP支持数据模型中的个别字段采用文本方式存储,这些字段就称为文本字段,通常可以用于某些Text或者Blob字段,或者是经常更新的数据表字段。要使用文本字段非常简单,只要在模型里面定义blobFields属性就行了。例如,我们需要对Blog模型的content字段使用文本字段,那么就可以使用下面的定义:Protected $blobFields = array('content');系统在查询和写入数据库的时候会自动检测文本字段,并且支持多个字段的定义。需要注意的是:对于定义的文本字段并不需要数据库有对应的字段,完全是另外的。而且,暂时不支持对文本字段的搜索功能。只读字段只读字段用来保护某些特殊的字段值不被更改,这个字段的值一旦写入,就无法更改。 要使用只读字段的功能,我们只需要在模型中定义readonlyField属性protected $readonlyField = array('name', 'email');例如,上面定义了当前模型的name和email字段为只读字段,不允许被更改。也就是说当执行save方法之前会自动过滤到只读字段的值,避免更新到数据库。下面举个例子说明下:$User = D("User"); // 实例化User对象$User->find(8); // 更改某些字段的值$User->name = 'TOPThink';$User->email = 'Topthink@gmail.com';$User->address = '上海静安区'; // 保存更改后的用户数据$User->save();事实上,由于我们对name和email字段设置了只读,因此只有address字段的值被更新了,而name和email的值仍然还是更新之前的值。悲观锁和乐观锁业务逻辑的实现过程中,往往需要保证数据访问的排他性。如在金融系统的日终结算处理中,我们希望针对某个时间点的数据进行处理,而不希望在结算进行过程中(可能是几秒种,也可能是几个小时),数据再发生变化。此时,我们就需要通过一些机制来保证这些数据在某个操作过程中不会被外界修改,这样的机制,在这里,也就是所谓的 “ 锁 ” ,即给我们选定的目标数据上锁,使其无法被其他程序修改。 ThinkPHP支持两种锁机制:即通常所说的 “ 悲观锁( Pessimistic Locking ) ”和 “ 乐观锁( Optimistic Locking ) ” 。悲观锁( Pessimistic Locking )悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。 通常是使用for update子句来实现悲观锁机制。ThinkPHP支持悲观锁机制,默认情况下,是关闭悲观锁功能的,要在查询和更新的时候启用悲观锁功能,可以通过使用之前提到的查询锁定方法,例如:$User->lock(true)->save($data);// 使用悲观锁功能乐观锁( Optimistic Locking )相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。 如一个金融系统,当某个操作员读取用户的数据,并在读出的用户数据的基础上进行修改时(如更改用户帐户余额),如果采用悲观锁机制,也就意味着整个操作过程中(从操作员读出数据、开始修改直至提交修改结果的全过程,甚至还包括操作员

[1] [2]  下一页


高级模型