0

I am using the following functions in my Contact model

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

I want to get the return of this array in the filter attribute of my view:

        [
        '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'
    ],

but I get the following error: Call to undefined method common\models\Contact::parents()

the rest of the relations work fine for example the attribute $model->parent

I was using the following code but it is wrong because dosn't brings the name of the parent_id within the same table but the name of the records with parent_id

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

I managed to fix my filter using 2 queries in the form but is not very elegant:

$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')

UPDATED AFTER CORRECT ANSWER

I put the logic in the module to reuse it in other places and used getParentsArray instead of just 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;
}

in views or controllers

$parents = Contact::getParentsArray();

2 Answers 2

1

I think that your problem is this; You are using the method Contact::parents() but this method doesn't exist in your model. You have declared a method getParents(), which allows Yii to use the magic getter method to access the parents as Contact::parents.

There is a subtle but important difference in how Yii uses these two functions which will affect how you use them to generate an array suitable for use in your dropdown list: The first, Contact::parents() uses the relationship you've declared to get all the parent records. It returns an array of models of class Contact, as you've declared in your method.

The second way is to directly call the static method getParents(). This has the advantage that it returns an instance of ActiveQuery, which then allows you to use the asArray() and all() methods associated with ActiveQuery.

So, for your use case, I would put some more code in the model to generate your dropdown. The advantage of this is that it keeps model logic (which this is) inside the model, and it also then becomes reusable in other situations.

So, in your model, create this method;

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

You can then use this in your view file like so;

'filter' => Contact::parentsArray()
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your reply Joe, I still having the same error: Undefined class constant 'parentsArray' I tried to put parentsArray as a public variable, and safe attribute in a desperate intent to make the view get the function but i had no luck. It is not related to the filter because I can't use it in $parents = common\models\Contact::parentsArray; with the same result
My mistake, I've found out that the getters and setters do not work with static functions. So you can either make your functions simple public functions, non-static, or call the function directly as Contact::getParentsArray()
0

Contact::parents() expression is calling a static method parents() which is not existed in your code. It this context parents() is not a relation. There is no QueryInterface initialized by using this expression.

For your task, use $dataProvider as base to relate the parents.

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

May be here you have validate size of the $dataProvider to go into first level.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.