Laravel 8 - #5 - Model, Collection dan Controller
Aplikasi yang sudah dibangun sebelumnya itu semua proses nya masih ditangani komponen `routes` kita, contohnya ketika kita melakukan request ke halaman `/posts` untuk menampilkan semua data dari blog post kita dilakukan di dalam routes, begitu pula dengan proses menampilkan halaman views, itu juga dilakukan di dalam routes. Hal tersebut tidak tepat, karena jika kita ingin menerapkan konsep MVC (Model, View, Controller) maka 2 proses tersebut seharusnya kita pisahkan sesuai dengan komponen nya.
Arman Dwi Pangestu
22 Desember 2023•1 menit baca
Pendahuluan
Aplikasi yang sudah dibangun sebelumnya itu semua proses nya masih ditangani komponen routes
kita, contohnya ketika kita melakukan request ke halaman /posts
untuk menampilkan semua data dari blog post kita dilakukan di dalam routes, begitu pula dengan proses menampilkan halaman views, itu juga dilakukan di dalam routes. Hal tersebut tidak tepat, karena jika kita ingin menerapkan konsep MVC (Model, View, Controller) maka 2 proses tersebut seharusnya kita pisahkan sesuai dengan komponen nya.
Misalkan jika kita ingin bekerja atau berhubungan dengan data, maka kita harus menyimpan kode nya di dalam komponen Model
. Dan jika terdapat sebuah proses seperti memilih, menampilkan views, maka kita harus menyimpan kode nya di dalam komponen Controller
.
Maka pada bagian ini, kita akan coba menerapkan konsep MVC dengan cara memisahkan kode nya ke dalam komponen-komponen yang terpisah. Sehingga nantinya kita akan belajar membuat model dan controller dan bagaimana cara menggabungkan ketiga komponen MVC tersebut.
Dan sedikit ada perubahan nama route pada aplikasi sebelumnya dari route /blog
menjadi /posts
di file routes/web.php
Route::get('/blog', function () {
...
});
Menjadi
Route::get('/posts', function () {
...
});
Kemudian navbar anchor link nya juga di file resources/views/partials/navbar.blade.php
<a class="nav-link {{ ($title === 'Posts' ? 'active' : '') }}" href="/blog">Blog</a>
Menjadi
<a class="nav-link {{ ($title === 'Posts' ? 'active' : '') }}" href="/posts">Blog</a>
Dan yang terakhir adalah anchor link pada single post di file /resources/views/post.blade.php
<a href="/blog">Back to Posts</a>
Menjadi
<a href="/posts">Back to Posts</a>
3 Cara Pembuatan Model
Terdapat 3 cara untuk pembuatan Model di aplikasi Laravel kita, berikut ada 3 cara untuk membuat Model pada aplikasi Laravel
PHP Artisan: Membuat Model
Untuk membuat sebuah model pada aplikasi Laravel kita, kita bisa menggunakan perintah PHP Artisan dengan cara seperti berikut ini di terminal kalian
php artisan make:model NamaModel
Membuat Model Manual
Kalian juga bisa membuat model secara manual dengan cara membuat file pada folder app/Models
Membuat Model menggunakan Extension Laravel Artisan
Jika kalian sudah menginstall extension nya, kalian bisa membuat sebuah model dengan menggunakan command palette milik nya Visual Studio Code. Caranya kalian cukup tekan CTRL
+ P
kemudian ketikan Artisan: Make Model
Pembuatan Model Untuk Data Blog Post
Sebelumnya kita menyimpan data blog post di lokasi routes nya, nah cara tersebut sebetulnya tidak tepat dan tidak efisien (karena kita menduplikat variable tersebut pada route single post nya). Untuk mengatasi hal tersebut, kita disini akan mencoba memindahkan data blog post tersebut kedalam sebuah model.
Kita akan memilih pembuatan model menggunakan cara PHP Artisan
yang dimana akan menjalankan artisan melalui aplikasi Terminal. Maka disini kita jalankan dengan perintah seperti berikut ini
php artisan make:model Post
Maka sekarang terdapat sebuah file baru di folder app/Models
dengan nama file nya adalah Post.php
. Pada model tersebut terdapat sebuah kode
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
yang dimana berfungsi untuk nantinya terhubung kedalam database, namun karena kita belum butuh maka bisa kita hapus dan extends pada Class Model
nya juga bisa kita hapus
Sehingga sekarang isi dari file model Post.php
tersebut seperti berikut ini
<?php
namespace App\Models;
class Post
{
}
Pemindahan Data Posts Dari Routes Kedalam Model
Selanjutnya kita coba cut atau ambil data $blog_posts
dari route /posts
agar disimpan di Model Post.php
dengan access modifier private dan juga static
maka sekarang isi file Post.php
seperti berikut ini
<?php
namespace App\Models;
class Post
{
private static $blog_posts = [
[
'title' => 'Judul Post Pertama',
'slug' => 'judul-post-pertama',
'author' => 'Arman Dwi Pangestu',
'body' => 'Lorem ipsum dolor sit, amet consectetur adipisicing elit. Quasi aliquid perspiciatis possimus. Quae sapiente molestiae perferendis ut dolorum illum fugit corrupti! Ratione pariatur quis odio! Explicabo quo incidunt velit aliquam iure, doloribus natus molestiae ab officiis, ea distinctio fugit dolores eos quam magni aliquid libero nihil ex iusto unde? Voluptates!'
],
[
'title' => 'Judul Post Kedua',
'slug' => 'judul-post-kedua',
'author' => 'Sandhika Galih',
'body' => 'Lorem, ipsum dolor sit amet consectetur adipisicing elit. Delectus, nobis qui. Officia eius, debitis eveniet nisi culpa quas, voluptate enim impedit ipsa corrupti sapiente nesciunt mollitia facilis at cumque laudantium.'
]
];
}
Menghubungkan Routes Dengan Model
Dan isi dari route /posts
nya menjadi seperti berikut ini
Catatan:
Jika kalian mendapatkan error pada Class
Post
nya, maka kalian harus melakukan import Class nya pada bagian paling atas file dengan perintah berikut ini:use App\Models\Post;
Jika kalian ingin mempermudah masalah import namespace tersebut, kalian bisa install Extension VSCode yang namanaya
PHP Namespace Resolver
. Extension tersebut jika kita melakukan klik kanan pada VSCode maka kita bisa melakukanImport All Classes
, sehingga jika ada Class yang error karena namespace nya tidak diload, dengan extension tersbeut akan otomatis terimport semua namespace nya.Method
all()
juga disini belum kita buat, sehingga pasti akan muncul error
Route::get('/posts', function () {
return view('posts', [
"title" => "Posts",
"posts" => Post::all()
]);
});
Setelah routes dan model nya terhubung, sekarang kita buat method all()
nya di Class Post
atau Model nya seperti berikut ini
Catatan: Tips Object Oriented Programming!
Dikarenakan disini property
$blog_posts
nya adalahstatic
maka kita harus menggunakan keywordself::$property
, namun jika property nya biasa maka kita menggunakan keyword$this->property
.
<?php
namespace App\Models;
class Post
{
private static $blog_posts = [
...
];
public static function all()
{
return self::$blog_posts;
}
}
Pemindahan Data Single Post Blog Agar Menggunakan Data Dari Model
Nah, pemindahan data dari routes ke model sudah selesai, jika kalian melakukan refresh pada web browser dengan routes /posts
maka tidak akan muncul error, namun jika kalian masuk ke dalam single post nya, data nya masih menggunakan data dari routes nya (bukan dari model).
Selanjutnya kita akan ubah juga agar data dari single post menggunakan data dari model nya. Sekarang ubah route single page atau route slug nya menjadi seperti berikut ini
// Halaman Single Post
Route::get('posts/{slug}', function ($slug) {
return view('post', [
'title' => 'Single Post',
'post' => Post::find($slug)
]);
});
Selanjutnya kita buat sebuah method static lagi dengan nama method nya adalah find()
di Model Post
nya
<?php
namespace App\Models;
class Post
{
private static $blog_posts = [
...
];
public static function all()
{
return self::$blog_posts;
}
public static function find($slug)
{
$posts = self::$blog_posts;
$post = [];
foreach ($posts as $p) {
if ($p['slug'] === $slug) {
$post = $p;
}
}
return $post;
}
}
Maka sekarang data dari view single post nya sudah mengambil dari Model yang sudah kita buat dan kode pada bagian routes nya juga sudah menjadi rapih (tidak ada data, karena data memang seharusnya di tempatkan pada komponen model).
Collection Pada Laravel
Kita bisa ubah data yang kita ambil agar menjadi sesuatu yang disebut dengan collection di Laravel. Apa itu Collection
? Collection sebetulny adalah pembungkus untuk sebuah Array, yang akan membuat Array menjadi lebih sakti.
Maksudnya bagaimana? lihat kode pada bagian mode berikut ini
private static $blog_posts = [
[
'title' => 'Judul Post Pertama',
'slug' => 'judul-post-pertama',
...
],
[
'title' => 'Judul Post Kedua',
'slug' => 'judul-post-kedua',
...
]
];
public static function all()
{
return self::$blog_posts;
}
Pada data model tersebut, kita mempunyai sebuah array di dalam array, ada array numeric yang didalamnya ada array associative. Nah kita akan membungkus array tersebut agar menjadi sebuah Collection.
Jika pada dokumentasi Laravel nya, di dalam Laravel menyediakan sebuah Collection yang merupakan pembungkus dari arrays of data. Sebagai contoh, lihat kode berikut ini. Kita akan menggunakan helper collect
untuk membuat sebuah instance collection baru dari array kemudian menjalankan function strtoupper
pada setiap element dan menghapus semua element kosong:
$collection = collect(['taylor', 'abigail', null])->map(function ($name) {
return strtoupper($name);
})->reject(function ($name) {
return empty($name);
});
Cara Membuat Collection
Seperti yang dijelaskan sebelumnya, helper collect
akan mengembalikan sebuah namespace Illuminate\Support\Collection
instance untuk memberikan array. Jadi, untuk membuat sebuah collection cukup simpel seperti kode berikut ini:
$collection = collect([1, 2, 3]);
Method Yang Tersedia Untuk Collection
Dengan mengubah array kita menjadi collection, maka array kita sekarang dapat menjalankan method-method yang tersedia pada collection. Berikut adalah list-list method yang tersedia pada Collection.
Catatan:
Kalian bisa melihat list method-method yang tersedia secara lebih lengkap pada dokumentasi laravel berikut ini laravel.com/docs/8.x/collections#available-methods
Alasan Mengapa Melakukan Convert Array Menjadi Collection
Nah, berhubung array yang di convert menjadi collection dapat menjalankan method-method. Kita akan menggunakan beberapa method keren pada collection seperti first
dan firstWhere
.
Method first
ini berfungsi untuk mencari element yang pertama, jika method firstWhere
untuk mencari element yang pertama ketemu dengan sebuah kondisi.
Mengubah Data Post Model Menjadi Sebuah Collection
Setelah memahami mengapa kita perlu mengubah array menjadi collection, selanjutnya kita akan ubah data array pada post model yang sudah kita buat sebelumnya agar menjadi sebuah collection di file app\Models\Post.php
Catatan: Tips Object Oriented Programming!
Perhatikan penulisan pemanggilan sebuah method yang static
static::method();
Keyword static didepan, merupakan teknik penulisan untuk pemanggilan method yang static, namun jika variabel teknik penulisan nya adalah
self::$property;
<?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();
// $post = [];
// foreach ($posts as $p) {
// if ($p['slug'] === $slug) {
// $post = $p;
// }
// }
return $posts->firstWhere('slug', $slug);
}
}
Bisa kalian lihat pada kode diatas tersebut, yang sebelumnya kita melakukan sebuah looping untuk mencari data berdasarkan $slug
di url atau route nya. Sekarang menjadi simpel dengan menggunakan method yang tersedia pada collection yaitu firstWhere
.
Kode tersebut artinya sebagai berikut, ambil semua collection dari property $posts
kemudian cari yang pertama kali ditemukan yang dimana slug nya = $slug
.
Pembuatan Controller
Setelah 2 komponen selesai kita buta yaitu Model dan View, selanjutnya kita akan membuat 1 komponen lagi yaitu Controller agar paradigma MVC benar-benar kita gunakan. Jika kalian lihat sekarang pada bagian routes nya, yang menangani proses itu masih routes nya itu sendiri.
Route::get('/', function () {
return view('home', [
'title' => 'Home'
]);
});
Route::get('/about', function () {
return view('about', [
"title" => "About",
"name" => "Arman Dwi Pangestu",
"email" => "armandwi.pangestu7@gmail.com",
"image" => "me-circle.png"
]);
});
Route::get('/posts', function () {
return view('posts', [
"title" => "Posts",
"posts" => Post::all()
]);
});
// Halaman Single Post
Route::get('posts/{slug}', function ($slug) {
return view('post', [
'title' => 'Single Post',
'post' => Post::find($slug)
]);
});
Nah, seharusnya proses tersebut di handle atau diurus oleh Controller jika kita ingin menerapkan konsep paradgima MVC. Karena memang yang namanya Controller itu adalah yang menangani atau mengendalikan nampilin atau View yang mana dan ngambil Model dari mana.
Jika diambil penjelasan Controller pada website resmi Laravel nya, Controller adalah dari pada kita mendefinisikan semua logic program kita saat menangani proses request atau closure
Route::get('', function() {
// Anonymous function inilah yang dinamakan closure
})
Dari pada kita bikin sebagai closure di dalam routes file kita, kita bisa merapihkan hal tersebut menggunakan sebuah Class Controller
. Controller bisa menggabungkan atau mengelompokan request yang serupa yang saling terkait untuk menangani logic nya dalam sebuah Class. Contohnya, jika kita ingin menangani halaman semua postingan dan yang menangani single postingan. Nah, hal tersebut cocok dijadikan satu Controller karena dua proses tersebut dihandle oleh Controller Post nantinya.
Cara Membuat atau Menulis Controller
Untuk pembuatan atau penulisan sebuah Controller, kita bisa bikin sebuah file yang tersimpan di app/Http/Controllers/
atau namespace folder ini App\Http\Controllers\
kemudian isian dari file tersebut membuat sebuah class yang format penulisan nya adalah Nama
kemudian di ikuti dengan kata Controller
sehingga menjadi IniNamaController
atau pada studi kasus kita PostController
dan class tersebut meng-extends atau mewarisi class bawaan laravel yaitu Controller
. Nah, didalam class tersebut nantinya mempunyai berbagai macam method untuk menangani tiap-tiap logic nya. Contoh penulisan Controller pada dokumentasi resmi Laravel nya sebagai berikut
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\User;
class UserController extends Controller
{
/**
* Show the profile for a given user.
*
* @param int $id
* @return \Illuminate\View\View
*/
public function show($id)
{
return view('user.profile', [
'user' => User::findOrFail($id)
]);
}
}
Nah, nantinya kita akan membuat 2 buah method didalam class Controller tersebut, 1 untuk menangani semua postingan dan 1 lagi untuk menangani sebuah postingan atau single post nya. Nah, setelah controller jadi, maka si routes nya tidak mempunyai lagi closure, namun kita tulis seperti ini saja
use App\Http\Controllers\UserController;
Route::get('/user/{id}', [UserController::class, 'show']);
Cara Membuat Controller Menggunakan Artisan
Sama halnya dengan model, kita juga bisa membuat controller menggunakan perintah php artisan dengan perintah seperti berikut ini
php artisan make:controller NamaController
Implementasi atau Penerapan Controller untuk Semua Postingan
Setelah mengetahui mengapa menggunakan Controller dan bagaimana cara membuatnya, sekarang saatnya kita menerapkan nya. Sekarang kalian buat sebuah Controller menggunakan perintah berikut ini:
php artisan make:controller PostController
Maka sekarang terdapat sebuah file baru di app/Http/Controllers/PostController.php
dengan isian seperti berikut:
Catatan:
Abaikan terlebih dahulu bagian
use Illuminate\Http\Request;
Karena hal tersebut nantinya akan berguna untuk menangani request jika kita mempunyai form atau data di URL sebagai request.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
//
}
Setelah Controller dibuat, selanjutnya kita akan membuat method yang namanya index
sebagai method default nya.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
//use App\Models\Post;
class PostController extends Controller
{
public function index()
{
return view('posts', [
"title" => "Posts",
// Menggunakan use
//"posts" => Post::all()
// Menggunakan expand class
"posts" => \App\Models\Post::all()
]);
}
}
Setelah Controller ready atau siap, sekarang kita benarkan penulisan routes nya agar tidak lagi menggunakan closure, sehingga yang tadinya penulisan nya seperti ini:
Route::get('/posts', function () {
return view('posts', [
"title" => "Posts",
"posts" => Post::all()
]);
});
Sekarang menjadi seperti ini
Route::get('/posts', [PostController::class, 'index']);
Nah, sekarang kita sudah menerapkan controller untuk menangani halaman semua postingan blog kita.
Implementasi atau Penerapan Controller untuk Single Postingan
Setelah sebelumnya kita sudah menerapkan controller untuk menangani halaman semua postingan, selanjutnya kita buat sebuah method baru dengan nama show
untuk menangani single post nya.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
//use App\Models\Post;
class PostController extends Controller
{
public function index()
{
return view('posts', [
"title" => "Posts",
// Menggunakan use
//"posts" => Post::all()
// Menggunakan expand class
"posts" => \App\Models\Post::all()
]);
}
public function show($slug)
{
return view('post', [
'title' => 'Single Post',
'post' => \App\Models\Post::find($slug)
]);
}
}
Nah, sekarang kita ubah bagian kode routes yang menggunakan closure pada route yang menangani single post nya agar menggunakan controller nya
Route::get('/posts', [PostController::class, 'index']);
// Halaman Single Post
Route::get('posts/{slug}', [PostController::class, 'show']);