Как получить все фильмы, которые идут в кинотеатре?

У меня есть следующие красноречивые сущности:

  • Фильм
  • ФильмСеанс
  • Кинотеатр
  • КиноТеатрКомната

Структура таблицы:

Schema::create('movies', function (Blueprint $table) {
    $table->increments('id');
});

Schema::create('movie_theaters', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name')->index();
    $table->string('slug')->index()->unique();
    $table->string('description')->index()->nullable();
    $table->longText('content')->nullable();

    $table->unsignedInteger('picture_id')->nullable();
    $table->foreign('picture_id')
         ->references('id')
         ->on('media');

    $table->boolean('activated')->default(true);

    $table->timestamps();
});

Schema::create('movie_theater_rooms', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name')->index();
    $table->string('description')->index()->nullable();
    $table->longText('content')->nullable();

    $table->boolean('activated')->default(true);

    $table->unsignedInteger('movie_theater_id');
    $table->foreign('movie_theater_id')
        ->references('id')
        ->on('movie_theaters')
        ->onDelete('cascade');

    $table->unsignedInteger('picture_id')->nullable();
    $table->foreign('picture_id')
        ->references('id')
        ->on('media');

    $table->timestamps();
});

Schema::create('movie_sessions', function (Blueprint $table) {
    $table->increments('id');

    $table->dateTime('starts_in');
    $table->dateTime('ends_in');

    $table->unsignedInteger('movie_theater_room_id');
    $table->foreign('movie_theater_room_id')
        ->references('id')
        ->on('movie_theater_rooms')
        ->onDelete('cascade');

    $table->unsignedInteger('movie_id');
    $table->foreign('movie_id')
        ->references('id')
        ->on('movies')
        ->onDelete('cascade');

    $table->boolean('activated')->default(true);

    $table->timestamps();
});

где Кинотеатр имеет много КиноТеатрКомната, каждый КиноТеатрКомната имеет много ФильмСеанс и каждый ФильмСеанс принадлежит Фильм.

Я пытаюсь получить все Фильм, которые сегодня воспроизводятся на Кинотеатр, по его $movieTheaterId, но, поскольку это длинная связь, я не могу получить такую ​​коллекцию.

Это то, что я пробовал:

public function scopeGetMoviesShowingTodayOnMovieTheater($movieTheaterId)
{
    return Movie::whereHas('sessions', function ($query) use ($movieTheaterId) {
        // $query->whereDate('starts_in', Carbon::today());

        $query->whereHas('movieTheaterRoom', function ($query) use ($movieTheaterId) {
            $query->where('movie_theater_id', $movieTheaterId);
        });
    });
}

При звонке App\Models\Movie::getMoviesShowingTodayOnMovieTheater(1)->get() вот что я получил:

PHP Recoverable fatal error: Object of class Illuminate/Database/Eloquent/Builder could not be converted to string in .../vendor/illuminate/support/Str.php on line 338

Я также пытался использовать этот пакет staudenmeir/eloquent-has-many-deep следующим образом:


class MovieTheater extends Model {
    use HasRelationships;

    public function movies()
    {
        return $this->hasManyDeep(Movie::class, [MovieSession::class, MovieTheaterRoom::class]);
    }
}

И при звонке App\Models\MovieTheater::find(1)->movies()->get()

Это результат:

Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'movie_sessions.movie_theater_id' in 'field list' (SQL: select movies.*, movie_sessions.movie_theater_id from movies inner join movie_theater_rooms on movie_theater_rooms.id = movies.movie_theater_room_id inner join movie_sessions on movie_sessions.id = movie_theater_rooms.movie_session_id where movie_sessions.movie_theater_id = 1)'

Где я не прав?

Как выглядит ваша структура таблицы?

Qirel 09.04.2019 10:35

Я добавил свои миграции к вопросу.

Eleandro Duzentos 09.04.2019 10:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
3
2
122
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Исключение

Object of class Illuminate/Database/Eloquent/Builder could not be converted to string in .../vendor/illuminate/support/Str.php on line 338

выбрасывается, потому что вы не указали параметр $query в своем определении области. Ваш код попытается преобразовать идентификатор кинотеатра в экземпляр Builder, что не удастся.

Попробуйте реорганизовать свой код следующим образом:

/**
 * Scope a query to only select movies that are showing in a certain theater.
 *
 * @param  \Illuminate\Database\Eloquent\Builder  $query
 * @param  int  $movieTheaterId
 * @return \Illuminate\Database\Eloquent\Builder
 */
public function scopeGetMoviesShowingTodayOnMovieTheater($query, $movieTheaterId)
{
    return $query
        ->whereHas('sessions.movieTheaterRoom', function ($query) use 
        ($movieTheaterId) {
            $query->whereMovieTheaterId($movieTheaterId);
        });
}

Я также добавил точечную нотацию в оператор whereHas для запроса вложенного отношения.

Я все еще получаю сообщение об ошибке: PHP Recoverable fatal error: Object of class Illuminate/Database/Eloquent/Builder could not be converted to string in .../vendor/illuminate/support/Str.php on line 338

Eleandro Duzentos 09.04.2019 10:35

Вы получаете это исключение, потому что ваше определение области неверно, оно должно возвращать построитель запросов. Смотрите обновленный ответ.

piscator 09.04.2019 10:38

Но это то, что я возвращаю.

Eleandro Duzentos 09.04.2019 10:41

Правильно, я был слишком быстр. Проблема в том, что вы пропустили параметр построителя запросов. Ваш код пытается преобразовать идентификатор кинотеатра в экземпляр построителя запросов.

piscator 09.04.2019 10:44

И что я должен делать? Это может быть потому, что я использую функцию с ограниченной областью действия?

Eleandro Duzentos 09.04.2019 10:45

Просто следуйте примеру в этом ответе, укажите параметр $query в определении области и определите идентификатор кинотеатра в качестве второго параметра.

piscator 09.04.2019 10:47

Работал как шарм! Можете ли вы сделать это как ответ, чтобы я мог пометить вопрос как отвеченный?

Eleandro Duzentos 09.04.2019 10:50

Здорово! Я изменил структуру ответа.

piscator 09.04.2019 10:58

Если вы хотите использовать staudenmeir/eloquent-has-many-deep, вы должны сделать заказ следующим образом

class MovieTheater extends Model {
    use HasRelationships;

    public function movies()
    {
        return $this->hasManyDeep(Movie::class, [MovieTheaterRoom::class, MovieSession::class]);
    }
}

Пример заказа:

Другие вопросы по теме