In this fourth part of creating WordPress-Like Blog using Laravel 5.6/5.7 and AdminLTE 3, we will :
- Replace the Static HTML data on the home screen with data from the posts table
- In the home screen, 0nly display the posts that has been published.
Firstly, we need to modify routes/web.php by adding the following route:
1 2 3 4 |
Route::get('/',[ 'uses' => 'BlogController@index', 'as' => 'blog', ]); |
Next, create BlogController :
1 |
php artisan make:controller BlogController |
The newly create BlogController.php will appear inside app/Http/Controllers folder.
Add public function index()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Post; class BlogController extends Controller { public function index(){ $posts = Post::all(); return view("blog.index", compact('posts')); } } |
Modify resources/views/blog/index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<h1 class="my-4">Page Heading <small>Secondary Text</small> </h1> @foreach($posts as $post) <!-- Blog Post --> <div class="card mb-4"> <img class="card-img-top" src="http://placehold.it/750x300" alt="Card image cap"> <div class="card-body"> <h2 class="card-title">Post Title</h2> <p class="card-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reiciendis aliquid atque, nulla? Quos cum ex quis soluta, a laboriosam. Dicta expedita corporis animi vero voluptate voluptatibus possimus, veniam magni quis!</p> <a href="#" class="btn btn-primary">Read More →</a> </div> <div class="card-footer text-muted"> Posted on January 1, 2017 by <a href="#">Start Bootstrap</a> </div> </div> @endforeach <!-- Pagination --> |
The posts will appear, but still have the same content. We need to do some changes.
Modify Post model and adding accessor public function getImageUrlAttribute :
1 2 3 4 5 6 7 8 9 10 11 |
public function getImageUrlAttribute($value){ $imageUrl = ""; if(!is_null($this->image)){ $imageUrl = $this->image; }else{ $imageUrl = ""; } return $imageUrl; } |
The accessor will initialise the imageUrl variable, and if the post has image, $imageUrl variable is the image url of the post.
Open Post model and create relationship to user model. Every post has author. We fetch the author from user table :
1 2 3 |
public function author(){ return $this->belongsTo(User::class); } |
Open User model and create relationship to post model. One user can create more than one post, and connected with author_id on post table :
1 2 3 |
public function posts(){ return $this->hasMany(Post::class,'author_id'); } |
Add with method to public function index BlogController, modify BlogController.php
1 2 3 4 5 6 7 |
public function index(){ $posts = Post::with('author') ->get(); return view("blog.index", compact('posts')); } |
Change the static date on the home screen using carbon diffForHumans method.
Open post model and create date accessor :
1 2 3 |
public function getDateAttribute($value){ return is_null($this->published_at) ? '' : $this->published_at->diffForHumans(); } |
Order by the latest post, create scopelatestFirst() in the Post.php model
1 2 3 |
public function scopeLatestFirst($query){ return $query->orderBy('created_at', 'desc'); } |
Open Post model and define the scope, to display the latest post first :
1 2 3 |
public function scopeLatestFirst($query){ return $query->orderBy('created_at', 'desc'); } |
Next, we will create a pagination. We can create it easily using laravel. Modify BlogController.php actionIndex :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class BlogController extends Controller { protected $limit = 5; public function index(){ $posts = Post::with('author') ->latestFirst() ->paginate($this->limit); return view("blog.index", compact('posts')); } } |
Modify resources/views/blog/index.php
1 2 3 4 |
<!-- Pagination --> <ul class="pagination justify-content-center mb-4"> {{ $posts->links() }} </ul> |
Afterwards, we will display only the post that has been published. We need to alter posts table by adding published_at column. Go to the terminal and type :
1 |
php artisan make:migration alter_posts_add_published_at_column --table=posts |
Open the newly create migration file and modify :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class AlterPostsAddPublishedAtColumn extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('posts', function (Blueprint $table) { $table->timestamp('published_at')->nullable(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('posts', function (Blueprint $table) { $table->dropColumn('published_at'); }); } } |
Modify poststableseeder.php and add published_at value :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<?php use Illuminate\Database\Seeder; use Faker\Factory; use Carbon\Carbon; class PostsTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { //reset posts table DB::table('posts')->truncate(); //generate 10 dummy posts $image = "http://placehold.it/750x300"; $posts = []; $faker = Factory::create(); $date = Carbon::create(2018, 7, 10, 11); for($i=1; $i<=10; $i++){ $date->addDays(1); $publishedDate = clone($date); $createdDate = clone($date); $posts[] = [ 'author_id' => rand(1,3), 'title' => $faker->sentence(rand(8,12)), 'excerpt' => $faker->text(rand(250,300)), 'body' => $faker->paragraphs(rand(10,15), true), 'slug' => $faker->slug(), 'image' => rand(0,1) == 1 ? $image : null, 'created_at' => $createdDate, 'updated_at' => $createdDate, 'published_at' => $i < 5 ? $publishedDate : ( rand(0,1) == 0 ? NULL : $publishedDate->addDays(4)), ]; } DB::table('posts')->insert($posts); } } |
Migrate and refresh the seed by typing this command inside the terminal :
1 |
php artisan migrate:refresh --seed |
Create scope published inside Post Model, and modify BlogController to add published posts only :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class BlogController extends Controller { protected $limit = 5; public function index(){ $posts = Post::with('author') ->latestFirst() ->published() ->paginate($this->limit); return view("blog.index", compact('posts')); } } |
1 2 3 |
public function scopePublished($query){ return $query->where("published_at", "<=", Carbon::now()); } |
Modify layouts/main.blade.php to add the route to Home :
1 2 3 4 5 |
<li class="nav-item active"> <a class="nav-link" href="{{ route('blog') }}">Home <span class="sr-only">(current)</span> </a> </li> |
To wrap things up, here are the files that we have changed:
app\Post.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Carbon\Carbon; class Post extends Model { protected $dates = ['published_at']; public function getImageUrlAttribute($value){ $imageUrl = ""; if(!is_null($this->image)){ $imageUrl = $this->image; }else{ $imageUrl = ""; } return $imageUrl; } public function author(){ return $this->belongsTo(User::class); } public function getDateAttribute($value){ return is_null($this->published_at) ? '' : $this->published_at->diffForHumans(); } public function scopeLatestFirst($query){ return $query->orderBy('created_at', 'desc'); } public function scopePublished($query){ return $query->where("published_at", "<=", Carbon::now()); } } |
app\Http\Controllers\BlogController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Post; class BlogController extends Controller { protected $limit = 5; public function index(){ $posts = Post::with('author') ->latestFirst() ->published() ->paginate($this->limit); return view("blog.index", compact('posts')); } } |
resources\views\blog\index.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
@extends('layouts.main') @section('content') <!-- Page Content --> <div class="container"> <div class="row"> <!-- Blog Entries Column --> <div class="col-md-8"> <h1 class="my-4"> </h1> @foreach($posts as $post) <!-- Blog Post --> <div class="card mb-4"> <img class="card-img-top" src="http://placehold.it/750x300" alt="Card image cap"> <div class="card-body"> <h2 class="card-title">{{ $post->title }}</h2> <p class="card-text">{{ $post->excerpt }}</p> <a href="#" class="btn btn-primary">Read More →</a> </div> <div class="card-footer text-muted"> Posted on {{ $post->date }} by <a href="#">{{ $post->author->name }}</a> </div> </div> @endforeach <!-- Pagination --> <ul class="pagination justify-content-center mb-4"> {{ $posts->links() }} </ul> </div> @include('layouts.sidebar') </div> <!-- /.row --> </div> <!-- /.container --> @endsection |
The result is as follows :
Github Commit.