【问题标题】:yii2 Filtering grid with dropdown list from same modelyii2过滤网格与来自同一模型的下拉列表
【发布时间】:2023-03-20 06:40:01
【问题描述】:

我在我的联系人模型中使用以下函数

public static function getParents()
{
    return $this->hasMany(Contact::className(), ['parent_id' => 'id']); 
}

我想在我的视图的filter属性中得到这个数组的返回:

        [
        'attribute' => 'parent_id',
        'value' => function ($model) {
            return $model->parent ? $model->parent->name : null;
        },
        'hAlign' => 'left',
        'vAlign' => 'middle',
        //'filter' => ArrayHelper::map(Contact::find()->where(['<>', 'parent_id', 0])->orderBy('name')->asArray()->all(), 'id', 'name'),
        'filter' => ArrayHelper::map(Contact::parents()->asArray()->all(), 'id', 'name'),
        'filterWidgetOptions' => [
            'pluginOptions' => ['allowClear' => true],
        ],
        'filterInputOptions' => ['placeholder' => 'Parent'],
        'format' => 'raw'
    ],

但我收到以下错误:调用未定义的方法 common\models\Contact::parents()

其余的关系工作正常,例如属性 $model->parent

我使用了下面的代码,但它是错误的,因为在同一个表中没有带上 parent_id 的名称,而是带上 parent_id 的记录的名称

'filter' => ArrayHelper::map(Contact::find()->where(['<>', 'parent_id', 0])->orderBy('name')->asArray()->all(), 'id', 'name'),

我设法在表单中使用 2 个查询修复了我的过滤器,但不是很优雅:

$subQuery = Contact::find()->select('parent_id')->where(['<>', 'parent_id', 0]);
$parents = ArrayHelper::map(Contact::find()->where(['in', 'id', $subQuery])->orderBy('name')->asArray()->all(), 'id', 'name')

正确答案后更新

我将逻辑放在模块中以便在其他地方重用它并使用 getParentsArray 而不仅仅是 parentsArray

public static function getParentsArray() {
    $subQuery = Contact::find()->select('parent_id')->where(['<>', 'parent_id', 0]);
    $parents = ArrayHelper::map(Contact::find()->where(['in', 'id', $subQuery])->orderBy('name')->asArray()->all(), 'id', 'name');
    return $parents;
}

在视图或控制器中

$parents = Contact::getParentsArray();

【问题讨论】:

    标签: yii yii2 yii2-advanced-app yii2-model kartik-v


    【解决方案1】:

    我认为你的问题是这样的;您正在使用方法Contact::parents(),但您的模型中不存在此方法。你已经声明了一个方法getParents(),它允许Yii 使用magic getter 方法来访问parents 作为Contact::parents

    Yii 如何使用这两个函数有一个微妙但重要的区别,这将影响你如何使用它们来生成适合在下拉列表中使用的数组: 第一个,Contact::parents() 使用您声明的关系来获取所有父记录。它返回一个 Contact 类的模型数组,正如您在方法中声明的那样。

    第二种方式是直接调用静态方法getParents()。这样做的好处是它返回一个ActiveQuery 的实例,然后允许您使用与ActiveQuery 关联的asArray()all() 方法。

    因此,对于您的用例,我会在模型中添加更多代码来生成您的下拉菜单。这样做的好处是它将模型逻辑(即 this )保留在模型中,并且在其他情况下也可以重用。

    所以,在你的模型中,创建这个方法;

    public static function getParentsArray(){
    return ArrayHelper::map(self::getParents()->asArray()->all(), 'id', 'name');
    }
    

    然后您可以像这样在视图文件中使用它;

    'filter' => Contact::parentsArray()
    

    【讨论】:

    • 感谢您的回复 Joe,我仍然遇到同样的错误:未定义的类常量 'parentsArray' 我试图将 parentsArray 作为公共变量和安全属性,以使视图获得功能,但我没有运气。它与过滤器无关,因为我不能在 $parents = common\models\Contact::parentsArray; 中使用它结果相同
    • 我的错误,我发现 getter 和 setter 不适用于静态函数。所以你可以让你的函数成为简单的公共函数,非静态的,或者直接调用函数Contact::getParentsArray()
    【解决方案2】:

    Contact::parents() 表达式正在调用您的代码中不存在的静态方法 parents()。在这种情况下, parents() 不是关系。没有使用此表达式初始化 QueryInterface。

    对于您的任务,使用$dataProvider 作为基础来关联父母。

    'filter' => ArrayHelper::map($dataProvider->getModels()[0]->parents->find()->all(),'id','name'),
    

    您可能在这里验证了$dataProvider 的大小以进入第一级。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-14
      • 2014-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多