本书未发布

62. 分类话题列表

未匹配的标注

简介

在本节里,我们实现点击顶部导栏里的『话题分类』显示该分类的话题列表。

需求分解

『话题分类』功能有助于话题的归类,方便用户按照话题分类查阅信息,本章节中,我们将开发以下功能:

  • 根据分类显示话题列表;
  • 分类名称作为列表页面标题;
  • 在顶部导航栏添加分类列表入口;
  • 给导航栏添加选中状态。

数据模型

首先,我们修改 Topic::minePaginate 方法,让它支持按分类搜索功能。

application/common/model/Topic.php

<?php
.
.
.
class Topic extends Model
{
    .
    .
    .
    /**
     * 分页查询方法
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2019-06-20
     * @param    array              $params    请求参数
     * @param    integer            $page_rows 每页显示数量
     * @return   [type]                        分页查询结果
     */
    public static function minePaginate($param = [], $per_page = 20)
    {
        $self = self;
        foreach ($param as $name => $value) {
            switch ($name) {
                case 'category_id':
                    if($value > 0){
                        $self = $self->where($name, $value);
                    }
                    break;
            }
        }
        $paginate = $self->paginate($per_page);
        return $paginate;
    }
}

控制器

  1. 首先,因为我们要在导航栏显示出所有分类,所以 Base 控制器在初始化时需要查询出所有分类信息:

application/index/controller/Base.php

<?php

namespace app\index\controller;
.
.
.
use app\common\model\Category as CategoryModel;

class Base extends Controller
{
    protected function initialize()
    {
        if(!request()->isAjax()){
            $site = ConfigModel::siteSetting();
            $this->assign('site', $site);

            $flash_names = ['success', 'info', 'danger'];
            foreach ($flash_names as $key => $name) {
                if(Session::has($name)){
                    $flash[$name] = Session::pull($name);
                }
            }
            $this->assign('flash', $flash);

            $categories = CategoryModel::order('id', 'ASC')->all();
            $this->assign('categories', $categories);
        }
    }
}
  1. 接着,使用命令行创建分类控制器:
$ php think make:controller index/Category

因为我们在分类控制器只需要展示话题列表,所以只需要 read 方法,完整代码如下。

application/index/controller/Category.php

<?php

namespace app\index\controller;

use think\Request;

use app\common\model\Topic as TopicModel;
use app\common\model\Category as CategoryModel;

class Category extends Base
{
    public function read(Request $request, $id)
    {
        $category = CategoryModel::find($id);
        $this->assign('category', $category);

        $param['category_id'] = $id;
        $paginate = TopicModel::minePaginate($param);
        $this->assign('paginate', $paginate);

        // 使用topic/index页面渲染输出
        return $this->fetch('topic/index');
    }
}

路由

在配置文件里定义控制方法访问路由规则:

route/route.php

<?php
.
.
.
// 话题管理
Route::get('topic', 'topic/index')->name('topic.index');
Route::get('category/<id>', 'category/read')->name('category.read');

助手函数

我们需要定义一个助手函数实现——当用户访问的是 category.read 页面时对应的分类菜单项是选中状态,否则 「话题」菜单项是选中状态。

application/index/common.php

<?php
.
.
.
/**
 * 顶部导航是否选中样式
 * @Author   zhanghong(Laifuzi)
 * @DateTime 2019-02-23
 * @param    string             $route_name 路由路径
 * @param    array              $param      判断参数
 * @return   [type]                         [description]
 */
function navbar_class($route_name, $param = [])
{
    $request = request();
    try{
        // 使用 request的 controlelr 和 action 方法生成当前访问页面路由路径
        $ctr_name = $request->controller(true);
        $act_name = $request->action(true);
        $page_route = $ctr_name . '/' .$act_name;
    }catch(\Exception $e){
        // 当 request 不存在 controller 或 action 方法时,使用routeInfo生成当前访问页面路由路径
        $route_info = $request->routeInfo();
        if(empty($route_info) || empty($route_info['route'])){
            $page_route = '';
        }else{
            $page_route = $route_info['route'];
        }
    }

    if(empty($page_route)){
        // 当前访问页面路由路径为空
        return '';
    }else if($route_name != $page_route){
        // 当前路由路径 和 菜单项路由路径不相等
        return '';
    }

    if(empty($param)){
        // 当前路由路径 和 菜单项路由路径相等 并且没有判断参数
        // 菜单项必然是选中状态
        return 'active';
    }

    $is_active = true;
    // 只有当所有 判断参数 都相等时菜单项才是选中状态
    foreach ($param as $name => $value) {
        $param_value = $request->param($name);
        $pm[$name] = $param_value;
        if($param_value != $value){
            $is_active = false;
            break;
        }
    }

    if($is_active){
        return 'active';
    }else{
        return '';
    }
}

视图模板

  1. 首先,我们在顶部导航栏里添加所有分类列表页入口,并且使用助手方法 navbar_class 给所有菜单项添加上选中状态判断。

application/index/view/layout/_header.html

.
.
.
<!-- Left Side Of Navbar -->
<ul class="navbar-nav mr-auto">
    <li class="nav-item <?php echo(navbar_class('topic/index')) ?>">
        <a class="nav-link" href="{:url('[topic.index]')}">话题</a>
    </li>
    {volist name="categories" id="category"}
        <li class="nav-item <?php echo(navbar_class('category/read', ['id' => $category->id])) ?>">
            <a class="nav-link" href="{:url('[category.read]', ['id' => $category->id])}">{$category->name}</a>
        </li>
    {/volist}
</ul>
.
.
.
  1. 接下来,为了实现「分类名称作为列表页面标题」,我们需要在话题列表页显示出分类名称:

application/index/view/topic/index.html

.
    .
    .
<div class="col-lg-9 col-md-9 topic-list">
    {if(isset($category) && !empty($category))}
        <div class="alert alert-info" role="alert">
            {$category->name} :{$category->description}
        </div>
    {/if}

    <div class="card ">
        .
        .
        .
    </div>
</div>
.
.
.
  1. 最后,我们还需要给列表里的话题分类添加 category.read 路由链接。

application/index/view/topic/_list.html

.
.
.
<a class="text-secondary" href="{:url('[category.read]', ['id' => $topic->category_id])}" title="{$topic->category->name}">
    <i class="far fa-folder"></i>
    {$topic->category->name}
</a>
.
.
.

样式优化

我们用浏览器访问话题列表页并点击某个分类的链接进入分类列表页,看到分类列表页样式有些混乱。

这是因为在 app.css 里使用主模板中定义的路由 CSS 类名称。

application/index/view/layout/main.html

.
.
.
<body>
    <div id="app" class="<?php echo(route_class()); ?>">
.
.
.

因为 topic.index' 和category.read两个方法使用同一个模板,当页面路由名称已变为category.read时对应的 CSS 类名已变为category-read-page` 。所以我们需要在样式表中新添加选择器。

public/static/assets/index/css/app.css'

.
.
.
/* Topic Index Page */

.topic-index-page .topic-list .nav > li > a,
.category-read-page .topic-list .nav > li > a{
  position: relative;
  display: block;
  padding: 5px 14px;
  font-size: 0.9em;
}

.topic-index-page .topic-list a,
.category-read-page .topic-list a{
  color: #444444;
}

.topic-index-page .topic-list .meta,
.category-read-page .topic-list .meta{
  font-size: 0.9em;
  color: #b3b3b3;
}

.topic-index-page .topic-list .meta a,
.category-read-page .topic-list .meta a{
  color: #b3b3b3;
}

.topic-index-page .topic-list .badge,
.category-read-page .topic-list .badge{
  background-color: #d8d8d8;
}

.topic-index-page .topic-list hr,
.category-read-page .topic-list hr{
  margin-top: 12px;
  margin-bottom: 12px;
  border: 0;
  border-top: 1px solid #dcebf5;
}
.
.
.

效果展示

Git 版本控制

下面把代码纳入到版本管理里:

$ git add -A
$ git commit -m "分类话题列表"

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~