Post Kategori dan Markdown
Di bagian keenam ini kita akan :
- Mengaktifkan Markdown Support
- Membuat Post kategori
Aktifkan Markdown Support
Markdown adalah markup languange yang ringan dengan sintaks teks. Markdown di desain sehingga bisa mudah dikonversi ke format HTML. Contoh markdown bisa dilihat di github.com pada bagian readme.md. Kita akan menggunakan markdown untuk digunakan di post body.
Untuk merubah markdown ke html, kita akan menggunakan LaravelMarkdown. Buka terminal dan perintahkan :
1 |
composer require graham-campbell/markdown |
Sesudah instalasi selesai, buka config/app.php dan masukkan dua baris berikut di bagian Providers dan Aliases :
1 2 3 |
GrahamCampbell\Markdown\MarkdownServiceProvider::class, 'Markdown' => GrahamCampbell\Markdown\Facades\Markdown::class, |
Buka show.blade.php, pada bagian $post->body, ubah menjadi seperti ini :
1 2 |
<!-- Post Content --> {!! $post->body_html !!} |
{!! !!}} artinya render langsung ke format HTML.
Tambahkan method berikut ke file app\Post.php
1 2 3 4 5 6 7 |
public function getBodyHtmlAttribute($value){ return $this->body ? Markdown::convertToHtml(e($this->body)) : NULL ; } public function getExcerptHtmlAttribute($value){ return $this->excerpt ? Markdown::convertToHtml(e($this->excerpt)) : NULL ; } |
Jangan lupa untuk menambahkan namespace :
1 |
use GrahamCampbell\Markdown\Facades\Markdown; |
Buka index.blade.php dan masukkan method excerpt_html juga:
1 |
<p class="card-text">{!! $post->excerpt_html !!}</p> |
Buka localhost:8000, jika tidak ada error berarti Anda sudah berhasil mengaktifkan Markdown support.
Post Kategori
Kita akan menambahkan master kategori dan menghubungkannya dengan post model.
Langkah 1, kita buat tabel categories.
1 |
php artisan make:migration create_categories --create=categories |
Buat migrasi untuk menambahkan kolom category_id pada tabel posts.
1 |
php artisan make:migration alter_posts_add_category_id --table=posts |
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 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class AlterPostsAddCategoryId extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('posts', function (Blueprint $table) { $table->integer('category_id')->unsigned(); $table->foreign('category_id')->references('id')->on('categories')->onDelete('restrict'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('posts', function (Blueprint $table) { $table->dropForeign(['category_id']); $table->dropColumn('category_id'); }); } } |
Buat new seeder, CategoriesTableSeeder :
1 |
php artisan make:seeder CategoriesTableSeeder |
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 48 49 |
<?php use Illuminate\Database\Seeder; class CategoriesTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { DB::table('categories')->truncate(); DB::table('categories')->insert([ [ 'title' => 'Web Design', 'slug' => 'web-design', ], [ 'title' => 'Web Programming', 'slug' => 'web-programming', ], [ 'title' => 'Internet', 'slug' => 'internet', ], [ 'title' => 'Digital Marketing', 'slug' => 'digital-marketing', ], [ 'title' => 'Social Media', 'slug' => 'social-media', ], ]); //update post data for($post_id =1; $post_id <= 10; $post_id++){ $category_id = rand(1,5); DB::table('posts') ->where('id',$post_id) ->update(['category_id'=>$category_id]); } } } |
Tambahkan CategoriesTableSeeder ke DatabaseSeeder.php :
1 2 3 4 5 6 |
public function run() { $this->call(UsersTableSeeder::class); $this->call(PostsTableSeeder::class); $this->call(CategoriesTableSeeder::class); } |
Selanjutnya, buka config/database.php dan ubah ‘strict’ ke false :
1 |
'strict' => false, |
Jalankan migrasi dan seed :
1 |
php artisan migrate:refresh --seed |
Buat kategori Model :
1 |
php artisan make:model Category |
Atur relasi antara post model, dan tambahkan getRouteKeyName untuk memfilter berdasarkan kategori nantinya.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Category extends Model { public function posts(){ return $this->hasMany(Post::class); } public function getRouteKeyName(){ return 'slug'; } } |
Buka Post model dan tambahkan relationship dengan model Category :
1 2 3 |
public function category(){ return $this->belongsTo(Category::class); } |
Selanjutnya, kita akan menampilkan kategori di sidebar. Sebelumnya kita perlu modifikasi BlogController method index() dan tambahkan method category(). Jangan lupa untuk menambahkan use App\Category.
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 |
public function index(){ $categories = Category::with(['posts' => function($query){ $query->published(); }]) ->orderBy('title','asc') ->get(); $posts = Post::with('author') ->latestFirst() ->published() ->paginate($this->limit); return view("blog.index", compact('posts','categories')); } public function category(Category $category){ $categoryName = $category->title; $categories = Category::with(['posts' => function($query){ $query->published(); }]) ->orderBy('title','asc') ->get(); $posts = $category->posts() ->with('author') ->latestFirst() ->published() ->paginate($this->limit); return view("blog.index", compact('posts','categories','categoryName')); } |
Tambahkan new route di routes/web.php
1 2 3 4 |
Route::get('/category/{category}',[ 'uses' => 'BlogController@category', 'as' => 'category' ]); |
Tambahkan widget untuk menampilkan kategori berikut di views/layouts/sidebar.blade.php
1 2 3 4 5 6 7 8 9 10 |
<div class="card my-4"> <h5 class="card-header">Categories</h5> <div> <ul class="list-group list-group-flush"> @foreach($categories as $category) <li class="list-group-item"><a href="{{ route('category', $category->slug)}}">{{ $category->title }} <span class="badge badge-pill badge-secondary float-right">{{ $category->posts->count() }}</span></a></li> @endforeach </ul> </div> </div> |
Sekarang kita akan menambahkan alert untuk memberikan informasi kita ada di kategori apa saat nama kategori di klik.
Modifikasi index.blade.php dan tambahkan alert :
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 48 49 50 51 52 53 54 55 56 57 58 59 60 |
@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> @if(!$posts->count()) <div class="alert alert-warning"> <p>Nothing Found</p> </div> @else @if(isset($categoryName)) <div class="alert alert-info"> <p>Category: <strong>{{ $categoryName }}</strong></p> </div> @endif @foreach($posts as $post) <!-- Blog Post --> <div class="card mb-4"> @if($post->image_url) <img class="card-img-top" src="{{ $post->image_url }}" alt="{{ $post->slug }}"> @endif <div class="card-body"> <h2 class="card-title"><a href="{{ route('blog.show', $post->slug) }}">{{ $post->title }}</a></h2> <p class="card-text">{!! $post->excerpt_html !!}</p> <a href="{{ route('blog.show', $post->slug) }}" class="btn btn-primary">Read More →</a> </div> <div class="card-footer text-muted"> Posted on {{ $post->date }} in category <a href="{{ route('category', $post->category->slug )}}">{{ $post->category->title }}</a> </div> </div> @endforeach @endif <!-- Pagination --> <ul class="pagination justify-content-center mb-4"> {{ $posts->links() }} </ul> </div> @include('layouts.sidebar') </div> <!-- /.row --> </div> <!-- /.container --> @endsection |
Apabila kita mengklik judul blog saat ini akan muncul error. Kita akan memodifikasi beberapa kode untuk mencegah error dan duplikasi kode. Kita akan menggunakan view composer provider untuk hal ini.
Buat provider baru :
1 |
php artisan make:provider ComposerServiceProvider |
Kode yang penting akan di load dari provider ini. Buka file provider yang baru kita buat di direktori App\providers, jangan lupa untuk menambahkan use App\Category :
1 2 3 4 5 6 7 8 9 10 |
public function boot() { view()->composer('layouts.sidebar', function($view){ $categories = Category::with(['posts' => function($query){ $query->published(); }])->orderBy('title','asc')->get(); return $view->with('categories',$categories); }); } |
Kita harus meregister provider ini di config/app.php
1 |
App\Providers\ComposerServiceProvider::class, |
Sekarang, rapikan BlogController.php sehingga menjadi seperti ini :
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 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Post; use App\Category; 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')); } public function category(Category $category){ $categoryName = $category->title; $posts = $category->posts() ->with('author') ->latestFirst() ->published() ->paginate($this->limit); return view("blog.index", compact('posts','categoryName')); } public function show(Post $post){ return view("blog.show", compact('post')); } } |
php artisan serve buka project, seharusnya tidak ada masalah.
Github Commit.
bug pada insert category DOException::(“SQLSTATE[HY000]: General error: 1364 Field ‘category_id’ doesn’t have a default value”)
sudah ketemu caranya?