WithTrashed в промежуточной модели отношения hasManyThrough

У меня есть 3 класса, связанных следующим образом:

Exhibitor
'- Bills
   '- Tickets

Счета и билеты используют черту SoftDeletes, а в классе Exhibitor у меня есть это отношение:

public function tickets()
{
    return $this->hasManyThrough(Ticket::class, Bill::class);
}

Мне нужно получить все билеты, включая удаленные (withTrashed), но это также должно включать все удаленные счета. Проблема в том, что withTrashed применяется только к модели Tickets, а не к Bills.

Этот запрос

    $tickets = exhibitor()->tickets()->withTrashed()
        ->where('bills.updated_at', '>=', Carbon::parse($since))
        ->orderBy('tickets.id')
        ->get();

Генерирует этот SQL

select `tickets`.*, `bills`.`exhibitor_id` from `tickets`
inner join `bills` on `bills`.`id` = `tickets`.`bill_id`
where `bills`.`deleted_at` is null 
and `bills`.`exhibitor_id` = ?
and `bills`.`updated_at` >= ?
order by `tickets`.`id` asc

Принимая во внимание, что мне нужен этот SQL без «bills.deleted_at is null», например:

select `tickets`.*, `bills`.`exhibitor_id` from `tickets`
inner join `bills` on `bills`.`id` = `tickets`.`bill_id`
where `bills`.`exhibitor_id` = ?
and `bills`.`updated_at` >= ?
order by `tickets`.`id` asc

Но я не вижу никаких вариантов, где я могу установить withTrashed() для модели Билла. Я думал, что должна быть возможность установить запрос обратного вызова для метода hasManyThrough, но, согласно API, это не поддерживается. Это кажется таким простым, и у меня такое чувство, что я что-то упускаю из виду, но я не могу этого найти...

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
2
0
226
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я бы определил область для модели билетов, поскольку запрос становится немного сложным.

public function scopeBillsSince($query, $since)
    return $query->whereHas('bills', function ($query2) use ($since) {
        return $query2->withThrashed()->where('updated_at', '>=', Carbon::parse($since))
    });
}

Теперь, используя эту область, вы можете запрашивать билеты следующим образом:

$tickets = exhibitor()->tickets()->withTrashed()->billsSince($since);

Насколько я знаю, запрос области основывается на exhibitor()->tickets()->withTrashed(), и в нем уже отсутствуют удаленные счета, поэтому я не уверен, как это может помочь, но я попробую, просто чтобы выяснить это.

Fluxlicious 01.03.2019 15:42

Просто подтвердил мое подозрение, вы не можете изменить запрос, уже определенный до области.

Fluxlicious 01.03.2019 15:58
Ответ принят как подходящий

На данный момент это невозможно: https://github.com/laravel/framework/issues/23039

Если вы не возражаете против установки внешнего пакета, вы можете использовать этот пакет, который я создал: https://github.com/staudenmeir/eloquent-has-many-deep

class Exhibitor extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function tickets()
    {
        return $this->hasManyDeep(Ticket::class, [Bill::class])
            ->withTrashed('bills.deleted_at');
    }
}

Этот пакет действительно идеален. Это также решает другую проблему, с которой я столкнулся, когда мне понадобилось 3-уровневое вложенное отношение. Спасибо, Джонас. В итоге я создал второе отношение в классе Exhibitor: >с мусором‌​ed(); }

Fluxlicious 01.03.2019 16:11

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