У меня есть следующие красноречивые сущности:
Структура таблицы:
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
frommovies
inner joinmovie_theater_rooms
onmovie_theater_rooms
.id
=movies
.movie_theater_room_id
inner joinmovie_sessions
onmovie_sessions
.id
=movie_theater_rooms
.movie_session_id
wheremovie_sessions
.movie_theater_id
= 1)'
Где я не прав?
Я добавил свои миграции к вопросу.
Исключение
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
Вы получаете это исключение, потому что ваше определение области неверно, оно должно возвращать построитель запросов. Смотрите обновленный ответ.
Но это то, что я возвращаю.
Правильно, я был слишком быстр. Проблема в том, что вы пропустили параметр построителя запросов. Ваш код пытается преобразовать идентификатор кинотеатра в экземпляр построителя запросов.
И что я должен делать? Это может быть потому, что я использую функцию с ограниченной областью действия?
Просто следуйте примеру в этом ответе, укажите параметр $query в определении области и определите идентификатор кинотеатра в качестве второго параметра.
Работал как шарм! Можете ли вы сделать это как ответ, чтобы я мог пометить вопрос как отвеченный?
Здорово! Я изменил структуру ответа.
Как выглядит ваша структура таблицы?