您现在的位置是:网站首页 > 心得笔记
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'));
}}