Untuk membuat CRUD Laravel dalam hal ini CRUD Posts, kita akan mulai langkah tersebut sebagai berikut:
1. Persiapan Proyek Laravel
Mulai dengan proyek Laravel baru dengan membukan console dan ketik berikut:
composer create-project --prefer-dist laravel/laravel blog
cd blog
php artisan serve
2. Buat Model dan Migration
Buat model Post dengan migration-nya dengan ketik di terminal berikut:
php artisan make:model Post -m
-m akan membuat migration di folder app\database\migrations. lalu Edit file migration di database/migrations/xxxx_create_posts_table.php menjadi sebagai berikut:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->string('image')->nullable(); // Kolom untuk gambar
$table->timestamps();
});
}
Setelah itu edit file .env untuk konfigurasi database sebagai berikut:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tutorials
DB_USERNAME=root
DB_PASSWORD=
Untuk nama database, username dan password silahkan sesuaikan dengan database masing-masing. Dalam tutorial ini, database kita buat degan nama tutorials, kemudian user root dan password kosong.
Kemudian jalankan perintah migrate untuk membuat tabel posts di database dengan ketik perintah berikut:
php artisan migrate
Setelah migrate berhasil, maka akan terbentuk tabel di database dengan nama tutorials dan otomatis akan dibuat table dengan nama posts.
Kemudian edit Model Post.php menjadi sebagai berikut:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = ['title', 'body', 'image'];
}
3. Buat Resource Controller
Buat controller untuk Post dengan melakukan perintah berikut:
php artisan make:controller PostController --resource
Lalu bukan file controller yang sudah kita create tadi di folder app\controllers dan edit menjadi berikut:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Display a listing of the posts.
*/
public function index()
{
$posts = Post::all();
return view('posts.index', compact('posts'));
}
/**
* Show the form for creating a new post.
*/
public function create()
{
return view('posts.create');
}
/**
* Store a newly created post in storage.
*/
public function store(Request $request)
{
$request->validate([
'title' => 'required|string|max:255',
'body' => 'required',
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
]);
$imageName = null;
if ($request->file('image')) {
$imageName = time() . '.' . $request->image->extension();
$request->image->move(public_path('images'), $imageName);
}
Post::create([
'title' => $request->title,
'body' => $request->body,
'image' => $imageName,
]);
return redirect()->route('posts.index')->with('success', 'Post created successfully.');
}
/**
* Display the specified post.
*/
public function show($id)
{
$post = Post::findOrFail($id);
return view('posts.show', compact('post'));
}
/**
* Show the form for editing the specified post.
*/
public function edit($id)
{
$post = Post::findOrFail($id);
return view('posts.edit', compact('post'));
}
/**
* Update the specified post in storage.
*/
public function update(Request $request, $id)
{
$post = Post::findOrFail($id);
$request->validate([
'title' => 'required|string|max:255',
'body' => 'required',
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
]);
$imageName = $post->image;
if ($request->file('image')) {
if ($imageName) {
unlink(public_path('images/') . $imageName); // Hapus gambar lama jika ada
}
$imageName = time() . '.' . $request->image->extension();
$request->image->move(public_path('images'), $imageName);
}
$post->update([
'title' => $request->title,
'body' => $request->body,
'image' => $imageName,
]);
return redirect()->route('posts.index')->with('success', 'Post updated successfully.');
}
/**
* Remove the specified post from storage.
*/
public function destroy($id)
{
$post = Post::findOrFail($id);
if ($post->image) {
unlink(public_path('images/') . $post->image); // Hapus gambar jika ada
}
$post->delete();
return redirect()->route('posts.index')->with('success', 'Post deleted successfully.');
}
}
4. Views
Buat view untuk menampilkan form dan data post. Buat folder posts di resources/views/posts dan buat file berikut:
index.blade.php (List Posts)
@extends('layout')
@section('title', 'Manage Posts')
@section('content')
<div class="container mt-5">
<h2 class="mb-4">Manage Posts</h2>
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<!-- Tombol untuk menambahkan post baru -->
<div class="d-flex justify-content-between mb-3">
<a href="{{ route('posts.create') }}" class="btn btn-primary">Create New Post</a>
<form action="{{ route('posts.index') }}" method="GET" class="d-flex">
<input type="text" name="search" class="form-control me-2" placeholder="Search posts" value="{{ request()->query('search') }}">
<button type="submit" class="btn btn-secondary">Search</button>
</form>
</div>
<!-- Tabel daftar posts -->
<table class="table table-bordered table-striped">
<thead class="table-dark">
<tr>
<th>#</th>
<th>Title</th>
<th>Image</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@forelse ($posts as $post)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $post->title }}</td>
<td>
@if ($post->image)
<img src="{{ asset('images/' . $post->image) }}" alt="{{ $post->title }}" class="img-thumbnail" style="width: 100px;">
@else
<span class="text-muted">No Image</span>
@endif
</td>
<td>{{ $post->created_at->format('d M Y') }}</td>
<td>
<a href="{{ route('posts.edit', $post->id) }}" class="btn btn-sm btn-warning">Edit</a>
<form action="{{ route('posts.destroy', $post->id) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Are you sure you want to delete this post?')">Delete</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="text-center">No posts found.</td>
</tr>
@endforelse
</tbody>
</table>
<!-- Pagination -->
<div class="d-flex justify-content-end">
</div>
</div>
@endsection
Kemudian di folder yang sama, create file create.blade.php di folder yang sama dan isikan code berikut:
@extends('layout')
@section('title', 'Create New Post')
@section('content')
<div class="container mt-5">
<h2 class="mb-4">Create New Post</h2>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('posts.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="mb-3">
<label for="title" class="form-label">Post Title</label>
<input type="text" class="form-control" id="title" name="title" value="{{ old('title') }}" placeholder="Enter post title">
</div>
<div class="mb-3">
<label for="content" class="form-label">Content</label>
<textarea class="form-control" id="content" name="body" rows="5" placeholder="Enter post content">{{ old('content') }}</textarea>
</div>
<div class="mb-3">
<label for="image" class="form-label">Post Image</label>
<input type="file" class="form-control" id="image" name="image">
</div>
<button type="submit" class="btn btn-primary">Create Post</button>
</form>
</div>
@endsection
dan create file edit.blade.php di folder views dan isi code menjadi berikut:
@extends('layout')
@section('title', 'Edit Post')
@section('content')
<div class="container mt-5">
<h2 class="mb-4">Edit Post</h2>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('posts.update', $post->id) }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="mb-3">
<label for="title" class="form-label">Post Title</label>
<input type="text" class="form-control" id="title" name="title" value="{{ old('title', $post->title) }}" placeholder="Enter post title">
</div>
<div class="mb-3">
<label for="content" class="form-label">Content</label>
<textarea class="form-control" id="content" name="body" rows="5">{{ old('content', $post->body) }}</textarea>
</div>
<div class="mb-3">
<label for="image" class="form-label">Post Image</label>
<input type="file" class="form-control" id="image" name="image">
@if ($post->image)
<div class="mt-3">
<img src="{{ asset('images/' . $post->image) }}" alt="Post Image" class="img-thumbnail" style="width: 150px;">
</div>
@endif
</div>
<button type="submit" class="btn btn-primary">Update Post</button>
</form>
</div>
@endsection
Karena di file create dan edit tadi kita extends layout, maka di folder resource/views, buat file php dengan nama layout.blade.php sebagai template dan isikan code berikut:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', 'CRUD Posts')</title>
<!-- Tambahkan Bootstrap CSS atau styling lainnya -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="{{ route('posts.index') }}">My Blog</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="{{ route('posts.index') }}">Posts</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('posts.create') }}">Create New Post</a>
</li>
</ul>
</div>
</nav>
<!-- Main Content -->
<div class="container mt-5">
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
@yield('content')
</div>
<!-- Tambahkan Bootstrap JS atau script lainnya -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</body>
</html>
5. Routing
Tambahkan route di routes/web.php:
use App\Http\Controllers\PostController;
Route::resource('posts', PostController::class);
Setelah itu, silahkan akses https://localhost/posts dan hasilnya sebagai berikut:
thank you :)