Laravel 项目:使用 TDD 构建论坛 Chapter 14

0.写在前面

  • 本系列文章为laracasts.com 的系列视频教程——Let's Build A Forum with Laravel and TDD 的学习笔记。若喜欢该系列视频,可去该网站订阅后下载该系列视频, 支持正版
  • 视频源码地址:https://github.com/laracasts/Lets-Build-a-Forum-in-Laravel
  • *本项目为一个 forum(论坛)项目,与本站的第二本实战教程 Laravel 教程 - Web 开发实战进阶 ( Laravel 5.5 ) 类似,可互相参照
  • 项目开发模式为TDD开发,教程简介为:

    A forum is a deceptively complex thing. Sure, it's made up of threads and replies, but what else might exist as part of a forum? What about profiles, or thread subscriptions, or filtering, or real-time notifications? As it turns out, a forum is the perfect project to stretch your programming muscles. In this series, we'll work together to build one with tests from A to Z.

  • 项目版本为 laravel 5.4,教程后面会进行升级到 laravel 5.5 的教学
  • 视频教程共计 102 个小节,笔记章节与视频教程一一对应

1.本节说明

  • 对应视频第 14 小节:A User Can Filter Threads By Username

2.本节内容

本节我们来实现根据用户来筛选话题的功能。首先运行一下测试:
file
会发现我们所有的测试都报错了,这是因为我们在上一节使用了 视图共享数据 :
forum\app\Providers\AppServiceProvider.php

.
.
public function boot()
{
    Carbon::setLocale('zh');
    \View::share('channels',\App\Channel::all());
}
.
.

boot()方法会在应用启动的最开始时就加载,在测试场景中,运行测试时,测试数据库中是不存在数据表的,所以就抛出了异常。我们改为使用 视图合成器

视图合成器是在渲染视图时调用的回调或者类方法。如果你每次渲染视图时都要绑定视图的数据,视图合成器可以帮你将这些逻辑整理到特定的位置。

forum\app\Providers\AppServiceProvider.php

.
.
public function boot()
{
    Carbon::setLocale('zh');
    \View::composer('*',function ($view){
       $view->with('channels',Channel::all()); 
    });
}
.
.

再次运行测试:
file
所以我们在更改了代码之后,要记得运行一下测试,确保代码无误。接下来按照惯例,建立新功能之前,先建立测试:
forum\tests\Feature\ReadThreadsTest.php

.
.
/** @test */
public function a_user_can_filter_threads_by_any_username()
{
    $this->signIn(create('App\User',['name' => 'NoNo1']));

    $threadByNoNo1 = create('App\Thread',['user_id' => auth()->id()]);
    $threadNotByNoNo1 = create('App\Thread');

    $this->get('threads?by=NoNo1')
        ->assertSee($threadByNoNo1->title)
        ->assertDontSee($threadNotByNoNo1->title);
}
.
.

运行测试会失败:
file
修改index()方法:
forum\app\Http\Controllers\ThreadsController.php

.
.
public function index(Channel $channel)
{
    if($channel->exists){
        $threads = $channel->threads()->latest();
    }else{
        $threads = Thread::latest();
    }

    if($username = request('by')){
        $user = \App\User::where('name',$username)->firstOrFail();

        $threads->where('user_id',$user->id);
    }

    $threads  = $threads->get();

    return view('threads.index',compact('threads'));
}
.
.

注:现在控制器中的代码比较粗糙,我们先让测试通过,在后面会进行重构,不要着急

运行测试:
file
系统界面:
file
修改导航栏,将这一功能显示出来:
forum\resources\views\layouts\app.blade.php

.
.
<div class="collapse navbar-collapse" id="app-navbar-collapse">
    <!-- Left Side Of Navbar -->
    <ul class="nav navbar-nav">
        <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-hidden="true"
               aria-expanded="false">Browse <span class="caret"></span> </a>

            <ul class="dropdown-menu">
                <li><a href="/threads">ALL Threads</a> </li>
                <li><a href="/threads?by={{ auth()->user()->name }}">My Threads</a> </li>
            </ul>
        </li>

        <li><a href="/threads/create">New Thread</a></li>
.
.

file
运行测试,看我们是否破坏了功能:

$ APP_ENV=testing phpunit

file
根据报错信息可知,在此行代码中:

<li><a href="/threads?by={{ auth()->user()->name }}">My Threads</a> </li>

若未登录,auth()->user()的值为null,因此会抛出上面的异常。修改一下代码:
forum\resources\views\layouts\app.blade.php

.
.
<div class="collapse navbar-collapse" id="app-navbar-collapse">
    <!-- Left Side Of Navbar -->
    <ul class="nav navbar-nav">
        <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-hidden="true"
               aria-expanded="false">Browse <span class="caret"></span> </a>

            <ul class="dropdown-menu">
                <li><a href="/threads">ALL Threads</a> </li>

                @if(auth()->check())
                    <li><a href="/threads?by={{ auth()->user()->name }}">My Threads</a> </li>
                @endif

            </ul>
        </li>

        <li><a href="/threads/create">New Thread</a></li>
.
.

再次测试:
file

3.写在后面

  • 如有建议或意见,欢迎指出~
  • 如果觉得文章写的不错,请点赞鼓励下哈,你的鼓励将是我的动力!
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 2

作者你好,你写的东西好像没有人看哎 。。。我替你着急。。。

5年前 评论
洛未必达

@shenyukun 哈哈,其实写这个,收获最大的是我自己。我自己有收获的同时,也想分享出来给大家看。等我更新完的时候再大力宣传一波,23333 :grin:

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!