使用定義的關係(更簡單,效率更低)。
這種方法的典型方式,它適用於相關的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輸出更新問題。我可以搭把手。 –