Table of Contents

Pengenalan

CRUD adalah singkatan yang berasal dari Create, Read, Update, dan Delete, dimana keempat istilah tersebut merupakan fungsi utama yang nantinya diimplementasikan ke dalam basis data.

Empat poin tersebut mengindikasikan bahwa fungsi utama melekat pada penggunaan database relasional beserta aplikasi yang mengelolanya, seperti Oracle, MySQL, SQL Server, dan lain – lain.

Jika dihubungkan dengan tampilan antarmuka (interface), maka peran CRUD sebagai fasilitator berkaitan dengan tampilan pencarian dan perubahan informasi dalam bentuk formulir, tabel, atau laporan. Nantinya, akan ditampilkan dalam browser atau aplikasi pada perangkat komputer user.

Disini kita akan membuat mengimplementsasi CRUD pada table Category dan Post.

Membuat Project
				
					composer create-project Laravel/laravel blog
				
			
Konfigurasi Database

Sesuaikan akses database pada file .env :

				
					DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=database_name
DB_USERNAME=database_user_name
DB_PASSWORD=database_password
				
			
Install Laravel Breeze(Autentikasi)
				
					composer require laravel/breeze --dev

php artisan breeze:install
 
npm install
npm run dev
				
			
				
					php artisan migrate
				
			
Membuat Model Migration & Seeder untuk Category
Generate File
				
					php artisan make:model Category -m
				
			

Akan otomatis terbuat 2 file yaitu :

  1. database/migrations/*_create_categories_table.php
  2. app/Models/Category.php

Sesuaikan kolom pada file database/migrations/*_create_categories_table.php :

Membuat table Category
				
					public function up()
{
    Schema::create('categories', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('slug');
        $table->timestamps();
    });
}
				
			

Dari perubahan di atas kita menambahkan 2 field baru dengan type data string.

Jalankan Migrate

				
					php artisan migrate
				
			
Menyesuaikan Model

Supaya field2 dapat ditambahkan atau diubah kita perlu menambahkan properti $fillabel pada file app/Models/Category.php :

				
					<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'slug',
    ];
}
				
			
Membuat Dummy Seeder

Membuat dummy jadi sebelum di insert sudah terdapat beberapa data dummy sebelumnya. Buat file database/seeders/CategorySeeder.php :

				
					<?php

    namespace Database\Seeders;

    use App\Models\Category;
    use Illuminate\Database\Seeder;

    class CategorySeeder extends Seeder
    {
        /**
         * Run the database seeds.
         *
         * @return void
         */
        public function run()
        {
            $data = [
                [
                    'name' => 'PHP',
                    'slug' => \Str::slug('PHP'),
                    'created_at' => now(),
                ],
                [
                    'name' => 'Python',
                    'slug' => \Str::slug('Python'),
                    'created_at' => now(),
                ],
                [
                    'name' => 'Java',
                    'slug' => \Str::slug('Java'),
                    'created_at' => now(),
                ],
                [
                    'name' => 'C++',
                    'slug' => \Str::slug('C++'),
                    'created_at' => now(),
                ],
                [
                    'name' => 'Ruby',
                    'slug' => \Str::slug('Ruby'),
                    'created_at' => now(),
                ],
            ];
            Category::insert($data);
        }
    }
				
			
Jalankan Database Seeder
				
					php artisan db:seed --class=CategorySeeder
				
			
Membuat Model, Migration, Controller & Route untuk Post
Generate File

Buat Model, Migration & Controller untuk Post secara bersamaan :

				
					php artisan make:model Post -mcr
				
			

Perintah di atas akan membuat 3 file secara bersamaan :

  1. app/Models/Post.php
  2. database/migrations/2023_01_11_052429_create_posts_table.php
  3. app/Http/Controllers/PostController.php
Membuat table Post

Sesuaikan field pada file database/migrations/*_create_posts_table.php :

				
					public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->string('slug');
        $table->longText('description');
        $table->foreignId('category_id')->constrained();
        $table->timestamps();
    });
}
				
			

Jalankan Migrate

				
					php artisan migrate
				
			
Menyesuaikan Model

Tambahkan property $fillable untuk fields yang akan diizinkan untuk dimanipulasi.

				
					<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    protected $fillable = [
        'title',
        'slug',
        'description',
        'category_id',
    ];

    public function category()
    {
        return $this->belongsTo(Category::class);
    }
}
				
			
Menambahkan Route

Supaya Controller dapat dibuka kita perlu menambahkan baris route pada file routes/web.php :

				
					Route::resource('posts', PostController::class);
				
			
Mengatur Controller

Sebelumnya file Controller sudah otomatis digenerate pada langkah di atas dengan di dalamnya terdapat fungsi bawaan seperti index, create, store, show, edit, update, & destroy.

Sekarang kita akan mengedit file Controller agar benar2 dapat digunakan. Buka file app/Http/Controllers/PostController.php :

				
					<?php

namespace App\Http\Controllers;

use App\Models\Post;
use App\Models\Category;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $title= "Post";
        $data = Post::with('category')->orderBy('id','desc')->paginate(10);
        return view('posts.index',compact('title','data'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $title = 'Post';
        $categories = Category::all();
        return view('posts.create', compact('title','categories'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'required',
            'category_id' => 'required|exists:App\Models\Category,id'
        ]);
        Post::create([
            'title' => $request->title,
            'slug' => \Str::slug($request->title),
            'content' => $request->content,
            'category_id' => $request->category_id,
        ]);

        return redirect()->route('posts.index')->with('status', 'Post Created Successfully');
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function show(Post $post)
    {
        return view('posts.show', compact('post'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function edit(Post $post)
    {
        $title = 'Post';
        $categories = Category::all();
        return view('posts.edit', compact('title','categories', 'post'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Post $post)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'required',
            'category_id' => 'required|exists:App\Models\Category,id',
        ]);
        $post->title = $request->title;
        $post->slug = \Str::slug($request->title);
        $post->content = $request->content;
        $post->category_id = $request->category_id;
        $post->save();

        return redirect()->route('posts.index')->with('status', 'Post Updated Successfully');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function destroy(Post $post)
    {
        $post->delete();
        return redirect()->route('posts.index')->with('status', 'Post Delete Successfully');
    }
}

				
			
Membuat View

Sebelum membuat view kita akan membuat folder baru resources/views/posts .

Menampilkan Data

Buat file baru posts/index.blade.php :

				
					@extends('layouts.app')

@section('content')
@if($message = Session::get('success'))

<div class="alert alert-success">
	{{ $message }}
</div>

@endif
<nav aria-label="breadcrumb">
  <ol class="breadcrumb">
    <li class="breadcrumb-item"><a href="#">Home</a></li>
    <li class="breadcrumb-item active" aria-current="page">{{ $title }}</li>
  </ol>
</nav>
<div class="card">
	<div class="card-header">
		<div class="row">
			<div class="col col-md-6"><b>{{ $title }}</b></div>
			<div class="col col-md-6">
                @can('create posts', Post::class)
				    <a href="{{ route('posts.create') }}" class="btn btn-success btn-sm float-end">Add</a>
                @endcan
			</div>
		</div>
	</div>
	<div class="card-body">
		<table class="table table-bordered">
			<tr>
				<th>Title</th>
				<th>Content</th>
				<th>Category</th>
				<th>Action</th>
			</tr>
			@if(count($data) > 0)

				@foreach($data as $row)

					<tr>
						<td>{{ $row->title }}</td>
						<td>{{ substr($row->content,1,100) }}</td>
						<td>{{ $row->category->name }}</td>
						<td>
							<form method="post" action="{{ route('posts.destroy', $row->id) }}">
								@csrf
								@method('DELETE')
								<a href="{{ route('posts.show', $row->id) }}" class="btn btn-primary btn-sm">View</a>
								<a href="{{ route('posts.edit', $row->id) }}" class="btn btn-warning btn-sm">Edit</a>
								<input type="submit" class="btn btn-danger btn-sm" value="Delete" />
							</form>

						</td>
					</tr>

				@endforeach

			@else
				<tr>
					<td colspan="5" class="text-center">No Data Found</td>
				</tr>
			@endif
		</table>
        <div class="py-2">
		    {!! $data->links() !!}
        </div>
	</div>
</div>
@endsection('content')

				
			
Menambahkan Data

Buat file baru posts/create.blade.php :

				
					@extends('layouts.app')

@section('content')
@if($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
<nav aria-label="breadcrumb">
  <ol class="breadcrumb">
    <li class="breadcrumb-item"><a href="#">Home</a></li>
    <li class="breadcrumb-item"><a href="{{route('posts.index')}}">{{ $title }}</a></li>
    <li class="breadcrumb-item active" aria-current="page">Edit</li>
</ol>
</nav>
<div class="card">
	<div class="card-header">Add {{$title}}</div>
	<div class="card-body">
		<form method="post" action="{{ route('posts.store') }}">
			@csrf
			<div class="row mb-3">
				<label class="col-sm-2 col-label-form">Title</label>
				<div class="col-sm-10">
					<input type="text" name="title" class="form-control" />
				</div>
			</div>
			<div class="row mb-4">
				<label class="col-sm-2 col-label-form">Category</label>
				<div class="col-sm-10">
					<select name="category_id" class="form-control">
                        <option>---</option>
                        @foreach($categories as $category)
                            <option value="{{ $category->id }}">{{$category->name}}</option>
                        @endforeach
					</select>
				</div>
			</div>
			<div class="row mb-4">
				<label class="col-sm-2 col-label-form">Content</label>
				<div class="col-sm-10">
                    <textarea class="form-control" name="content" rows="3"></textarea>
				</div>
			</div>
			<div class="text-center">
				<input type="submit" class="btn btn-primary" value="Add" />
			</div>
		</form>
	</div>
</div>
@endsection('content')

				
			
Ubah Data

Buat file baru posts/edit.blade.php :

				
					@extends('layouts.app')

@section('content')
<nav aria-label="breadcrumb">
  <ol class="breadcrumb">
    <li class="breadcrumb-item"><a href="#">Home</a></li>
    <li class="breadcrumb-item"><a href="{{route('posts.index')}}">{{ $title }}</a></li>
    <li class="breadcrumb-item active" aria-current="page">Edit</li>
</ol>
<div class="card">
	<div class="card-header">
		<div class="row">
			<div class="col col-md-6"><b>{{ $title }}</b></div>
			<div class="col col-md-6">
				<a href="{{ route('posts.index') }}" class="btn btn-primary btn-sm float-end">View All</a>
			</div>
		</div>
	</div>
	<div class="card-body">
        <form method="post" action="{{ route('posts.update', $post->id) }}" enctype="multipart/form-data">
            @csrf
            @method('PUT')
            <div class="row mb-3">
                <label class="col-sm-2 col-label-form">Title</label>
                <div class="col-sm-10">
                    <input value="{{ $post->title }}" type="text" name="title" class="form-control" />
                </div>
            </div>
            <div class="row mb-4">
                <label class="col-sm-2 col-label-form">Category</label>
                <div class="col-sm-10">
                    <select name="category_id" class="form-control">
                        <option>---</option>
                        @foreach($categories as $category)
                            <option value="{{ $category->id }}" {{$category->id==$post->category->id?'selected':''}}>{{$category->name}}</option>
                        @endforeach
                    </select>
                </div>
            </div>
            <div class="row mb-4">
                <label class="col-sm-2 col-label-form">Content</label>
                <div class="col-sm-10">
                    <textarea class="form-control" name="content" rows="3">{{$post->content }}</textarea>
                </div>
            </div>
            <div class="text-center">
				<input type="hidden" name="hidden_id" value="{{ $post->id }}" />
				<input type="submit" class="btn btn-primary" value="Update" />
			</div>
        </div>
    </form>
</div>
@endsection('content')

				
			
Jalankan
				
					npm run dev

php artisan serve
				
			
Produksi

Untuk fase Produksi jalankan perintah berikut :

				
					npm run build