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

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

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

Ответить: [body, question_id, user_id]

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

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

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

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

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

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

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

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

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


person Amr Noman    schedule 05.05.2019    source источник


Ответы (4)


Удалите 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();
person Jonas Staudenmeir    schedule 05.05.2019
comment
Спасибо, это работает. Но я предполагаю, что это нельзя использовать со свойством $withCount для автоматического включения счетчика, верно? - person Amr Noman; 05.05.2019
comment
Не напрямую, но вы можете установить свойство $withCount в конструкторе вашей модели. - person Jonas Staudenmeir; 05.05.2019

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

$questions = Question::withCount('contributors', function ($query) {
    $query->distinct('user_id');
})->get()
person Silencesys    schedule 05.05.2019
comment
К сожалению, это не имело значения. - person Amr Noman; 05.05.2019
comment
Я думаю, что метод отношения должен содержать только определение отношения, без различения. Это может быть также причиной того, что мое предложение не работает. - person Silencesys; 05.05.2019
comment
Это не сработает, даже если я удалю вызов, отличный от определения отношения... это дает тот же результат. - person Amr Noman; 05.05.2019
comment
извините за неправильный ответ, я проверил отдельный метод в документах Laravel, и он не принимает никаких аргументов, поэтому он должен быть только отдельным (). Однако мне интересно, работает ли ваш первый выбор - просто получить всех участников, они разные? Таким образом, решением может быть выбор только user_id в методе обратного вызова, а затем вызов отдельного запроса. - person Silencesys; 05.05.2019
comment
Спасибо за вашу помощь, мне пришлось использовать необработанное выражение, как говорит другой ответ. - person Amr Noman; 05.05.2019

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

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();
person MaNsHa QaRiB    schedule 05.05.2019

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

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

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

person whallas pimentel    schedule 19.08.2020