您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
5-8 数据模型之关联查询性能问题(hasMany)
发布时间:2023-04-28 20:18:22编辑:雪饮阅读()
-
首先说的是老师讲的查询缓存,就是通过模型实例多次调用其hasMany(可能老师说的还包含hasOne)的模型属性时候仅仅只查询第一次执行时候的sql。
这里我这里是没有发现。
关联模型hasMany在查询一个数据列表中,然后该列表中每个数据项又附加一个数据列表的情况下非常有用,使用时候需要模型实例以with方法传入模型的“属性名”,该属性名是get前缀方法名,方法名遵循首字母大写(驼峰命名,因为get已经是g首字母小写了),且该方法实现中最后return的仅仅是hasMany方法的直接返回(后面不能有其它连贯操作)。
但with接收的属性名则继续使用小写即可。
综上所述,我们这里以用户为主,查询多个用户每个用户的文章列表为例,那么上篇中的WpPosts模型可以不用动,主要是在WpUsers模型中除了原来的getPosts方法实现Posts属性外,这里还需要一个纯关联关系hasMany的关系建立。则WpUsers如:
<?php
namespace app\models;
use yii\db\ActiveRecord;
class WpUsers extends ActiveRecord{
public function getPosts(){
return $this->hasMany(WpPosts::className(),['post_author'=>'ID'])->asArray()->all();
}
//纯关联模型
public function getPosts2(){
return $this->hasMany(WpPosts::className(),['post_author'=>'ID']);
}
}
然后实例如:
<?php
namespace app\controllers;
use app\models\WpPosts;
use app\models\WpUsers;
use yii\web\Controller;
class HelloController extends Controller{
public $layout='common';
public function actionIndex(){
/*
关联查询问题一
查询当前模型关联的那个模型时候,当前实例多次调用关联模型“属性”时候仅执行一次查询sql
这样导致的结果是数据库数据有改变了,然后第二次查询的还是之前第一次查询的结果
实际情况:我这里测试发现并没有这样的问题
$user->Posts调用了两次出现了两次如
SELECT * FROM `wp_posts` WHERE `post_author`='1'
这样的sql
据说如果出现了这种问题可以使用unset($user->Posts)这种方式解决
就是每次使用完$user->Posts就unset下
* */
$user=WpUsers::find()->where(["ID"=>1])->one();
print_r($user->Posts);
print_r($user->Posts);
}
public function actionIndex2(){
/*
关联查询问题二
就是说如果是有多个用户,要分别查看每个用户的文章列表
那么常规做法如
$users=WpUsers::find()->all();
foreach($users as $user){
print_r($user->Posts);
}
假如说这里有100个用户,那么首先查询到这100个用户的这条sql是一次查询
然后又有100个用户对应的文章列表的查询,又是100条查询
总共就是101条查询了。。。。。
当然有人会说可以第一次查询结果里面把关联id全部取出来形成一个数组用in查询,
然后查询回来再通过循环组合到用户列表每个用户的属性中
可以当然是可以的,只是这样做一般的:
首先把关联id形成一个数组这些代码繁琐,然后就算用in查询回来后重新组合又是需要循环
性能上和便利性我觉得都是不太好的。
那么实际上因为user模型上有posts属性使用的hasMany实现的,则可以直接使用with方法,
直接就实现了上面这个节省100条sql为1条sql的逻辑
当然这里在模型hasMany里面就仅仅返回hasMany方法即可,
我之前后面还有连贯方法->asArray()->all()的执行导致报错了
* */
$users=WpUsers::find()->with("posts2")->all();
print_r($users);
}
} 关键字词:hasMany