Laravel 8 - #7 - Post Model dan Route Model Binding
Pada pembahasan kali ini kita akan membahas kembali mengenai model didalam Laravel, yang dimana akan kita perbaiki model `Post` kita yang sebelumnya dibuat secara manual, kali ini kita akan coba buat agar model nya dengan cara yang benar yaitu dengan merepresentasikan class model nya sebagai tabel didalam database. Hal tersebut nantinya kita juga harus membuat sebuah migrasi untuk tabel Post tersebut.
Arman Dwi Pangestu
24 Desember 2023•1 menit baca
Pendahuluan
Pada pembahasan kali ini kita akan membahas kembali mengenai model didalam Laravel, yang dimana akan kita perbaiki model Post
kita yang sebelumnya dibuat secara manual, kali ini kita akan coba buat agar model nya dengan cara yang benar yaitu dengan merepresentasikan class model nya sebagai tabel didalam database. Hal tersebut nantinya kita juga harus membuat sebuah migrasi untuk tabel Post tersebut.
Membuat Model Post Baru
Kalian bisa ubah nama file model Post.php
di folder app/Models
menjadi Post_.php
agar tersimpan history pembelajaran nya, selanjutnya kita buat model Post baru namun dengan cara menggunakan perintah php artisan
php artisan make:model Post
Nah, setelah membuat model nya kita juga perlu membuat migration nya untuk membuat skema tabel Post kita sehingga kita perlu membuat 2x. Namun, ada caranya agar kita dapat membuat model dan migration nya hanya dengan 1 perintah yaitu dengan perintah berikut ini
php artisan make:model -m Post
Maka sekarang akan muncul output di terimanl nya seperti berikut ini
Catatan:
Bisa kalian lihat, nama file migration nya sudah menjadi plural atau jamak
posts
sedangkan nama model nya yaitu singularPost
.
Model created successfully.
Created Migration: 2023_12_23_182552_create_posts_table
Setelah file model dan migration nya dibuat, sekarang kita ubah field yang akan disimpan di tabel Post kita dengan cara mengubah isian dari method up
pada file migration nya
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('excerpt');
$table->text('body');
$table->timestamp('publish_at')->nullable();
$table->timestamps();
});
}
Jika skema nya sudah siap, sekarang jalankan perintah berikut ini untuk memperbarui skema tabel nya
php artisan migrate:fresh
Mengisikan Data kedalam Tabel Post
Setelah tabel didalam database nya diperbarui, selanjutnya kita isikan data kedalam tabel post menggunakan Tinker
php artisan tinker
Setelah masuk kedalam shell tinker nya, sekarang buat instance object dari class Model nya dengan perintah
$post = new Post;
Selanjutnya kita isikan data object untuk masing-masing field nya
$post->title = 'Judul Pertama';
$post->excerpt = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus illo atque quod minus, iusto nam error fugiat delectus nobis ullam incidunt a corrupti inventore reprehenderit blanditiis quia tempora qui culpa eligendi quas sit animi? Ex, adipisci.';
$post->body = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus illo atque quod minus, iusto nam error fugiat delectus nobis ullam incidunt a corrupti inventore reprehenderit blanditiis quia tempora qui culpa eligendi quas sit animi? Ex, adipisci. Fuga laboriosam facilis ullam animi at maxime, quo recusandae libero architecto sapiente sed ut unde aliquam sit consequatur itaque necessitatibus dicta hic nobis sequi minus nam. Minus architecto quibusdam fugiat earum voluptatibus aliquid deleniti animi tenetur, rerum quod aliquam voluptate autem neque reiciendis adipisci velit, nulla, at amet beatae natus accusantium pariatur. Officia atque incidunt rerum optio, ut at dolorem ratione facilis voluptatibus corrupti!';
Ingat, perintha diatas hanya menyimpan data kedalam object namun belum tersimpan kedalam database nya, untuk menyimpan nya kita harus save terlebih dahulu dengan perintah
$post->save();
Sekarang buat post baru lagi dengan cara membuat instace baru
$post = new Post;
Misalkan data nya seperti ini
$post->title = 'Judul Kedua';
$post->excerpt = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere soluta quidem consequuntur a et, cupiditate officia consectetur! Molestias, molestiae.';
$post->body = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere soluta quidem consequuntur a et, cupiditate officia consectetur! Molestias, molestiae. Voluptas inventore eaque aut placeat ea sint esse voluptatem debitis nesciunt, eos consequuntur dignissimos sunt dolor, nihil veritatis, commodi soluta? Non vel quis omnis magnam eos ut, beatae laboriosam. Vero qui quas, cumque possimus illo deserunt rerum non quia nihil quibusdam doloremque cum repellat fugiat suscipit! Doloremque ducimus harum ipsam quisquam inventore itaque, voluptatibus aperiam sint non nulla cumque est tempora earum obcaecati mollitia perspiciatis, tenetur fugit eos natus modi sequi nemo odit exercitationem qui. Magni molestiae vitae dolorum aut voluptates?';
Dan kita save
$post->save();
Setelah data nya tersimpan, kita bisa langsung query menggunakan tinker dengan perintah
Jenis Jenis Query Collection
Post::all();
Maka akan muncul semua data nya
= Illuminate\Database\Eloquent\Collection {#7091
all: [
App\Models\Post {#7092
id: 1,
title: "Judul Pertama",
excerpt: "Lorem ipsum dolor sit amet, consectetur adipisicing elit. ...",
body: "...",
publish_at: null,
created_at: "2023-12-23 18:39:35",
updated_at: "2023-12-23 18:41:49",
},
App\Models\Post {#7093
id: 2,
title: "Judul Kedua",
excerpt: "Lorem ipsum dolor sit amet, consectetur adipisicing elit. ...",
body: "...",
publish_at: null,
created_at: "2023-12-23 18:42:22",
updated_at: "2023-12-23 18:42:22",
},
],
}
Atau hanya ingin menampilkan yang pertama saja
Post::first();
Hasil data nya
= App\Models\Post {#7095
id: 1,
title: "Judul Pertama",
excerpt: "Lorem ipsum dolor sit amet, consectetur adipisicing elit. ...",
body: "...",
publish_at: null,
created_at: "2023-12-23 18:39:35",
updated_at: "2023-12-23 18:41:49",
}
Atau jika kita ingin mencari postingan semuanya namun hanya judul nya saja, bisa menggunakan method pluck
Post::pluck('title');
Maka hasil data nya
= Illuminate\Support\Collection {#7091
all: [
"Judul Pertama",
"Judul Kedua",
],
}
Atau ingin mencari postingan yang id nya 2
Post::find(2);
Maka hasilnya
= App\Models\Post {#6142
id: 2,
title: "Judul Kedua",
excerpt: "Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
body: "...",
publish_at: null,
created_at: "2023-12-23 18:42:22",
updated_at: "2023-12-23 18:42:22",
}
Penjelasan Mengapa Tidak Error
Sekarang jika kalian kembali ke halaman /posts
maka tidak akan muncul error padahal kita tidak mengubah view, routes dan controller nya. Ajaib bukan? padahal jika kita lihat pada model Post nya tidak mempunyai method all
dan method find
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
}
Tidak seperti model yang kita buat sebelumnya yang sudah di rename menjadi Post_.php
<?php
namespace App\Models;
class Post
{
private static $blog_posts = [
...
];
public static function all()
{
return collect(self::$blog_posts);
}
public static function find($slug)
{
$posts = static::all();
return $posts->firstWhere('slug', $slug);
}
}
Mengapa bisa seperti itu? karena method all
dan find
sudah ada di Laravel, sehingga method all
dan find
pada Controller Post nya bisa berjalan
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
return view('posts', [
"title" => "Posts",
"posts" => \App\Models\Post::all()
]);
}
public function show($slug)
{
return view('post', [
'title' => 'Single Post',
'post' => \App\Models\Post::find($slug)
]);
}
}
Modifikasi Views Posts
Namun disini method show
nya tidak berjalan karena method find
bukan mencari berdasarkan slug melainkan mencari berdasarkan id, kita coba benarkan pada file views posts.blade.php
agar link anchor nya mengarah ke id
@extends('layouts.main')
@section('container')
@foreach ($posts as $post)
...
<h2>
<a href="/posts/{{ $post['id'] }}">{{ $post['title'] }}</a>
</h2>
...
@endforeach
@endsection
Maka sekarang single page post nya akan berjalan kembali namun berdasarkan id nya bukan slug nya
Selanjutnya kita tidak akan lagi menggunakan notasi array $post['id']
untuk mengakses data pada variable nya, namun kita akan menggunakan notasi object $post->id
. Mengapa pada view tersebut jalan ketika menggunakan notasi array? karena collection itu memungkinkan kita bisa mengakses menggunakan kedua notasi tersebut.
Sehingga sekarang bisa kita ubah menjadi notasi object dengan menggunakan panah ->
, maka sekarang isian dari file view posts.blade.php
nya seperti berikut ini
@extends('layouts.main')
@section('container')
@foreach ($posts as $post)
<article class="mb-5">
<h2>
<a href="/posts/{{ $post->id }}">{{ $post->title }}</a>
</h2>
<h5>By: {{ $post->author }}</h5>
<p>{{ $post->excerpt }}</p>
</article>
@endforeach
@endsection
Modifikasi Views Post atau Single Page Post
Jika kalian perhatikan pada file view single page post post.blade.php
, penulisan data dari body
post nya kita simpan pada tag element <p>
. Nah, mungkin saja kedepannya postingan yang dikirim itu beberapa paragraf (mungkin panjang). Sehingga, sangat memungkinkan tag element <p>
tersebut berada didalam data body
nya
@extends('layouts.main')
@section('container')
...
<p>{{ $post['body'] }}</p>
...
@endsection
Nah, jika sekarang kan isian dari body
nya itu hanya seperti berikut ini
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere soluta quidem
consequuntur a et, cupiditate officia consectetur! Molestias, molestiae.
Voluptas inventore eaque aut placeat ea sint esse voluptatem debitis nesciunt,
eos consequuntur dignissimos sunt dolor, nihil veritatis, commodi soluta? Non
vel quis omnis magnam eos ut, beatae laboriosam. Vero qui quas, cumque possimus
illo deserunt rerum non quia nihil quibusdam doloremque cum repellat fugiat
suscipit! Doloremque ducimus harum ipsam quisquam inventore itaque, voluptatibus
aperiam sint non nulla cumque est tempora earum obcaecati mollitia perspiciatis,
tenetur fugit eos natus modi sequi nemo odit exercitationem qui. Magni molestiae
vitae dolorum aut voluptates?
Mungkin saja isian dari body kedepannya seperti ini, mungkin nantinya kedepannya kita menggunakan tools WYSIWYG (What You See What You Get)
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Officiis, eius sint
tempora, et alias tenetur saepe ipsa nihil temporibus nemo ipsum quas
repellendus nulla tempore quaerat a vitae nam. Harum vitae cum, quas
doloremque vero esse dicta tempora, quidem suscipit ad temporibus quibusdam
impedit adipisci nemo, officia voluptas. Dolorum, delectus consequuntur
impedit cupiditate cumque quibusdam dicta sed maxime in accusamus laboriosam
magnam odio facere amet iure sit nisi incidunt numquam non blanditiis
exercitationem dolorem voluptatibus architecto.
</p>
<p>
Repudiandae reiciendis nisi dolore deserunt exercitationem vitae perferendis,
minima accusantium amet. Animi, quia eius? Hic assumenda ipsum numquam
repudiandae? Sapiente, quae ea atque ab iste aperiam harum! Expedita
reprehenderit temporibus doloremque? Modi harum nobis deleniti laudantium
aspernatur repellat corrupti nostrum vitae voluptatibus. At, ut.
</p>
Sehingga bisa kita hilangkan tag <p>
pada view nya, sekalian kita ubah juga format penulisan nya dari array menjadi object seperti berikut ini.
@extends('layouts.main')
@section('container')
<article>
<h2>{{ $post->title }}</h2>
<h5>By: {{ $post->author }}</h5>
{{ $post->body }}
</article>
<a href="/posts">Back to Posts</a>
@endsection
Membuat Data Post Baru
Sekarang kita coba membuat data post baru menggunakan tinker namun pada bagian body nya kita sisipkan tag element html seperti <p>
kira-kira apa yang akan terjadi.
$post = new Post;
$post->title = 'Judul Post Ketiga';
$post->excerpt = 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Officiis, eius sint';
$post->body = '<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Officiis, eius sint tempora, et alias tenetur saepe ipsa nihil temporibus nemo ipsum quas repellendus nulla tem
pore quaerat a vitae nam. Harum vitae cum, quas doloremque vero esse dicta tempora, quidem suscipit ad temporibus quibusdam impedit adipisci nemo, officia voluptas. Dolorum, delectus conse
quuntur impedit cupiditate cumque quibusdam dicta sed maxime in accusamus laboriosam magnam odio facere amet iure sit nisi incidunt numquam non blanditiis exercitationem dolorem voluptatib
us architecto.</p><p>Repudiandae reiciendis nisi dolore deserunt exercitationem vitae perferendis, minima accusantium amet. Animi, quia eius? Hic assumenda ipsum numquam repudiandae? Sapie
nte, quae ea atque ab iste aperiam harum! Expedita reprehenderit temporibus doloremque? Modi harum nobis deleniti laudantium aspernatur repellat corrupti nostrum vitae voluptatibus. At, ut
.</p>';
$post->save();
Nah, sekarang jika kalian pergi ke single page post untuk postingan yang ketiga. Alih-alih tag nya berjalan, tag <p>
nya malah ikut ter-render seperti text biasa, kita tidak mau dong hal tersebut terjadi.
Hal tersebut mengapa terjadi? itu karena Laravel mencoba mengamankan isian dari variabel kita di dalam string blade ini
{{ $post->body }}
Notasi double curly braces atau dua kurung kurawal tersebut artinya blade akan mencetak menggunakan php echo
sekaligus menjalankan method atau function htmlspecialchars
. Sehingga, jika didalam nya terdapat tag html, function tersebut akan meng-escape.
Jika hal tersebut tidak kita inginkan atau kita pengen menampilkan tag nya sesuai fungsi nya bukan di render seperti text biasa, kita jangan gunakan format penulisan bladde {{ }}
tetapi kita bisa gunakan format penulisan blade nya seperti berikut ini
Catatan: Penting!
Format penulisan
{!! !!}
harus dilakukan dengan hati-hati dan pastikan input-an yang dimasukan itu bebas dari script yang aneh-aneh.
{!! $post->body !!}
Format penulisan {!! !!}
tersebut artinya kita tidak akan melakukan escape karatkter, sehingga sekarang tag <p>
nya akan tampil sebagai mestinya.
Membuat Data Post Baru Menggunakan Method Create
Nah, pada sebelumnya kita membuat sebuah data pada tinker kita menjalankan perintah seperti berikut
$post = new Post;
$post->title
$post->excerpt
$post->body
$post->save();
Kita bisa gunakan metode lain yaitu dengan cara menggunakan method create
seperti berikut
Post::create([
'title' => 'Judul Ke Empat',
'excerpt' => 'orem ipsum dolor sit amet consectetur adipisicing elit. Soluta quia, aliquid harum, facere optio fugit officia ad',
'body' => '<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Soluta quia, aliquid harum, facere optio fugit officia ad, animi iste eligendi dicta quam itaque consectetur magnam voluptates? Facilis, ipsum sapiente beatae suscipit fugiat quaerat necessitatibus accusamus.</p> <p>Illum voluptatum, reprehenderit animi iure labore itaque iusto assumenda voluptatibus dolorum vel deleniti illo ipsum obcaecati consequuntur cupiditate? Odio laboriosam officia hic aut esse delectus fugiat, recusandae at itaque nostrum dolor quo dolorem nesciunt tenetur ea neque vel sunt error quod exercitationem facere ex cum? Sint velit nihil quia veritatis corrupti! Vel ratione repudiandae libero aut excepturi in magni.</p> <p>Est, similique molestias culpa aliquam maiores perferendis placeat nulla iusto, optio deserunt magnam quae. Culpa exercitationem reiciendis omnis quod quia aliquid expedita at, doloribus nemo impedit unde quasi provident repellendus voluptate, asperiores quidem commodi laudantium. Fugiat aliquid culpa laborum aspernatur aliquam nam, debitis assumenda iusto vel dolore impedit dolor veritatis blanditiis. Sunt fugit sed in dolores?</p>',
]);
Nah jika kita mencoba menjalankan perintah pada tinker diatas, kita akan mendapatkan sebuah error message yaitu Mass Assignment Exception
Illuminate\Database\Eloquent\MassAssignmentException Add [title] to fillable property to allow mass assignment on [App\Models\Post].
Hal tersebut terjadi karena Laravel sudah menangani nya, sehingga tidak boleh banyak property sekaligus langung dimasukan kedalam tabel seperti perintah tersebut, default nya tidak boleh atau dijagain.
Cara untuk mengatasi nya, kita harus membuat sebuah property yang namanya fillable
didalam model Post
, sekarang kita bisa tambahkan property berikut ini didalam model Post nya
Catatan:
Jika kita tidak tulis yang tidak masuk kedalam property
fillable
tersebut, maka field tersebut tidak bisa diisi menggunakancreate
dan nantinya akan otomatis diisi sesuai dengan apa yang kita buat didalam skema atau file migration (jika mempunyai nilai default, maka akan menggunakan nilai tersebut, jika timestamps maka akan menggunakan nilai waktu ketika data tersebut dibuat)
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = ['title', 'excerpt', 'body'];
}
Jika sudah, sekarang kita bisa jalankan kembali method create
nya di tinker namun harus di reset terlebih dahulu session nya dengan cara keluar dari shell nya kemudian masuk kembali lagi dan jalankan method create nya. Maka sekarang akan berhasil mengisikan data menggunakan create (tidak lagi terkena error Exception Mass Assignment)
[!] Aliasing 'Post' to 'App\Models\Post' for this Tinker session.
= App\Models\Post {#6140
title: "Judul Ke Empat",
excerpt: "orem ipsum dolor sit amet consectetur adipisicing elit. Soluta quia, aliquid harum, facere optio fugit officia ad",
body: "<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Soluta quia, aliquid harum, facere optio fugit officia ad, animi iste eligendi dicta quam itaque consectetur magnam voluptates? Facilis, ipsum sapiente beatae suscipit fugiat quaerat necessitatibus accusamus.</p> <p>Illum voluptatum, reprehenderit animi iure labore itaque iusto assumenda voluptatibus dolorum vel deleniti illo ipsum obcaecati consequuntur cupiditate? Odio laboriosam officia hic aut esse delectus fugiat, recusandae at itaque nostrum dolor quo dolorem nesciunt tenetur ea neque vel sunt error quod exercitationem facere ex cum? Sint velit nihil quia veritatis corrupti! Vel ratione repudiandae libero aut excepturi in magni.</p> <p>Est, similique molestias culpa aliquam maiores perferendis placeat nulla iusto, optio deserunt magnam quae. Culpa exercitationem reiciendis omnis quod quia aliquid expedita at, doloribus nemo impedit unde quasi provident repellendus voluptate, asperiores quidem commodi laudantium. Fugiat aliquid culpa laborum aspernatur aliquam nam, debitis assumenda iusto vel dolore impedit dolor veritatis blanditiis. Sunt fugit sed in dolores?</p>",
updated_at: "2023-12-23 19:43:12",
created_at: "2023-12-23 19:43:12",
id: 4,
}
Maka sekarang total post nya terdapat 4 buah data
Perbedaan Property Fillable dan Guarded
Nah, jadi harus ditulis field-field mana saja yang fillable
atau property yang boleh diisi. Namun, sebetulnya ada kebalikan dari fillable
jika kalian tidak ingin menambahkan satu-satu field-field nya yaitu guarded
Misalkan, field id
yang ingin dijagain dan sisanya boleh diisi
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
// protected $fillable = ['title', 'excerpt', 'body'];
protected $guarded = ['id'];
}
Sehingga dapat kita simpulkan
fillable
: ini yang boleh diisi, sisanya tidak bolehguarded
: ini yang tidak boleh diisi, sisanya boleh
Silahkan kalian pilih mau pakai yang mana, kedua property tersebut nantinya akan berguna jika ingin melakukan Mass Assignment yang lain (selain dari create
), misalkan kita ingin update
. Nah update
juga merupakan sebuah Mass Assigment, sehingga jika kita menjalankan perintah seperti berikut ini
Post::find(3)->update(['title' => 'Judul Ketiga Berubah']);
Nah hal tersebut bisa berjalan, karena kita hanya tidak memperbolehkan field id
saja yang tidak boleh diubah
protected $guarded = ['id'];
Maka sekarang jika kalian lihat data ketiga, title nya berubah menjadi Judul Ketiga Berubah
Post::all();
...
App\Models\Post {#7105
id: 3,
title: "Judul Ketiga Berubah",
excerpt: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Officiis, eius sint",
body: "...",
publish_at: null,
created_at: "2023-12-23 19:19:38",
updated_at: "2023-12-23 19:54:52",
},
...
Atau misalkan kita coba ubah menggunakan metode lain yaitu where
Catatan:
Method
find
jika diartikan pada raw SQL adalahWHERE id = ...
nah jika methodwhere
jika diartikan pada raw SQL bisa berubah ubah bukan hanyaid
atau pakai yang lain sepertititle
Post::where('title', 'Judul Ketiga Berubah')->update(['excerpt' => 'excerpt postingan ketiga berubah']);
Jika perintah diatas dijalankan maka akan muncul output
= 1
Artinya terdapat 1 data yang berubah dan jika kita kembali kehalaman /posts
nya maka data nya akan seperti berikut ini
Route Model Binding
Jika dikutip dari dokumentasi resmi Laravel nya. "Pada saat kita menyuntikkan sebuah id dari model kita kedalam route kita atau kedalam controller, yang biasanya kita lakukan adalah query record yang kita cari berdasarkan id tadi. Nah Laravel mempunyai sebuah fitur yang namanya Route Model Binding yang tugasnya meng-skip apa yang kita lakukan tadi, sehingga Laravel nya akan langsung melakukan query in agar supaya dapat langsung data sesuai dengan apa yang kita cari tadi, tanpa harus kirimin id terus kita query sendiri atau mengirimkan instance dari model yang sesuai"
Implementasi Route Model Binding
Catatan:
Penulisan type hinting ini harus kalian perhatikan, misalkan yang kalian tulis pada property parameter anonymous function nya adalah
$user
, maka harus sama persis dengan apa yang kalian tulis pada route nya/users/{user}
(tidak boleh berbeda)
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
return $user->email;
});
Pada saat kita akan mendapatkan sesuatu dari URL kita, biasanya kan kita tulis /users/{id}
atau /users/{slug}
(kita kirimin willcard nya). Nah kalo sekarang kita langsung aja panggil instance nya, kalo kita ngirimin nya post kita kirim nya post di /.../{disini}
atau kalo ngirim nya user
langsung kita kirim /users/{user}
tidak usah id
atau slug
lagi.
Tapi didalam parameter anonymous function nya kita langsung kasih type hinting nya atau tipe data nya bahwa dia itu adalah model yang namanya user function (User $user)
Jika kita lihat sekarang kode dari PostController.php
nya
public function show($slug)
{
return view('post', [
'title' => 'Single Post',
'post' => \App\Models\Post::find($slug)
]);
}
Yang kita cari adalah slug, namun method find
yang dicari adalah id
sehingga bisa kita ubah menjadi
public function show($id)
{
return view('post', [
'title' => 'Single Post',
'post' => \App\Models\Post::find($id)
]);
}
Nah, method tersebut artinya kita melakukan query terlebih dahulu, ambil id
nya lalu query menggunakan method find
. Nah, sekarang kita bisa tidak melakukan hal tersebut dengan cara mengubah file routes nya di web.php
Route::get('posts/{post}', [PostController::class, 'show']);
Nah sekarang di route nya, parameter yang ditangkap bukan lagi id
melainkan post
sehingga kode nya menjadi seperti berikut ini
public function show(Post $post)
{
return view('post', [
'title' => 'Single Post',
'post' => $post
]);
}
Post $post
artinya kita ikat karena namanya juga Route Model Binding, jadi routes nya tadi mengirimkan model ke method show
lalu di ikat di Post $post
. Sehingga yang dikirimkan kedalam view nya tidak perlu lagi melakukan query dengan method find
namun bisa langsung jadi $post
.
Nah, hal tersebut memungkinkan kita untunk mengirimkan data bukan lagi id
pada url nya. Karena jika id
takutnya nanti ditebak atau diakses secara paksa.
Penambahan Slug Pada Skema Tabel Post
Kita buka kembali file migrations untuk tabel post nya, kemudian tambahkan field slug
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('slug')->unique();
$table->string('author');
$table->text('excerpt');
$table->text('body');
$table->timestamp('publish_at')->nullable();
$table->timestamps();
});
}
Setelah skema database diperbarui, kita lakukan lagi migrate:fresh
untuk menerapkan skema terbaru
php artisan migrate:fresh
Sekarang masuk kembali kedalam shell Tinker
nya
php artisan tinker
Kemudian isikan kembali data postingan nya
Post::create([
'title' => 'Judul Pertama',
'slug' => 'judul-pertama',
'author' => 'Arman Dwi Pangestu',
'excerpt' => 'Lorem ipsum pertama',
'body' => '<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Soluta quia, aliquid harum, facere optio fugit officia ad, animi iste eligendi dicta quam itaque consectetur magnam voluptates? Facilis, ipsum sapiente beatae suscipit fugiat quaerat necessitatibus accusamus.</p> <p>Illum voluptatum, reprehenderit animi iure labore itaque iusto assumenda voluptatibus dolorum vel deleniti illo ipsum obcaecati consequuntur cupiditate? Odio laboriosam officia hic aut esse delectus fugiat, recusandae at itaque nostrum dolor quo dolorem nesciunt tenetur ea neque vel sunt error quod exercitationem facere ex cum? Sint velit nihil quia veritatis corrupti! Vel ratione repudiandae libero aut excepturi in magni.</p> <p>Est, similique molestias culpa aliquam maiores perferendis placeat nulla iusto, optio deserunt magnam quae. Culpa exercitationem reiciendis omnis quod quia aliquid expedita at, doloribus nemo impedit unde quasi provident repellendus voluptate, asperiores quidem commodi laudantium. Fugiat aliquid culpa laborum aspernatur aliquam nam, debitis assumenda iusto vel dolore impedit dolor veritatis blanditiis. Sunt fugit sed in dolores?</p>',
]);
Post::create([
'title' => 'Judul Ke Dua',
'slug' => 'judul-ke-dua',
'author' => 'Arman Dwi Pangestu',
'excerpt' => 'Lorem ipsum ke dua',
'body' => '<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Soluta quia, aliquid harum, facere optio fugit officia ad, animi iste eligendi dicta quam itaque consectetur magnam voluptates? Facilis, ipsum sapiente beatae suscipit fugiat quaerat necessitatibus accusamus.</p> <p>Illum voluptatum, reprehenderit animi iure labore itaque iusto assumenda voluptatibus dolorum vel deleniti illo ipsum obcaecati consequuntur cupiditate? Odio laboriosam officia hic aut esse delectus fugiat, recusandae at itaque nostrum dolor quo dolorem nesciunt tenetur ea neque vel sunt error quod exercitationem facere ex cum? Sint velit nihil quia veritatis corrupti! Vel ratione repudiandae libero aut excepturi in magni.</p> <p>Est, similique molestias culpa aliquam maiores perferendis placeat nulla iusto, optio deserunt magnam quae. Culpa exercitationem reiciendis omnis quod quia aliquid expedita at, doloribus nemo impedit unde quasi provident repellendus voluptate, asperiores quidem commodi laudantium. Fugiat aliquid culpa laborum aspernatur aliquam nam, debitis assumenda iusto vel dolore impedit dolor veritatis blanditiis. Sunt fugit sed in dolores?</p>',
]);
Post::create([
'title' => 'Judul Ke Tiga',
'slug' => 'judul-ke-tiga',
'author' => 'Arman Dwi Pangestu',
'excerpt' => 'Lorem ipsum ke tiga',
'body' => '<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Soluta quia, aliquid harum, facere optio fugit officia ad, animi iste eligendi dicta quam itaque consectetur magnam voluptates? Facilis, ipsum sapiente beatae suscipit fugiat quaerat necessitatibus accusamus.</p> <p>Illum voluptatum, reprehenderit animi iure labore itaque iusto assumenda voluptatibus dolorum vel deleniti illo ipsum obcaecati consequuntur cupiditate? Odio laboriosam officia hic aut esse delectus fugiat, recusandae at itaque nostrum dolor quo dolorem nesciunt tenetur ea neque vel sunt error quod exercitationem facere ex cum? Sint velit nihil quia veritatis corrupti! Vel ratione repudiandae libero aut excepturi in magni.</p> <p>Est, similique molestias culpa aliquam maiores perferendis placeat nulla iusto, optio deserunt magnam quae. Culpa exercitationem reiciendis omnis quod quia aliquid expedita at, doloribus nemo impedit unde quasi provident repellendus voluptate, asperiores quidem commodi laudantium. Fugiat aliquid culpa laborum aspernatur aliquam nam, debitis assumenda iusto vel dolore impedit dolor veritatis blanditiis. Sunt fugit sed in dolores?</p>',
]);
Mengganti Id Menjadi Slug Pada Route Single Post
Untuk mengganti nya kita bisa ubah anchor link pada file view posts.blade.php
nya agar mengarah atau menggunakan slug
<a href="/posts/{{ $post->slug }}">{{ $post->title }}</a>
Sekarang jika kalian hover preview link nya sudah mengarah atau menggunakan slug, namun jika kalian mencoba membuka nya maka akan error karena masih mencari berdasarkan id
Bagaimana cara mengatasi agar pencarian nya menjadi menggunakan slug bukan id? nah cara nya cukup mudah, kalian buka kembali file routes web.php
nya.
Route::get('posts/{post}', [PostController::class, 'show']);
Jika kalian menggunakan wildcard nya adalah {post}
, maka default nya akan mencari berdasarkan id
sebagai unique identifier nya. Namun jika penulisan nya adalah {post:slug}
Route::get('posts/{post:slug}', [PostController::class, 'show']);
Maka sekarang pencarian query nya akan berdasarkan slug
nya untuk mendapatkan post yang unique nya. Sehingga jika kita simpulkan
- Jika menggunakan
{post}
=WHERE id = ...
- Jika menggunakan
{post:slug}
=WHERE slug = ...