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

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

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

ex.

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

или

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

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

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

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

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

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

приемлемым решением было бы добавить еще один столбец в мою таблицу отчетов и добавить только offender_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('AppUser');
    }
}

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

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

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

Комментарий Модель

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

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

1 ответов


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

$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. если у вас есть другие модели, которые имеют отношения доклад, просто представьте себе хаос.

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

добавить на 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();