ThinkPHP在设计上,和CakePHP有很多相似的地方,模型关联就是几乎和CakePHP如出一辙, 刚开始还觉得很方便, 在进行表之间关联查询的时候,不用自己去写SQL语句,在使用中却发现了问题,日志记录中发现异常。
要求:在查询用户的时候,把用户所在的部门查询出来
添加模型文件:
/mytest/Application/Home/Model/UsersModel.class.php
/mytest/Application/Home/Model/DeptModel.class.php
<?php
namespace Home\Model;
use Think\Model;
use Think\Model\RelationModel;
class UsersModel extends RelationModel {
protected $_link = array(
'Dept' => array(
'mapping_type' => self::BELONGS_TO,
'class_name' => 'Dept',
'foreign_key' => 'dept_id',
)
);
}
<?php
namespace Home\Model;
use Think\Model;
use Think\Model\RelationModel;
class DeptModel extends RelationModel {
protected $_link = array(
'Users' => array(
'mapping_type' => self::HAS_MANY,
'class_name' => 'Users',
'foreign_key' => 'dept_id',
)
);
}
查询所有用户:
$User = D('Users');
$res = $User->relation(true)->select();
输出结果:
0 =>
array (size=8)
'id' => string '1' (length=1)
'name' => string 'ThinkPHP2' (length=9)
'email' => string 'JKSM,JKSM,ThinkPHP2@gmail.comJKSM,JKSM,' (length=39)
'gender' => string '3' (length=1)
'balance' => null
'his_use_balance' => null
'dept_id' => string '1' (length=1)
'Dept' =>
array (size=3)
'id' => string '1' (length=1)
'd_name' => string '研发部' (length=9)
'num' => string '102' (length=3)
1 =>
array (size=8)
'id' => string '2' (length=1)
'name' => string 'ThinkPHP1' (length=9)
'email' => string 'ThinkPHP1@gmail.com' (length=19)
'gender' => string '0' (length=1)
'balance' => null
'his_use_balance' => null
'dept_id' => string '1' (length=1)
'Dept' =>
array (size=3)
'id' => string '1' (length=1)
'd_name' => string '研发部' (length=9)
'num' => string '102' (length=3)
....
但是检查日志,发现不对劲了,这么多条SQL语句
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='1' ) LIMIT 1 [ RunTime:0.0003s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='1' ) LIMIT 1 [ RunTime:0.0003s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='1' ) LIMIT 1 [ RunTime:0.0003s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='1' ) LIMIT 1 [ RunTime:0.0002s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='2' ) LIMIT 1 [ RunTime:0.0002s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='1' ) LIMIT 1 [ RunTime:0.0003s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='2' ) LIMIT 1 [ RunTime:0.0003s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='2' ) LIMIT 1 [ RunTime:0.0003s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='2' ) LIMIT 1 [ RunTime:0.0002s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='2' ) LIMIT 1 [ RunTime:0.0002s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='3' ) LIMIT 1 [ RunTime:0.0002s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='1' ) LIMIT 1 [ RunTime:0.0002s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='3' ) LIMIT 1 [ RunTime:0.0002s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='1' ) LIMIT 1 [ RunTime:0.0002s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='3' ) LIMIT 1 [ RunTime:0.0002s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='2' ) LIMIT 1 [ RunTime:0.0002s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='2' ) LIMIT 1 [ RunTime:0.0003s ]
SQL: SELECT * FROM `dept` WHERE ( 1=1 AND id='2' ) LIMIT 1 [ RunTime:0.0003s ]
查看源码:
/mytest/ThinkPHP/Library/Think/Model.class.php
$this->_after_select($resultSet,$options);
把主表数据查询到之后,执行回调方法,循环查询查询关联表,
/mytest/ThinkPHP/Library/Think/Model/RelationModel.class.php
// 查询数据集成功后的回调方法
protected function _after_select(&$result,$options) {
// 获取关联数据 并附加到结果中
if(!empty($options['link']))
$this->getRelations($result,$options['link']);
}
/**
* 获取返回数据集的关联记录
* @access protected
* @param array $resultSet 返回数据
* @param string|array $name 关联名称
* @return array
*/
protected function getRelations(&$resultSet,$name='') {
// 获取记录集的主键列表
foreach($resultSet as $key=>$val) {
$val = $this->getRelation($val,$name);
$resultSet[$key] = $val;
}
return $resultSet;
}
如果主表查询记录有30条,就需要循环30次,想不通怎么会用这种方式处理关联查询?