Зависимые таблицы Yii2, как обходится без дополнительной модели?

В общем имеется 2 таблицы
book и genre

и между ними связь много ко многим, соот-о добавляю pivot table genre-book

и чтоб делать стандартные вызовы приходится вызывать вечно $model->genres, - это если из модели book вызываю, но что если мне приходится искать книги из жанров, соответство для вывода я в виджет буду передавать function some( Book $item ) и получается что туда приходит модель зависимой таблицы GenreBook
и приходится писать $model->book->title
как можно обходить вызов book при этом иметь нужные данные?
пример отрывка из моего кода RecomendedBook:
public function renderItem($item)
    {
        $title = $item->book->title();
        $cardContent = '';
        $imgSrc = '/img/book-thumb/'.rand(1,100).'.jpg';
        $author = $item->book->author()[0]['first-name'].' '.$item->book->author()[0]['last-name'];
        $cardContent .= Html::img($imgSrc,['class' => 'card-img-top']);
        $cardContent .= Html::tag('h4',$title,['class' => 'card-title']);
        $cardContent .= Html::tag('small',$author,['class' => 'text-muted']);

        $cardDiv = Html::tag('div',$cardContent,['class' => 'card-block']);

        return Html::a($cardDiv,['book/'.$item->book->url],$this->cardOptions);
    }


Составление dataProvider:

$model = Book::find()->where( [ 'url' => $url ] )->limit( 1 )->one();
        foreach ( $model->genres() as $genre ) {
            $search = new GenreBookSearch();
            $dataProvider[$genre['@attributes']['title']] = $search->search(Yii::$app->request->queryParams);
            $dataProvider[$genre['@attributes']['title']]->query->andWhere(['genre_id' => $genre['@attributes']['id']]);
        }


собственно вопрос, если я буду использовать эту гадость вроде $model->book->title()
то при попытке передать автора книги, мне придется составлять точные копии зависимостей, правильно ли это и как можно это все осознать.

Заранее благодарю!
  • Вопрос задан
  • 333 просмотра
Решения вопроса 1
@dtBlack
Ваш вопрос очень сложен для понимания.
Как я понял вам хочется писать короче и понятней?
Тем более для избежания ошибок вероятно придется писать не $item->book->title, а что то похожее на !empty($item->book)?$item->book->tytle:''

Я так понимаю проблема у тебя в построении модели и возможно не знание что такое hasMany и hasOne (ссылку на документацию и примеры использования обсуждали на этом же сайте), а так же возможно вам не известно такое явление как магические методы, и конкретно __get ().

Так что у тебя должно быть что то примерное:
class Genre extends ActiveRecord
{
    public function getBooks()
    {
        return $this->hasMany(Book::className(), ['id' => 'book_id'])
            ->viaTable('genre_book', ['genre_id' => 'id']);
    }
}

И тогда у тебя в атрибуте $genre->books будет список книг по этому жанру.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@vyrkmod
Пишу на php. И не стыдно.
Вам сюда, конкретно viaTable(). В итоге должно получиться как для книг $book->genres, так и для жанров $genre->books. А создавать для связующей таблицы не несущей в себе дополнительной информации отдельную модель - как правило не конструктивно.
Ответ написан
Комментировать
@Antarit
Не совсем понятно, в чем вопрос... Если хочешь внутри функции renderItem обойтись без вызова $item->book так сделай следующим образом
public function renderItem($book)
    {
//какой-то код...
        $title = $book->title();
        $author = $book->author()[0]['first-name'].' '.$book->author()[0]['last-name'];
//какой-то код...
}

и вызывай себе спокойно renderItem($item->book)
А то прям как-то очень усложняешь себе жизнь...
А вообще тебе стоит разобраться с релейшнс hasOne() и hasMany() а не писать страшные датапровайдеры... И все подобные вопросы отпадут само собой...
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы