dklight
@dklight
php кодер - level 2.5

Ошибка Trying to get property 'name' of non-object ->with() как решить?

есть запрос вида:
$query = Event::find()->where(['i_user' => $_SESSION['user']['id']])
                    ->with('category')
                    ->with('type')
            ->orderBy($rsort2)

в модели:
public function getCategory() {
        return $this->hasOne(Category::className(), ['id' => 'i_cat']);
    }
    public function getType() {
        return $this->hasOne(Type::className(), ['id' => 'type']);
    }

при выводе возникает описанная в теме ошибка:
<?=$ev['category']->name?></td>
    <?=$ev['type']->name?></span>


причем вывод имени категории отрабатывает без ошибок, а вывод имени типа не видит, хотя функции выборки аналогичны. Была идея просто работать с массивами:
$query = Event::find()->where(['i_user' => $_SESSION['user']['id']])
                    ->with('category')
                    ->with('type')
            ->orderBy($rsort2)
            ->asArray()
            ->all();

но в коде присутствует еще пагинация

Есть идеи?
  • Вопрос задан
  • 592 просмотра
Решения вопроса 2
AnnaVel
@AnnaVel
Попробуйте получать данные так:
<td><?= $ev->category->name ?></td>
<span><?= $ev->type->name ?></span>
Ответ написан
@vksee
Преамбула:
Класс Event наследник ActiveRecord.
При обращении к свойству, если в вашем классе в рамках PHP не объявлено доступное свойство type - то вызывается магический метод __get('type') (у родительского класса) для определения существования в рамках Yii атрибута или геттера getType() для получения значения этого атрибута: yii\db\BaseActiveRecord::__get()
- Вначале проверяется наличие атрибута с таким именем, если имеется - возвращается значение атрибута.
- Затем проверяется наличие уже полученных значений по связанным данным. Это, как правило, другой объект наследник ActiveRecord, в вашем случае описано для class Type.
- Если пока ни чего не найдено, проверяется наличие геттера и его вызов, к примеру getType().
- Если геттер вернул не объект запроса данных, то возвращается это значение из геттера.
Методы определения связей (hasOne, hasMany и т.п.) - возвращают объект типа ActiveQueryInterface (как правило это ActiveQuery).
- Если результат геттера возвращает объект типа ActiveQueryInterface, то этот запрос выполняется, и затем возвращается уже результат запроса.
Таким образом мы получаем результат запроса и получаем связанную запись или записи типа ActiveRecord.
Если требуется получить результат запроса связанных данных (объект типа ActiveRecord), то вызывается $ev->type, но если сам запрос для дальнейшей манипуляции - то $ev->getType().

Ответ:
В вашем случае ошибка в том, что до описанной в getType() связи дело не доходит. Потому что есть атрибут type.
Ваш код $ev->type - возвращает "айдишник". А вы к нему обращаетесь затем как к объекту ...->name.

1. Требуется по разному назвать связь и атрибут для хранения связи.
Удобнее сделать так - атрибут назвать type_id (в базе и в правилах):
public function getType() {
    return $this->hasOne(Type::className(), ['id' => 'type_id']);
}

И тогда:
- $ev->type_id - айдишник связанных данных.
- $ev->type - благодаря магии __get() и описанию связи через getType() - вернётся связанный объект типа class Type (наследник ActiveRecord).
- $ev->getType() - запрос ActiveQuery для получения связанных данных.

2. Или переименуйте getType() на что-нибудь типа getEventType(), и тогда сработает $ev->eventType->name.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы