您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
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