ThinkPHP视图查询详解


  本文标签:ThinkPHP,视图查询

ThinkPHP提供的视图查询应用功能十分强大,用户利用视图查询功能可以将多个数据表的字段内容按需要进行指定和筛选,组织成一个基于这些数据表的视图模型,然后就可以通过该模型直接进行多表联合查询,非常方便和简单 。

例如在项目中,我们定义有三个表:

user          用户基础表,
user_info   用户详细信息表,
dept          部门分类表

现在我们需要获取某个用户信息,
该信息要包括用户的帐号名称和相关资料与及所在部门的名称,
这时候我们可以利用视图查询进行处理 。

下面举例加以说明:

1.构建一个新项目并进行相关配置(可参考前面的教程,这里省略)
2.创建一个数据库tpview,并添加这三个表
(1) 用户表

CREATE TABLE `think_user` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT ID编号,
 `name` varchar(20) NOT NULL COMMENT 帐户,
 `password` varchar(32) NOT NULL COMMENT 密码,
 `dept_id` smallint(6) unsigned NOT NULL,
 `status` tinyint(1) unsigned NOT NULL DEFAULT 1 COMMENT 开放状态,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT=会员表 AUTO_INCREMENT=2 ;
INSERT INTO `think_user` (`id`, `name`, `password`, `dept_id`, `status`) VALUES
(1, zzguo28, 123456, 2, 1);

(2)用户信息表

CREATE TABLE `think_user_info` (
 `user_id` int(11) NOT NULL COMMENT 用户id,
 `nick_name` varchar(30) NOT NULL COMMENT 用户昵称,
 `email` varchar(100) NOT NULL COMMENT 邮箱地址,
 `address` varchar(100) NOT NULL COMMENT 详细地址,
 `gender` tinyint(1) NOT NULL DEFAULT 0 COMMENT 性别,
 `mobile` varchar(100) NOT NULL COMMENT 手机号码,
 `telephone` varchar(100) NOT NULL COMMENT 电话号码,
 KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT=用户信息表;
INSERT INTO `think_user_info` (`user_id`, `nick_name`, `email`, `address`, `gender`, `mobile`, `telephone`) VALUES
(1, 国, zzguo28@163.com, TP路think街1.6号, 1, 12345678901, 123456);

(3) 部门分类表

CREATE TABLE `think_dept` (
 `id` smallint(3) NOT NULL AUTO_INCREMENT,
 `name` varchar(50) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
INSERT INTO `think_dept` (`id`, `name`) VALUES
(1, 开发部),
(2, 销售部),
(3, 财务部);

3.在项目/Lib/Model下创建这三个表的基础模型Model
  本示例没涉及到验证等其它功能,所以只要简单定义测可,例如

 <?php
  class UserModel extends Model {
  }
 ?>

其实视图模型对应的数据表并非一定要有相应的的基础模型,但是建议您创建,这样单表和视图都可以操作 。

4.创建视图模型,代码如下,详细注解见其后:

(附注:最新svn上已增加动态扩展模型功能,使用新版需要将protected属性改为public属性,建议使用动态扩展功能去使用视图查询,而不再是本教程的继承方式 。那样使用会更灵活 。)

<?php
import(ViewModel);
class UserViewModel extends ViewModel{
  protected $viewFields = array(
    User   =>array(id,name,_as=>u,_type=>left),
    UserInfo =>array(email,mobile,_as=>ui,_on=>ui.user_id=u.id),
    Dept   =>array(name=>dept,_on=>u.dept_id=Dept.id),
  );
}
?>

对上述代码解释如下:

在第2行代码中,由于自TP1.6版开始已将视图查询分离出原Model类,因此这里需要使用import方法引入了视图模型类 。

第3行代码中,定义了该模型名称为UserViewModel,视图模型的名称Model前的命名是随意的,只是为了有别于其它模型,通常我们会以xxxViewModel这样的方式去命名 。并且一定要继承ViewModel 。(ThinkPHP1.6版无需再设置模型的viewModel属性为true,只要继承ViewModel则可)

第4行代码$viewFields 属性表示视图模型包含的字段,每个元素定义了各个数据表或者模型所需的字段 。
格式是

protected $viewFields = array(
    表名=>array(所需字段,_as=>别名定义,_on=>筛选条件,_type=>指定join类型,支持right,inner,left三种),
);

注意到第7行代码中的name=>dept,因为User模型里面已经存在了一个name字段,所以我们通过这种方式把Dept模型的name字段映射为dept字段,如果有多个字段,可以使用同样的方式添加 。

定义完毕后,我们在Action中进行测试,代码如下

<?php
class IndexAction extends Action{
  public function index(){
    $dao = D(UserView);
    $where[u.id] = 1;
    dump($dao->where($where)->find());
    dump($dao->getLastSql());
  }
}
?>

然后访问该操作,可以看到我们成功取得所需的查询内容:

array(1) {
 [0] => array(5) {
  ["id"] => string(1) "1"
  ["name"] => string(7) "zzguo28"
  ["email"] => string(17) "zzguo28@163.com"
  ["mobile"] => string(11) "12345678901"
  ["dept"] => string(9) "销售部"
 }
}

并可以看到使用的sql如下

"SELECT u.id AS id,u.name AS name,ui.email AS email,ui.mobile AS mobile,Dept.name AS dept FROM think_user u LEFT JOIN think_user_info ui ON ui.user_id=u.id JOIN think_dept Dept ON u.dept_id=Dept.id WHERE ( u.id = 1 ) LIMIT 1 "

视图模型在查询上和普通单表并没有多大分别,可以使用我们所熟悉的各种连贯操作,例如order,limit等等 。