分类下的话题列表
『话题分类』功能有助于话题的归类,方便用户查阅信息,本次,我们将开发以下功能:
根据分类显示话题列表; 列表页面标题定制; 增加顶部导航栏; 导航栏的选中状态。
1. 根据分类列表话题
路由文件新增一行:
routes/web.php
// 话题
Route::resource('categories', 'CategoriesController', ['only' => ['show']]);
使用命令行创建控制器:
php artisan make:controller CategoriesController
控制器中新增方法 show() :
app/Http/Controllers/CategoriesController.php
<?php
namespace App\Http\Controllers;
use App\Models\Category;
use App\Models\Topic;
use Illuminate\Http\Request;
class CategoriesController extends Controller
{
// 类别详情页
public function show(Category $category)
{
// 读取分类 ID 关联的话题,并按每 20 条分页
$topics = Topic::where('category_id', $category->id)->paginate(20);
// 传参变量话题和分类到模板中
return view('topics.index', compact('topics', 'category'));
}
}
接下来在话题列表中为分类添加 categories.show 路由链接:
resources/views/topics/_topic_list.blade.php
<a href="{{ route('topics.show', [$topic->id]) }}" title="{{ $topic->title }}">
{{ $topic->title }}
</a>
我们还需定制列表页面模板,用以标示当前所在的分类,以此来与『所有话题列表页面』区分:
resources/views/topics/index.blade.php
@extends('layouts.app')
@section('title', '话题列表')
@section('content')
<div class="row mb-5">
<div class="col-lg-9 col-md-9 topic-list">
@if (isset($category))
<div class="alert alert-info" role="alert">
{{ $category->name }} :{{ $category->description }}
</div>
@endif
<div class="card ">
.
.
.
浏览器访问话题列表页:
并点击某个分类的链接进入分类列表页:
列表页面标题定制
当我们在『分类话题列表』页面时,我们希望页面的标题里有当前的分类名称:
修改列表页面模板,使用 来定制 title 区块:
resources/views/topics/index.blade.php
@extends('layouts.app')
@section('title', isset($category) ? $category->name : '话题列表')
@section('content')
再次刷新页面:
增加顶部导航栏
接下来新增顶部导航栏,让用户能更加方便的查看分类信息:
resources/views/layouts/_header.blade.php
<!-- 导航栏 -->
<ul class="navbar-nav mr-auto">
<li class="nav-item active"><a class="nav-link" href="{{ route('topics.index') }}">话题</a></li>
<li class="nav-item"><a class="nav-link" href="{{ route('categories.show', 1) }}">分享</a></li>
<li class="nav-item"><a class="nav-link" href="{{ route('categories.show', 2) }}">教程</a></li>
<li class="nav-item"><a class="nav-link" href="{{ route('categories.show', 3) }}">问答</a></li>
<li class="nav-item"><a class="nav-link" href="{{ route('categories.show', 4) }}">公告</a></li>
</ul>
刷新页面:
现在我们可以很方便地通过顶部导航栏来筛选信息,接下来我们需要处理下选中状态。
导航的 Active 状态
导航的选中状态样式是通过添加 CSS 类选择器 active 来实现的:
<!-- 导航栏 -->
<ul class="navbar-nav mr-auto">
<li class="nav-item active"><a class="nav-link" href="{{ route('topics.index') }}">话题</a></li>
<li class="nav-item"><a class="nav-link" href="{{ route('categories.show', 1) }}">分享</a></li>
<li class="nav-item"><a class="nav-link" href="{{ route('categories.show', 2) }}">教程</a></li>
<li class="nav-item"><a class="nav-link" href="{{ route('categories.show', 3) }}">问答</a></li>
<li class="nav-item"><a class="nav-link" href="{{ route('categories.show', 4) }}">公告</a></li>
</ul>
此样式是 Bootstrap 框架的 提供。
我们需要通过判断『路由命名』和『路由参数』为导航栏添加 active 类,接下来我们使用一个很方便的类库来辅助我们实现此功能。
使用 Composer 安装 hieu-le/active:
composer require "hieu-le/active
安装完成后,在模板中使用:
<!-- 导航栏 -->
<ul class="navbar-nav mr-auto">
<li class="nav-item {{ active_class(if_route('topics.index')) }}"><a class="nav-link" href="{{ route('topics.index') }}">话题</a></li>
<li class="nav-item {{ active_class(1) }}"><a class="nav-link" href="{{ route('categories.show', 1) }}">分享</a></li>
<li class="nav-item {{ active_class(2) }}"><a class="nav-link" href="{{ route('categories.show', 2) }}">教程</a></li>
<li class="nav-item {{ active_class(3) }}"><a class="nav-link" href="{{ route('categories.show', 3) }}">问答</a></li>
<li class="nav-item {{ active_class(4) }}"><a class="nav-link" href="{{ route('categories.show', 4) }}">公告</a></li>
</ul>
上面代码看起来很复杂,太多重复代码,我们来优化下。将重复代码抽出来放到一个辅助函数里:
app/helpers.php
function category_nav_active($category_id)
{
return active_class((if_route('categories.show') && if_route_param('category', $category_id)));
}
重新修改模板里的调用:
resources/views/layouts/_header.blade.php
<!-- 导航栏 -->
<ul class="navbar-nav mr-auto">
<li class="nav-item {{ active_class(if_route('topics.index')) }}"><a class="nav-link" href="{{ route('topics.index') }}">话题</a></li>
<li class="nav-item {{ category_nav_active(1) }}"><a class="nav-link" href="{{ route('categories.show', 1) }}">分享</a></li>
<li class="nav-item {{ category_nav_active(2) }}"><a class="nav-link" href="{{ route('categories.show', 2) }}">教程</a></li>
<li class="nav-item {{ category_nav_active(3) }}"><a class="nav-link" href="{{ route('categories.show', 3) }}">问答</a></li>
<li class="nav-item {{ category_nav_active(4) }}"><a class="nav-link" href="{{ route('categories.show', 4) }}">公告</a></li>
</ul>
接下来讲解下 active_class 函数的用法,此函数的定义如下:
/**
* 如果 $condition 不为 True 即会返回字符串 `active`
*
* @param $condition
* @param string $activeClass
* @param string $inactiveClass
*
* @return string
*/
function active_class($condition, $activeClass = 'active', $inactiveClass = '')
如果传参满足指定条件 ( activeClass ,否则返回 $inactiveClass 。
此扩展包提供了一批函数让我们更方便的进行 $condition 判断:
- if_route() - 判断当前对应的路由是否是指定的路由;
- if_route_param() - 判断当前的 url 有无指定的路由参数。
- if_query() - 判断指定的 GET 变量是否符合设置的值;
- if_uri() - 判断当前的 url 是否满足指定的 url;
- if_route_pattern() - 判断当前的路由是否包含指定的字符;
- if_uri_pattern() - 判断当前的 url 是否含有指定的字符; 在这里我们用到第 1 和 第 2 。
测试一下: