Использование отношения Laravel Eloquents HasManyThrough с несколькими отношениями через полиморфизм

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

Получение отчетов пользователей не является проблемой, это можно сделать напрямую с помощью user->reports() но мне бы очень хотелось получать отчеты, в которых другие люди сообщали о указанном пользователе. Я могу заставить это работать, используя либо hasManyThrough отношение или запросы НО только на одной модели за один раз.

ех.

public function offenses() {
return $this->hasManyThrough('Recipe', 'Reports');
}

Или же

->with('user.recipe.reports')

Проблема в том, что мой отчетный объект — это не просто рецепты, это могут быть комментарии, изображения и т. Д. Поэтому вместо использования нескольких функций логичным способом было бы как-то проанализировать связь между hasManyThrough различными параметрами.

Теоретически выглядит так:

public function offenses() {
return $this->hasManyThrough(['Recipe', 'RecipeComments'], 'Reports');
}

Это каким-либо образом возможно? С каким-то недокументированным синтаксисом? Если нет, то есть ли какие-нибудь умные обходные пути / взломы?

Возможное решение?

Было бы приемлемым решением добавить еще один столбец в мою таблицу отчетов и добавить только offender_id, как это?

ID | User_id | Offender_id | Reportable_type | Reportable_id

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


модели

Полиморфная модель

class Report extends Model {
public function reportable() {
return $this->morphTo();
}

public function User() {
return $this->belongsTo('App\User');
}
}

Рецепт Модель

class Recipe extends Model {
public function user() {
return $this->belongsTo('App\User');
}

public function reports() {
return $this->morphMany('App\Report', 'reportable');
}
}

Модель комментария

class RecipeComment extends Model {
public function user() {
return $this->belongsTo('App\User');
}

public function reports() {
return $this->morphMany('App\Report', 'reportable');
}
}

7

Решение

Используя вашу текущую модель, вы можете получить все зарегистрированные модели для пользователя с помощью следующего кода:

$recipeCommentReport = RecipeComment::whereHas('reports',function($q){
return $q->where('user_id','=',Auth::user()->id)
});

$recipeReport = Recipe::whereHas('reports',function($q){
return $q->where('user_id','=',Auth::user()->id)
});

//Get all reports into one
$reports = $recipeReport->merge([$recipeCommentReport]);

В лучшем случае это грязно, потому что:

  1. Мы не можем отсортировать результаты, учитывая, что мы используем два отдельных запроса базы данных.
  2. Если у вас есть другие модели с отчетными отношениями, просто представьте себе хаос.

Лучшее решение, как вы поняли выше:

Добавить offender_id колонка к вашему report Таблица.

Это чище и следует принципу СУХОЙ.

Сценарии типичного случая

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

Report::where('offender_id','=',Auth::check()->id)
->where('reportable_type','=','RecipeComment')
->get();

Считать оскорбления по типу для пользователя

Report::where('offender_id','=',Auth::check()->id)
->grouBy('reportable_type')
->select(Db::raw('count(*)'),'reportable_type')
->get();
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]