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

#php #laravel #eloquent

#php #laravel #красноречивый

Вопрос:

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

  • Фильм
  • MovieSession
  • MovieTheater
  • Кинотеатральный зал

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

 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();
});
  

там, где в MovieTheater есть множество кинотеатров, в каждом кинотеатре есть множество сеансов фильмов, и каждый сеанс принадлежит фильму.

Что я пытаюсь, так это получить все фильмы, которые воспроизводятся сегодня на MovieTheater, по его $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);
        });
    });
}
  

При вызове AppModelsMovie::getMoviesShowingTodayOnMovieTheater(1)->get() это то, что я получил:

Исправляемая неустранимая ошибка PHP: объект класса Illuminate /Database /Eloquent / Builder не удалось преобразовать в строку в …/vendor/illuminate/support/Str.php в строке 338

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

 
class MovieTheater extends Model {
    use HasRelationships;

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

И при вызове AppModelsMovieTheater::find(1)->movies()->get()

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

Осветите / Database / QueryException с сообщением ‘SQLSTATE[42S22]: столбец не найден: 1054 неизвестных столбца ‘movie_sessions.movie_theater_id’ в ‘списке полей’ (SQL: выберите movies .*, movie_sessions . movie_theater_id из movies внутреннего соединения movie_theater_rooms на movie_theater_rooms . id = movies . movie_theater_room_id внутреннее соединение movie_sessions на movie_sessions . id = movie_theater_rooms . movie_session_id где movie_sessions . movie_theater_id = 1)’

Где я ошибаюсь?

Комментарии:

1. Как выглядит ваша табличная структура?

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

Ответ №1:

Исключение

Объект класса Illuminate /Database /Eloquent /Builder не удалось преобразовать в строку в …/vendor/illuminate/support/Str.php в строке 338

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

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

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

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

Комментарии:

1. Я все еще получаю ошибку: 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

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

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

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

5. Сработало как по волшебству! Можете ли вы оформить это как ответ, чтобы я мог пометить вопрос как отвеченный?

Ответ №2:

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

 class MovieTheater extends Model {
    use HasRelationships;

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

Примерный порядок:
введите описание изображения здесь