Я получил довольно простое приложение, в котором пользователь может публиковать комментарии и рецепты других пользователей. Я использую полиморфное отношение для хранения отчетов. Который отлично работает; однако сейчас я пытаюсь получить оскорбления, совершенные пользователем.
Получение отчетов пользователей не является проблемой, это можно сделать напрямую с помощью 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');
}
}
Используя вашу текущую модель, вы можете получить все зарегистрированные модели для пользователя с помощью следующего кода:
$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]);
В лучшем случае это грязно, потому что:
Лучшее решение, как вы поняли выше:
Добавить 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();
Других решений пока нет …