您现在的位置是:网站首页 > 心得笔记

laravel框架中本地作用域的使用

盛悦2019-08-06548人围观
简介通过 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'));
    }}