Использование withCount() для отношения, которое имеет Different()

У меня есть следующие модели:

Вопрос: [название, user_id]

Отвечать: [тело, id_вопроса, id_пользователя]

Пользователь: [имя]

Как видите, на вопрос есть много ответов, и ответ принадлежит пользователю.

Я добавил отношение участники к модели Вопрос, которая извлекает всех пользователей, добавивших ответ (используя ответы в качестве таблицы соединения):

public function contributors() 
{
    return $this->belongsToMany(User::class, 'replies')->distinct('user_id');
}

Мне пришлось использовать distinct() для удаления дубликатов, потому что пользователь может опубликовать много ответов на один вопрос, и это отлично работает.

Теперь проблема возникает, когда я делаю:

Question::withCount('contributors')->get()

Он игнорирует вызов distinct() и дает мне общее количество пользователей, которые добавили ответ (включая дубликаты).

Любая идея, как я могу это исправить?

Стоит ли изучать 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-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
3
0
694
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете сделать это, добавив обратный вызов в метод withCount.

$questions = Question::withCount('contributors', function ($query) {
    $query->distinct('user_id');
})->get()

К сожалению, это не имело значения.

Amr Noman 05.05.2019 20:00

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

Silencesys 05.05.2019 20:06

Это не сработает, даже если я удалю вызов, отличный от определения отношения... это дает тот же результат.

Amr Noman 05.05.2019 20:08

извините за неправильный ответ, я проверил отдельный метод в документах Laravel, и он не принимает никаких аргументов, поэтому он должен быть только отдельным (). Однако мне интересно, работает ли ваш первый выбор - просто получить всех участников, они разные? Таким образом, решением может быть выбор только user_id в методе обратного вызова, а затем вызов отдельного запроса.

Silencesys 05.05.2019 20:15

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

Amr Noman 05.05.2019 20:32
Ответ принят как подходящий

Удалите distinct() из отношения и используйте withCount() с необработанным выражением:

public function contributors() 
{
    return $this->belongsToMany(User::class, 'replies');
}

Question::withCount(['contributors' => function ($query) {
    $query->select(DB::raw('count(distinct(user_id))'));
}])->get();

Спасибо, это работает. Но я предполагаю, что это нельзя использовать со свойством $withCount для автоматического включения счетчика, верно?

Amr Noman 05.05.2019 20:29

Не напрямую, но вы можете установить свойство $withCount в конструкторе вашей модели.

Jonas Staudenmeir 05.05.2019 21:31

Вы также можете использовать переменную здесь для различия

public function contributors() 
{
    return $this->belongsToMany(User::class, 'replies');
}

Question::withCount(['contributors' => function ($query) use ($var)  {
    $query->select(DB::raw('count(distinct(user_id))'));
}])->get();

Вам нужно продолжать использовать Different('user_id') в методе отношения, чтобы такие операции работали правильно:

$question->contributors()->count();
$question->contributors->count();
$question->contributors()->get()->count();

иначе в некоторых случаях вы получите разные результаты.

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