Yii2: has_many gridview and detailview

2019-08-09 08:34发布

I'm going to use 1st normalization form in my Yii2 project, so I've added table like this
| id | post_id | tag_id |
and when I'm to posts model I've writed this:

public function getTags()
{
    return $this->hasMany(PostTags::className(), ['post_id' => 'id']);
}

In view widget I've added 'tags.tag_id', but it shows no data.
Is there any way to show this tags in DetailView and GridView widgets?

May be, I can write "group_concat" somewhere?

标签: php yii2
1条回答
劫难
2楼-- · 2019-08-09 08:58

I'd recommend to write a widget for displaying a links list of related records. It's reusable, prevents HTML generation in model / controller, reduces the amount of code in view.

<?php

namespace common\widgets;

use yii\base\Widget;
use yii\helpers\Html;

/**
 * Widget for display list of links to related models
 */
class RelatedList extends Widget
{
    /**
     * @var \yii\db\ActiveRecord[] Related models
     */
    public $models = [];

    /**
     * @var string Base to build text content of the link.
     * You should specify attribute name. In case of dynamic generation ('getFullName()') you should specify just 'fullName'.
     */
    public $linkContentBase = 'name';

    /**
     * @var string Route to build url to related model
     */
    public $viewRoute;

    /**
     * @inheritdoc
     */
    public function run()
    {
        if (!$this->models) {
            return null;
        }

        $items = [];
        foreach ($this->models as $model) {
            $items[] = Html::a($model->{$this->linkContentBase}, [$this->viewRoute, 'id' => $model->id]);
        }

        return Html::ul($items, [
            'class' => 'list-unstyled',
            'encode' => false,
        ]);
    }
}

Here are some examples (assuming tag name is stored in name column).

Usage in GridView:

[
    'attribute' => 'tags',
    'format' => 'raw',
    'value' => function ($model) {
        /* @var $model common\models\Post */
        return RelatedList::widget([
            'models' => $model->tags,
            'viewRoute' => '/tags/view',
        ]);
    },
],

Usage in DetailView:

/* @var $model common\models\Post */

...

[
    'attribute' => 'tags',
    'format' => 'raw',
    'value' => RelatedList::widget([
        'models' => $model->tags,
        'viewRoute' => '/tags/view',
    ]),        
],

Don't forget to set format raw, because by default content is rendered as plain text to prevent XSS attacks (html special characters are escaped).

You can modify this to fit your needs, this is just an example.

查看更多
登录 后发表回答