Yii2:GridView,用于一对多关系数据


Yii2: GridView for one-to-many relational data

我有一个对象Object1,它以一对多关系引用Object2:一个Object1对多个Object2

在我的Object1视图中,我试图仅包括相关Object2项的yii'grid'GridView。除了Object1数据之外。只是Object2项目中的一个GridView

使用下面这样的代码,我相信我必须在控制器中设置$dataProvider$searchModel,但我不确定如何将Yii::$app->request->queryParams$id链接起来。

我的代码只返回所有Object2项,而不管它们与Object1的关系如何,这对我来说虽然很有意义,但不是我想要的。

我甚至不确定这是否是正确的做法。有人知道解决方案吗?提前谢谢。

/* Object1 model */
public function getRelations() {
    return $this->hasMany(Object2::className(), ['relation' => 'id']);
}
/* Object1 view */
<?= GridView::widget([
    'dataProvider' => $dataProvider,
    'filterModel' => $searchModel,
    'columns' => [
        ['class' => 'yii'grid'SerialColumn'],
        'id',
        'attr1',
        'attr2',
        'attr3',
        'attr4',
        ['class' => 'yii'grid'ActionColumn'],
    ],
]);
/* Object1 controller */
public function actionView($id){
    $searchModel = new Object2Search();
    $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
    return $this->render('view', [
        'model' => $this->findModel($id),
        'searchModel' => $searchModel,
        'dataProvider' => $dataProvider,
    ]);
}

我可以建议另一种方法,而不是在细节视图中呈现GridView。

Object1Object2项创建单独的常规GridView小部件。

扩展Object1 GridView的ActionColumn,并添加到相关项的链接。我已经在这里解释过了,但为了更好地理解,我也在这里包含了代码:

[
    'class' => 'yii'grid'ActionColumn',
    'template' => '{objects2} {view} {update} {delete}',
    'buttons' => [
        'objects2' => function ($url, $model, $key) {
            /* @var $model common'models'Object1 */
            return Html::a(
                '<span class="glyphicon glyphicon-arrow-down"></span>',
                ['objects2/index', 'object1_id' => $model->id],
                [
                    'title' => 'Objects 2',
                    'aria-label' => 'Objects 2',
                    'data-pjax' => '0',
                ]
            );
        },        
    ],
],

修改Object2Controllerindex动作以接受附加参数(对象1 id):

/**
 * @param integer $object1_id
 * @return string
 * @throws 'yii'web'NotFoundHttpException
 */
public function actionIndex($object1_id)
{
    $searchModel = new Object2Search;
    $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
    return $this->render('index', [
        'searchModel' => $searchModel,
        'dataProvider' => $dataProvider,
    ]);
}

Object2Searchsearch()方法还应处理附加参数:

/**
 * @param array $params
 * @return ActiveDataProvider
 */
public function search($params)
{
    $query = Object2::find()->where(['object1_id' => $params['object1_id']]);
    $dataProvider = new ActiveDataProvider([
        'query' => $query,            
    ]);
    if (!($this->load($params) && $this->validate())) {
        return $dataProvider;
    }
    // Additional filters
    return $dataProvider;
}

确保rules()和其他过滤器中未包含object1_id

至于Object2项的显示,只需排除object1_id列即可。

显然,这可以进行更多的定制,这只是一个基本的例子。

这种方法的主要优点是不同类型的模型的代码是分离的,更容易维护。

关于在细节视图中使用它,如上所述,修改Object2Search模型的search()方法,通过object1_id应用初始滤波器,但在这种情况下,从查询参数中传递id参数(来自view动作):

$query = Object2::find()->where(['object1_id' => $params['id']]);

使用GridView的部分以获得更好的视图组织。