您现在的位置是:网站首页 > 心得笔记
laravel框架中本地作用域的使用
简介通过 URI 传参 order 给控制器,控制器根据此参数来决定数据的读取逻辑。因为多个列表都会用到排序,并且是在不同的控制器中,所以在此处为了复用性考虑,我们将会把排序逻辑代码放置于 某一个的数据模型中。作为一个合格的程序员,编码时需时刻注意代码复用性
具体参考文档!!!
接下来的步骤是:
Topic 中编写排序逻辑;
TopicsController 控制器中调用;
CategoriesController 控制器中调用。
...class Topic extends Model{ . . . public function scopeWithOrder($query, $order) { // 不同的排序,使用不同的数据读取逻辑 switch ($order) { case 'recent': $query->recent(); break; default: $query->recentReplied(); break; } // 预加载防止 N+1 问题 return $query->with('user', 'category'); } public function scopeRecentReplied($query) { // 当话题有新回复时,我们将编写逻辑来更新话题模型的 reply_count 属性, // 此时会自动触发框架对数据模型 updated_at 时间戳的更新 return $query->orderBy('updated_at', 'desc'); } public function scopeRecent($query) { // 按照创建时间排序 return $query->orderBy('created_at', 'desc'); }}
这里我们使用了 Laravel 本地作用域 。本地作用域允许我们定义通用的约束集合以便在应用中复用。要定义这样的一个作用域,只需简单在对应 Eloquent 模型方法前加上一个 scope 前缀,作用域总是返回 查询构建器。一旦定义了作用域,则可以在查询模型时调用作用域方法。在进行方法调用时不需要加上 scope 前缀。如以上代码中的 recent()
和 recentReplied()
。
2. 控制器中调用
接下来我们在话题控制器中链式调用定义的方法 withOrder()
:
app/Http/Controllers/TopicsController.php
<?php...class TopicsController extends Controller{... public function index(Request $request, Topic $topic) { $topics = $topic->withOrder($request->order)->paginate(20); return view('topics.index', compact('topics')); }...}
$request->order
是获取 URI http://larabbs.test/topics?order=recent
中的 order
参数。
接下来修改模板,我们需要为按钮添加链接还有选中状态:
resources/views/topics/index.blade.php
... <div class="card "> <div class="card-header bg-transparent"> <ul class="nav nav-pills"> <li class="nav-item"> <a class="nav-link {{ active_class( ! if_query('order', 'recent')) }}" href="{{ Request::url() }}?order=default"> 最后回复 </a> </li> <li class="nav-item"> <a class="nav-link {{ active_class(if_query('order', 'recent')) }}" href="{{ Request::url() }}?order=recent"> 最新发布 </a> </li> </ul> </div>...
Request::url()
获取的是当前请求的 URL
3. 分类话题列表排序
接下来我们在分类控制器中调用方法 withOrder()
:
app/Http/Controllers/CategoriesController.php
<?phpnamespace App\Http\Controllers;use Illuminate\Http\Request;use App\Models\Topic;use App\Models\Category;class CategoriesController extends Controller{ public function show(Category $category, Request $request, Topic $topic) { // 读取分类 ID 关联的话题,并按每 20 条分页 $topics = $topic->withOrder($request->order) ->where('category_id', $category->id) ->paginate(20); // 传参变量话题和分类到模板中 return view('topics.index', compact('topics', 'category')); }}