laravel - 如何使用数据透视表中的数据过滤 Eloquent 集合
问题描述
我正在寻找一种精细而简洁的解决方案,以使用相关数据透视表中的数据过滤我的 Eloquent 集合。我实际上已经找到了解决问题的方法,尽管感觉我的解决方案有点糟糕。这是我得到的:
两个模型视频和用户,每个用户都可以单独跟踪视频的进度。为此,我需要在与用户相关的评级表中保存每个视频的进度。当您只想搜索进度时,除了一些其他过滤器(类别、全文搜索)之外,您还可以这样做。我觉得有点奇怪的是,我必须将“where()”部分加倍,我正在检查登录用户的视频进度。
视频.php
class Video extends Model
{
use SearchableTrait;
use Taggable;
[...]
public function videocreator(){
return $this->belongsTo('App\User', 'create_user_id');
}
public function users(){
return $this->belongsToMany('App\User', 'progress', 'video_id', 'user_id')
->withPivot('progress_index')
->withTimestamps();
}
[...]
}
用户.php
class User extends Authenticatable
{
use Notifiable;
[...]
public function videoscreated(){
return $this->hasMany('App\Video');
}
public function videos(){
return $this->belongsToMany('App\Video', 'progress', 'user_id', 'video_id')
->withPivot('progress_index')
->withTimestamps();;
}
}
视频控制器.php
class VideoController extends Controller
{
public function index(Request $request)
{
[...]
$videos = Video::with('videocreator')->with(['users' => function ($query) {
$query->where('users.id', '=', auth()->user()->id);
}])->latest();
if($request->filled('progress') && $request['progress'] !== 'all'){
$videos = $videos->whereHas('users', function($query) use($selectedProgress) {
$query->where('progress_index', $selectedProgress)->where('users.id', '=', auth()->user()->id);
});
}
$videos = $videos->get();
[...]
}
如您所见,这部分where('users.id', '=', auth()->user()->id)
是重复的。我的一个来自 Ruby on Rails Faction 的朋友建议先从用户模型中获取视频(这就是你在那里的做法)。尽管通过这种方式,您可以将视频限制在进度表中的用户范围内。这不是你想要的。该应用程序应仅跟踪每个视频的每个用户进度,这意味着所有用户都可以看到所有视频(而不是不属于他们自己的进度。另一种方法是将您为用户过滤的部分放入关系中. 一种方法如:myProgress()
或类似的东西。
你对此有何看法?有没有更“雄辩”的方法来解决这个问题?提前感谢您阅读这篇文章!
解决方案
我会做这样的事情:
// Get an instance of the videos relationship of the current authenticated user
// Eager load the videocreator relationship
$videoQuery = request()->user()->videos()->with('videocreator');
if ($request->filled('progress') && $request->input('progress') !== "all") {
// Constrain the query : only get the videos with rated_index equal to $selectedProgress
$videoQuery = $videoQuery->wherePivot('rated_index', $selectedProgress);
}
// Finally, run the query against the database
$videos = $videoQuery->latest()->get();
推荐阅读
- python-2.7 - 使用 python 将 if 或 else 添加到 selenium google webdriver 时得到不同的结果
- spring-boot - Thymeleaf:离线添加 CSS
- c# - 将位于 SharePoint 网站中的子文档添加到 WordDocument
- java - JSch 库是否支持动态端口转发?
- c# - 在低于正常优先级的 Windows 服务中停止 Parallel.ForEach
- c# - 使用基本身份验证的正确方法是什么?
- python - Matplotlib imshow 和 kivy
- arrays - 从方法中获取空数组
- javascript - 访问我的 cookie 的第三方扩展
- cdn - 为什么 CDN 不能正常工作?