使用定义的关系(更简单,效率更低)。
这种方法的典型方式,它适用于相关的Category
模型。因此它需要大量的内存。
class Content extends \yii\db\ActiveRecord
{
/**
* Returns comma separated list of category titles using specified separator.
*
* @param string $separator
*
* @return string
*/
public function getCategoriesCsv($separator = ', ')
{
$titles = \yii\helpers\ArrayHelper::getColumn($this->categories, 'title');
return implode($separator, $titles);
}
// ...
}
应与预先加载使用:
Content::find()
->with('categories')
->all();
使用子查询(更有效,不太方便)
这种方法使用子查询和不使用关系和相关模型。因此这种方式更快,并保留大量的内存。
class Content extends \yii\db\ActiveRecord
{
const ATTR_CATEGORIES_CSV = 'categoriesCsv';
/**
* @var string Comma separated list of category titles.
*/
public $categoriesCsv;
/**
* Returns DB expression for retrieving related category titles.
*
* @return \yii\db\Expression
*/
public function prepareRelatedCategoriesExpression()
{
// Build subquery that selects all category records related with current content row.
$queryRelatedCategories = Category::find()
->leftJoin('{{%content_category}}', '{{%content_category}}.[[category_id]] = {{%category}}.[[id]]')
->andWhere(new \yii\db\Expression('{{%content_category}}.[[content_id]] = {{%content}}.[[id]]'));
// Prepare subquery for retrieving only comma-separated titles
$queryRelatedCategories
->select(new \yii\db\Expression('GROUP_CONCAT({{%category}}.[[title]])'));
// Prepare expression with scalar value from subquery
$sqlRelatedCategories = $queryRelatedCategories->createCommand()->getRawSql();
return new \yii\db\Expression('(' . $sqlRelatedCategories . ')');
}
// ...
}
当附加列的别名等于某些型号的性能,它将被all()
方法来填充:
$contentModels = Content::find()
->andSelect([
'*',
Content::ATTR_CATEGORIES_CSV => Content::prepareRelatedCategoriesExpression(),
])
->all();
foreach ($contentModels as $contentModel) {
$contentModel->id;
$contentModel->categoriesCsv; // it will be also populated by ->all() method.
// ...
}
PS:我没有测试此代码,大概应该是固定的查询检索类别。
此外,在本例中使用的书面基地简单的语法,但它可能会使用不同的助手,结款等
使用匿名函数获取gridview的所需值进行优化,以更可爱的状态。 –
@InsaneSkull,但它会为每一行运行一个单独的查询。 – Arth
不是真的,如果你使用'joinWith()'或'with()'。只是使用循环。如果使用gridview和dataProvider输出更新问题。我可以搭把手。 –