多表关联一对一查询之hasOne
public function actionAbout()
{
$article = Article::findOne(1);
$category = $article->hasOne('app\models\Category', ['id'=>'cate_id'])->one();
var_dump($category);
}
上面的例子可以更加简便为:
public function actionAbout()
{
$article = Article::findOne(1);
$category = $article->hasOne(Category::className(), ['id'=>'cate_id'])->one();
var_dump($category);
}
上面的例子hasOne()是直接写在控制器中的,如果需要多次用到此方法,会产生耦合,规范的写法是将此方法方法模型中:
模型中:
class Article extends ActiveRecord {
public function getCategory()
{
$category = $this->hasOne(category::className(), ['id'=>'cate_id'])->one();
return $category;
}
}
控制器中:
public function actionAbout()
{
$article = Article::findOne(1);
$category = $article->getCategory();
var_dump($category);
}
hasOne()第二种写法:
模型中:
class Article extends ActiveRecord {
public function getCategory()
{
$category = $this->hasOne(category::className(), ['id'=>'cate_id'])->asArray();
return $category;
}
}
控制器中:
public function actionAbout()
{
$article = Article::findOne(1);
$category = $article->category;
var_dump($category);
}
PS:通过调用category属性,会自动走__get()魔术函数,__get()会自动补上get,变成getCategory(),并且会自动判断到hasOne()在结尾加上one(),所以模型里不需要加one()也行,最后返回结果。
上面的例子都是获取的一篇文章对应的分类,项目中我们常常都是获取每一篇文章对应的分类:
模型中:
class Article extends ActiveRecord {
public function getCategory()
{
$category = $this->hasOne(category::className(), ['id'=>'cate_id'])->asArray();
return $category;
}
}
控制器中:
public function actionAbout()
{
$articles = Article::find()->all();
foreach ($articles as $article) {
$category[] = $article->category;
}
var_dump($category);
}
PS:这种方法执行sql次数为下面次数之和:
$articles = Article::find()->all(); //执行1次
foreach ($articles as $article) {
$category[] = $article->category; //有多少篇文章执行多少次sql
}
上例性能优化:
模型中:
class Article extends ActiveRecord {
public function getCategory()
{
$category = $this->hasOne(category::className(), ['id'=>'cate_id']);
return $category;
}
}
控制器中:
public function actionAbout()
{
$articles = Article::find()->with('category')->asArray()->all();
var_dump($articles);
}
PS:这种方法只执行一次sql语句,效率会大大提高。实际是使用了join查询。