Build an online forum with Laravel — Create routes, views, controllers. Generate auth. Write test (Part 2)

Connor Leech
May 5, 2017 · 3 min read

Part 1 — Initial setup and database seeding is available here.



Routing and Controller

First create the route for viewing threads. Routes are defined in routes/web.php.

Route::get(‘/threads’, ‘ThreadController@index’);

The ThreadController is in app/Http/Controllers/ThreadController.php.

In that file return the latest threads:

class ThreadController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$threads = Thread::latest()->get();
return view('threads.index', compact('threads'));
}

‘Latest’ is a method that adds an order by to the timestamp. The full list of available methods is here.

Authentication

Next we’re going to add authentication to the application. This will also generate layout view files in the resources directory.

$ php artisan make:auth
Authentication scaffolding generated successfully.
Default authentication system generated by Laravel. Full post on authentication available here.

Solve random error

For some reason I got an error when firing up the server: The only supported ciphers are AES-128-CBC and AES-256-CBC (#9080). If you encounter this error run the below commands:

$ php artisan key:generate
$ php artisan config:clear
$ php artisan serve

Create Threads View

Next we’ll generate a file for the threads view

$ mkdir resources/views/threads
$ touch resources/views/threads/index.blade.php

That view will inherit from the layout template and render the threads data using the blade template engine:

@extends('layouts.app')@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Forum Threads</div>
<div class="panel-body">
@foreach($threads as $thread)
<article>
<h4>{{ $thread->title }}</h4>
<div class='body'>
{{ $thread->body }}
</div>
</article>
<hr>
@endforeach
</div>
</div>
</div>
</div>
</div>
@endsection

We can then view the threads after we fire up the server: http://localhost:8000/threads

Show Single Thread

Add the route to routes/web.php:

Route::get('/threads/{thread}', 'ThreadController@show');

Then in app/Http/Controllers/ThreadController.php

/**
* Display the specified resource.
*
* @param \App\Thread $thread
* @return \Illuminate\Http\Response
*/
public function show(Thread $thread)
{
return $thread;
}

Using Route Model Binding this will automatically render JSON when we visit http://localhost:8000/threads/1.

JSON response for single Thread

In order to render a view we can update the return value:

public function show(Thread $thread)
{
return view('threads.show', compact('thread'));
}

Markup is in resources/views/threads/show.blade.php:

@extends('layouts.app')@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">{{ $thread->title }} </div>
<div class="panel-body">
{{ $thread->body }}
</div>
</div>
</div>
</div>
</div>
@endsection

Testing

For a Laravel 5.4 application, connection setting for our test database are in ./phpunit.xml.

<php>
<env name="APP_ENV" value="testing"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
</php>

We are going to use SQLite for the test database and our data will be stored in memory on our local machine.

To run tests use this command:

$ vendor/bin/phpunit

Then create a Threads test file in tests/Feature/ThreadsTest.php:

<?phpnamespace Tests\Feature;use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ThreadsTest extends TestCase
{
use DatabaseMigrations;
/** @test */
public function a_user_can_view_all_threads()
{
$thread = factory('App\Thread')->create();
$response = $this->get('/threads');
$response->assertSee($thread->title);
}
/** @test */
public function a_user_can_read_a_single_thread()
{
$thread = factory('App\Thread')->create();
$response = $this->get('/threads/' . $thread->id);
$response->assertSee($thread->title);
}
}

Add Links

Adding links is very straightforward:

<a href='/threads/{{$thread->id}}'>{{ $thread->title }}</a>

Alternatively, you can add a method to the Thread model in app/Thread.php:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Thread extends Model
{
public function path()
{
return '/threads/' . $this->id;
}
}

Then to generate the path to the url you could do:

<a href='{{ $thread->path() }}'>{{ $thread->title }}</a>

Either way works!

Employbl

Employbl is a database of active candidates in the Bay Area. I generate leads for talent teams

Connor Leech

Written by

Engineer, writer and community organizer. I built Employbl to help candidates get jobs in the Bay Area: https://employbl.com/

Employbl

Employbl

Employbl is a database of active candidates in the Bay Area. I generate leads for talent teams

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade