413 12
发新话题
打印

ThinkPHP高级指南

ThinkPHP高级指南

4.1 分页支持
ThinkPHP内置了分页类,位于 ORG.Util.Page ,使用举例:
  • $dao = D('User');
  • $count      = $dao->getCount();
  • import("ORG.Util.Page");
  • if(!empty($_REQUEST['listRows'])) {
  •   $listRows  =  $_REQUEST['listRows'];
  • }else{
  •   $listRows=4;
  • }
  • $p= new Page($count,$listRows);
  • $list=$dao->findAll('','','*','id asc',$p->firstRow.','.$p->listRows);
  • $page= $p->show();
  • $this->assign("page",$page);
  • $this->assign("userList",$list);



在模版文件中,使用标签
  • {$page}


就可用输出分页
显示效果

其中每页显示的记录数、页数等信息均可以修改。

如果需要定制分页的显示,可以使用下面的方式输出分页
  • $page= $p->show(true);
  • $this->assign("page",$page);


然后,在模版文件里面自己添加下面的变量
  • $page['totalRows'] // 总的记录数
  • $page['upPage'] // 上一页链接
  • $page['downPage'] // 下一页链接
  • $page['totalPages'] // 总页数
  • $page['firstPage'] // 第一页链接
  • $page['endPage'] // 最后一页链接
  • $page['nextPages'] //下一个链接页(比如说设置每页显示5页链接,这里指的是下一个5页)
  • $page['prePages'] // 上一个链接页
  • $page['linkPages'] // 当前链接页
  • $page['nowPage'] // 当前页


不过,目前这种方式还是存在一定不足,更好的方式是自己扩展一个Page类来定制输出。

TOP

4.2 关联查询
关于ThinkPHP的关联查询支持。
目前支持的表间关联方式包括三种:
  • 1、ONE_TO_ONE ( 包括HAS_ONE 和 BELONGS_TO )
  • 2、ONE_TO_MANY( 包括HAS_MANY 和 BELONGS_TO)
  • 3、MANY_TO_MANY


Dao类增加了一个xfind() 方法用于直接获取带关联记录的返回结果,而 getRelation() 方法用于获取已经返回记录的关联记录(集)。
xfind的参数和find方法保持不变,区别在于xfind方法会一起返回关联记录,而find方法默认不返回关联记录。
find方法最后增加了一个relation参数,用以控制是否进行关联查询。 xfind方法仅仅是find方法的一个引用。relation参数支持false(不进行关联查询)、true(进行所有关联查询)和array(只查询某个关联)。
举例:
  • $dao->find("id=2"); // 返回id为2的记录
  • $dao->xfind("id=2"); // 返回id为2的记录,并同时返回其关联记录(如果有定义)



如果不是使用find方法进行查询,可以配合getRelation方法进行关联记录的查询。
例如:
  • $user = $dao->getById($id);
  • $user = $dao->getRelation($user);
  • // 或者使用下面的方法
  • $user = $dao->getById($id,'','*','',true);



同样,增加了xFindAll方法进行关联查询(返回Volist对象),而findAll方法默认不进行关联查询。
例如:
  • $list = $dao->findAll("type=1"); //查询type为1的用户
  • $list = $dao->xFindAll("type=1"); // 查询并返回关联记录


关联查询需要Vo类定义_link 属性配合,例如UserVo中定义如下关联信息:
  • var $_link = array(
  •         // 每个用户都有一个个人档案
  •         array(   'mapping_type'=>HAS_ONE,
  •                     'class_name'=>'Profile',
  •                     'foreign_key'=>'userId',
  •                     'mapping_name'=>'profile',
  •                    ),
  •       // 每个用户有多个文章
  •        array(    'mapping_type'=>HAS_MANY,
  •                     'class_name'=>'Article',
  •                     'foreign_key'=>'userId',
  •                     'mapping_name'=>'articles',
  •                     'mapping_order'=>'cTime desc'),
  •         // 每个用户都属于一个部门
  •         array(   'mapping_type'=>BELONGS_TO,
  •                     'class_name'=>'Dept',
  •                     'foreign_key'=>'userId',
  •                     'mapping_name'=>'dept'),
  •         // 每个用户可以属于多个组,每个组可以有多个用户
  •         array(    'mapping_type'=>MANY_TO_MANY,
  •                     'class_name'=>'Group',
  •                     'mapping_name'=>'groups',
  •                     'foreign_key'=>'userId',
  •                     'relation_foreign_key'=>'goupId',
  •                     'relation_table'=>'think_gourpUser')
  •         );



而getRelation方法,则用于获取已经查询到的Vo对象的某个关联记录
  • $vo = $dao->getRelation($vo,HAS_MANY,'articles');



关于映射关系的定义,还有一些高级默认规则,除了mapping_type、class_name 和mapping_name 三个属性必须外,其他都是可选的。另外,还可以包括mapping_order、condition、mapping_limit等高级属性。

默认规则
外键的默认规则是当前Vo对象名称+id,例如:
UserVo对应的可能是表think_user (注意:think只是一个表前缀,可以随意配置)
那么think_user表的外键默认为 user_id,如果不是,就必须在定义表间映射关系的时候定义 foreign_key 。
同样的道理,对于多对多的情况,relation_foreign_key 的规则相同。
多对多的中间表默认表规则如下:
如果think_user 和 think_group 存在一个对应的中间表,默认的表名应该是
如果是由group来操作关联表,中间表应该是 think_group_user,如果是从user表来操作,那么应该是think_user_group,也就是说,多对多关联的设置,必须有一个Vo类里面需要显式定义中间表,否则双向操作会出错。
中间表无需另外的id主键(但是这并不影响中间表的操作),通常只是由 user_id 和 group_id 构成。

另外一个潜规则,因为表间映射关系可以定义condition属性,通常都是通过外键来获取关联数据,但是如果你定义了condition属性,那么就会重新使用condition的条件来获取关联表的数据。
在HAS_MANY 和MANY_TO_MANY情况下,可以使用mapping_order 和 mapping_limit 进行记录的排序和获取部分数据。HAS_ONE 和 BELONGS_TO 永远都只会返回最多一条记录。
另外除了MANY_TO_MANY之外,其他映射关系可以使用 mapping_fields 来返回你需要的关联表字段。

关于自引用关联
如果Vo类的_link属性里面对于 class_name 为自身的情况就属于自引用关联。
通常用于从属关系的关联,例如,某个用户是另外一个用户的领导,某个节点下面有多个子节点这样的应用情况。
对于这样的情况,ThinkPHP增加了一个parent_key属性来定义,该属性在自引用方式下面有效。例如NodeVo中有如下定义:
  • //每个节点具有多个子节点
  • var $_link = array(
  •        array(    'mapping_type'=>HAS_MANY,
  •                     'class_name'=>'Node',
  •                     'foreign_key'=>'id',
  •                     'parent_key'=>'pid',
  •                     'mapping_name'=>'sub',
  •                     'mapping_order'=>'seqNo asc'),
  •    );


parent_key 默认名称为parent_id,如果不是则需要指定。

TOP

4.3 关联写入
目前ThinkPHP支持的关联写入功能暂时只包含HAS_ONE 和 HAS_MANY 的关联操作,包括增加、保存和删除。
Dao类增加了三个变量,默认都是false
  • $auto_save_relations // 是否自动保存关联
  • $auto_delete_relations // 是否自动删除关联
  • $auto_add_relations // 是否自动插入关联


关键的方法是新增的opRelation方法
可以对关联记录进行自动操作的方法包括:

  • add 新增操作
  • addAll 增加列表操作
  • save 保存操作
  • del 删除操作


如果对上面的参数设置为true的话,上面的操作方法就会完成相应的自动关联操作。

如果需要在自定义的方法里面实现关联写入,请使用opRelation方法:
  • opRelation($opType,$data,$type='',$name='')
  • $opType 包括ADD SAVE DEL 三个操作类型
  • $data 表示当前的数据
  • $type 表示关联类型 HAS_ONE HAS_MANY
  • $name 表示关联映射名称

TOP

4.4 数据缓存
ThinkPHP支持多种方式的数据缓存功能,即使在没有开启数据缓存功能,也可以通过调用缓存方法来实现数据缓存。如果在项目配置文件中启用动态数据缓存,即设置DATA_CACHE_ON为true,以及设置缓存有效时间DATA_CACHE_TIME(单位为秒)。关于动态数据缓存的详细设置,请参考入门指南的数据缓存ThinkPHP对于默认的内置操作会自动采用数据缓存功能。
这里讲述下系统的自动缓存功能和如何自己控制缓存。
例如,第一次调用edit方法的时候,会对获取的Vo对象进行缓存,当再次刷新页面的时候,不会从数据库读取数据了,而是直接从缓存中读取要编辑的Vo对象,如果这个时候其他用户已经对该Vo对象作了修改,那么会自动获取最新的缓存数据。
其实,也就是因为使用系统内置的update方法保存了Vo对象的时候,会自动重新缓存的Vo对象。
在Action类里面内置了常用的数据缓存和获取方法。
通用的数据缓存和读取:
  • // 使用identify标识符缓存data数据
  • // data可以是任何数据类型
  • cacheData(identify,data);
  • // 获取缓存标识为identify的缓存数据
  • getCacheData(identify);
  • // 删除缓存标识为identify的缓存数据
  • delCacheData(identify);


针对Vo对象的缓存
  • // 缓存某个Id的vo对象
  • // 系统自动生成缓存标识符
  • cacheVo(vo,id);
  • // 获取某个id的缓存vo对象
  • getCacheVo(voClass,id)
  • // 删除缓存的vo对象
  • delCacheVo(voClass,id)

TOP

4.5 项目自动创建
ThinkPHP后台管理具备项目自动创建的功能,首先确保后台管理项目运行正常。
自动创建的作用是根据节点管理里面添加的项目名称自动创建项目的目录结构、入口文件、配置文件等,免去了手动创建众多目录和文件的麻烦。
要使用自动创建功能,请确认你的网站根目录具有可写权限。
然后,在后台的节点管理添加项目节点,添加成功后,在列表的操作部分点击创建连接,系统就会自动创建项目目录结构,并把后台管理的配置文件复制到添加的项目中,如果需要修改,请手动进行修改。

注意:为了安全,在后台删除项目并不会删除项目目录结构,如果需要,请手动对目录结构进行删除操作。

TOP

4.6 模块自动生成
ThinkPHP后台管理具备自动生成模块的功能,前提是你已经为模块创建好了相应的符合配置要求的数据表。
这一功能比较适合功能单一的模块操作,Action类、Dao类和Vo类均使用同名数据表。
要自动创建模块,请首先在节点管理里面添加模块节点,然后点击创建连接自动创建模块。

模块自动生成的文件包括,项目的Action类(没有任何操作方法)、Dao类(没有任何方法,直接继承Dao类)和Vo类(已经包含数据表对应字段的属性定义),以及模版的模块目录。
请放心,如果已经存在创建好的项目类库文件,系统不会再次重新生成。

TOP

4.7 自定义标签库
系统已经支持的标签库包括CX标签库和HTML标签库,你还可以根据自己需要扩展或者增加标签库。
标签库由定义文件和解析类构成。每个标签库存在一个XML定义文件,用来定义标签库中的标签和属性。并且一个标签库文件对应一个标签库解析类,每个标签就是解析类中的一个方法。
例如,CX标签库的定义文件是cx.xml 位于ThinkTemplate/Template/Tags/目录下面,而cx标签库解析类文件是位于ThinkTemplate/Template/TagLib/目录下面的TagLib_Cx.class.php文件,每个标签的解析方法就是TagLib_Cx类的一个方法,为了不和系统的关键字冲突,所以在方法名前加上了_前缀,因此,假如要定义Cx:Vo 的标签解析,就需要定义一个 _vo方法。
标签库解析类的作用其实就是把某个标签定义解析成为有效的模版文件(可以包括PHP语句或者HTML标签)。

TOP

4.8 表单验证类
ThinkPHP内置了表单验证类来提供对表单提交的数据进行验证,这里指的是后台验证,而不是客户端的验证,客户端验证请参考Js类库的CheckForm类。
表单验证类位于ORG.Text.Validation,通过正则的方式对数据进行验证,并定义了一些常用的验证规则。包括:
  • require 字段必须
  • email 邮箱
  • phone 电话号码
  • mobile 手机号码
  • url URL地址
  • currency 货币
  • number 数字
  • zip 邮政编码
  • qq QQ号码
  • integer 整数
  • double 浮点数
  • english 英文
  • chinese 中文
  • username 用户名
  • password 密码


验证类的使用方法:
  • import("ORG.Text.Validation");
  • $validation = Validation: :getInstance();
  • if(!$validation->check($_POST['username'],'username')) {
  •     $this->error('用户名不符合规范!');
  • }


使用自定义的正则式验证
  • if(!$validation->check($_POST['name'],'/^[a-z]\w{4,}$/i')) {
  •     $this->error( '用户名必须是以字母打头,且5位以上!');
  • }



在ThinkPHP框架中,你还可以单独定义一个_validation方法,用来对表单数据进行验证。
系统在执行操作之前,会检查该模块是否存在_validation方法,如果存在,会自动调用进行验证。
一个典型的_validation方法定义如下,当验证没有通过的时候,系统会返回$this->error信息给客户端。
  • function _validation()
  • {
  • $validation = Validation: :getInstance();
  • //对所有需要验证的数据进行验证
  • if(isset($_POST['name'])) {
  •     if(!$validation->check($_POST['name'],'require')) {
  •   $this->error    =   '用户名必须';
  •   return false;
  •     }
  • }
  • if(isset($_POST['password']) ) {
  •     if(!$validation->check($_POST['password'],'require')) {
  •   $this->error    =   '密码有误';
  •   return false;
  •     }
  • }
  • return true;
  • }

TOP

4.9 Vo自动验证
ThinkPHP还支持Vo自动验证,可以无需定义_validation方法来进行验证,只需要在Vo类定义的时候使用_validation属性定义需要验证的属性,在表单提交的时候系统会完成自动验证过程。
Vo类的_validation属性定义格式如下:
  • var $_validate = array(
  • array("content","require","内容不能为空"),
  • array("email","email","Email格式错误"),
  • array("userId","/^\d+$/","必须是数字"),
  • );


_validate 属性是一个二维数组,每个元素定义了一个验证因子,由三个元素组成且必须,第一个元素是要验证的属性名,第二个元素是验证规则,支持定义规则和正则,第三个元素是出错提示信息。
系统会在根据表单提交数据创建Vo对象的时候自动对_validate 定义的内容进行验证。例如:
  • $dao = D("Blog");
  • $vo  =  $dao->createVo();
  • if(false === $vo) {
  • $this->error($dao->error);
  • }

TOP

4.10 Vo自动填充
在Vo类定义 $_auto 属性,可以完成Vo自动填充功能,用来处理默认值和其他系统写入字段。定义方法:
  • var $_auto = array (
  •   array('status','1','ADD'),
  •   array('mTime','time','UPDATE'),
  •   array('type','0','ALL'),
  • );



每个自动填充项是一个数组,依次代表 字段名称、填充值和填充类型(ALL 始终 ADD 新增时填充 UPDATE 更新时填充)。填充类型留空默认表示ADD。
在使用Dao的CreateVo方法创建Vo对象的时候,如果存在_auto定义,就会进行自动填充。
填充值如果是函数就填充函数返回值,否则就按照字符串填充。

PS:该自动填充可能会覆盖表单提交项目。其,目的是为了防止表单非法提交字段。

TOP

 413 12
发新话题