U
U
ukoHka2017-03-01 18:44:12
Yii
ukoHka, 2017-03-01 18:44:12

How to properly use relationships in Yii2?

When generating the Payments model via Gii, the related tables were displayed only in the rules.
Function

public function getStates()
    {
        return $this->hasOne(PaymentStates::className(), ['id' => 'state']);
    }
added manually. Based on this model, I generated PaymentsSearch, where in the search function I added
$query->joinWith([
         'states' => function ($q2) {
           $q2->select(['name']);
         }
. Next, search is called in the controller and rendered
return $this->render('list', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);

List.php uses GridView, where I added a column to columns
[
          'attribute' => 'states.name',
          'format' => 'raw',
          'label' => 'Статус платежа',
          'value' => function (Payments $p) {
            switch ($p->state) {
              case 1 : $class = 'fa fa-question'; break;
              case 2 : $class = 'fa fa-times'; break;
              case 3 : $class = 'fa fa-check'; break;
            }
            return Html::tag('div',Html::tag('span','', ['class'=>$class])
                      . ' ' . $p->states->name);
          }
        ]

And here in the line $p->states->name the error Trying to get property of non-object is generated. What is the correct way to write the code so that $p->states returns a PaymentStates object?
The strangest thing is that this code worked, but I changed something (it seems that I just added fields to the table and regenerated Payments and PaymentsSearch). And now I can't figure out why it stopped working and how to use relationships in Yii2 at all.
There is also a connection with the User class, which in the same provider displays the necessary data correctly and the code there is almost the same

Answer the question

In order to leave comments, you need to log in

2 answer(s)
M
Maxim Timofeev, 2017-03-01
@webinar

The getStates link returns null, the link does not mean that you have a state for each Payment. Check this point and make a check, either in code:

$state = ($p->states)?$p->states->name:'не определено';
return Html::tag('div',Html::tag('span','', ['class'=>$class]). ' ' . $state);

or in the model like so:
public function getStateName()
    {
        $name = 'хз';
        if($this->states)
            $name = $this->states->name;
        return $name;
    }

well, it's natural to use $model->stateName instead of $model->states->name

U
ukoHka, 2017-03-01
@ukoHka

Instead of

$query->joinWith([
         'states' => function ($q2) {
           $q2->select(['name']);
         }
used
$query->with([
         'states'
       ]);

And everything began to display correctly. I don't know what the difference is between the two, but it definitely worked through joinWith before.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question