У меня есть следующие модели:
Вопрос: [название, user_id]
Отвечать: [тело, id_вопроса, id_пользователя]
Пользователь: [имя]
Как видите, на вопрос есть много ответов, и ответ принадлежит пользователю.
Я добавил отношение участники к модели Вопрос, которая извлекает всех пользователей, добавивших ответ (используя ответы в качестве таблицы соединения):
public function contributors()
{
return $this->belongsToMany(User::class, 'replies')->distinct('user_id');
}
Мне пришлось использовать distinct() для удаления дубликатов, потому что пользователь может опубликовать много ответов на один вопрос, и это отлично работает.
Теперь проблема возникает, когда я делаю:
Question::withCount('contributors')->get()
Он игнорирует вызов distinct() и дает мне общее количество пользователей, которые добавили ответ (включая дубликаты).
Любая идея, как я могу это исправить?






Вы можете сделать это, добавив обратный вызов в метод withCount.
$questions = Question::withCount('contributors', function ($query) {
$query->distinct('user_id');
})->get()
Я думаю, что метод отношения должен содержать только определение отношения, без различения. Это может быть также причиной того, что мое предложение не работает.
Это не сработает, даже если я удалю вызов, отличный от определения отношения... это дает тот же результат.
извините за неправильный ответ, я проверил отдельный метод в документах Laravel, и он не принимает никаких аргументов, поэтому он должен быть только отдельным (). Однако мне интересно, работает ли ваш первый выбор - просто получить всех участников, они разные? Таким образом, решением может быть выбор только user_id в методе обратного вызова, а затем вызов отдельного запроса.
Спасибо за вашу помощь, мне пришлось использовать необработанное выражение, как говорит другой ответ.
Удалите 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 для автоматического включения счетчика, верно?
Не напрямую, но вы можете установить свойство $withCount в конструкторе вашей модели.
Вы также можете использовать переменную здесь для различия
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();
иначе в некоторых случаях вы получите разные результаты.
К сожалению, это не имело значения.