Membuat CRUD Post. Halo sobat edikomputer kembali lagi dengan saya edi Prasetyo, kali ini kita akan lanjutkan tutorial lanjutan membuat aplikasi blog menggunakan laravel 9. Pada tutorial kali ini kita akan membahas bagaimana cara membuat CRUD untuk Post.
Post atau artikel nantinya akan relasi dengan category. Kita akan membuat beberapa hal yang pertama kita akan membuat file migrasi untuk table post, kemudian kita juga akan membuat post Controller dan post Model, lalu kita juga membutuhkan View untuk create, edit dan delete post yang terakhir kita akan seting route.
Membuat Migrasi table post
Silahkan buka projek laravel_blog yang sebelumnya sudah di buat di vscode, lalu buka terminal dan jalankan perintah :
php artisan make:migration create_posts_table
Sekarang silahkan buka file migrasi create_posts_table yang berada di folder database/migration, lalu tambahkan beberapa field dengan menambahkan kode dibawah ini :
$table->integer('category_id');
$table->string('slug');
$table->string('title');
$table->longText('content')->nullable();
$table->string('image')->nullable();
$table->tinyInteger('status')->default(1)->comment('1=publish, 0=draft');
Sehingga keseluruhan kode dari post table ini adalah seperti di bawah ini :
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->integer('category_id');
$table->string('slug');
$table->string('title');
$table->longText('content')->nullable();
$table->string('image')->nullable();
$table->tinyInteger('status')->default(1)->comment('1=publish, 0=draft');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
};
Jika sudah jalankan migrasi dengan mengetik perintah seperti di bawah ini melalui terminal
php artisan migrate
Jika sudah silahkan cek databasenya jika sudah muncul table posts berarti kita sudah berhasil Membuat table posts nya.
Membuat Controller Posts
Oke sekarang kita akan lanjutkan dengan membuat Controller untuk CRUD post, Silahkan ketik perintah berikut di terminal :
php artisan make:controller Admin/PostController
Lalu buat juga Request dengan mengetik perintah
php artisan make:request PostFormRequest
Kemudian buat juga model dengan perintah seperti berikut
php artisan make:model Post
Sekarang silahkan Buka file PostController.php yang ada di direktory app/Http/Controllers/Admin lalu ubah semua kode menjadi seperti di bawah ini :
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\PostFormRequest;
use App\Models\Category;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\File;
use App\Models\Post;
class PostController extends Controller
{
public function index()
{
$posts = Post::orderBy('id', 'desc')
->leftJoin('categories', 'categories.id', '=', 'posts.category_id')
->select('posts.id', 'posts.title', 'posts.content', 'posts.slug', 'posts.status', 'categories.name as category_name')
->paginate(5);
return view('admin.post.index', compact('posts'));
}
public function create()
{
$categories = Category::all();
return view('admin.post.create', compact('categories'));
}
public function store(PostFormRequest $request)
{
$validatedData = $request->validated();
$slugRequest = Str::slug($validatedData['title']);
$code = random_int(00, 99);
$slug = $slugRequest . '-' . $code;
$post = new Post;
$post->category_id = $validatedData['category_id'];
$post->title = $validatedData['title'];
if (Post::where('slug', $slugRequest)->exists()) {
$post->slug = $slug;
} else {
$post->slug = $slugRequest;
}
$post->content = $validatedData['content'];
if ($request->hasFile('image')) {
$file = $request->file('image');
$ext = $file->getClientOriginalExtension();
$filename = time() . '.' . $ext;
$file->move('uploads/post/', $filename);
$post->image = $filename;
}
$post->status = $validatedData['status'];;
$post->save();
return redirect('admin/posts')->with('message', 'Post Has Added');
}
public function edit(Post $post)
{
$categories = Category::all();
return view('admin.post.edit', compact('post', 'categories'));
}
public function update(PostFormRequest $request, $post)
{
$validatedData = $request->validated();
$post = Post::findOrFail($post);
$post->category_id = $validatedData['category_id'];
$post->title = $validatedData['title'];
$post->content = $validatedData['content'];
if ($request->hasFile('image')) {
$path = 'uploads/post/' . $post->image;
if (File::exists($path)) {
File::delete($path);
}
$file = $request->file('image');
$ext = $file->getClientOriginalExtension();
$filename = time() . '.' . $ext;
$file->move('uploads/post/', $filename);
$post->image = $filename;
}
$post->status = $validatedData['status'];
$post->update();
return redirect('admin/posts')->with('message', 'Post update Succesfully');
}
public function destroy(int $post_id)
{
$post = Post::findOrFail($post_id);
$post->delete();
return redirect()->back()->with('message', 'Post has ben Deleted!');
}
}
Save, lalu buka file PostFormRequest.php yang berada di app/Http/Requests, Lalu replace semua code dengan code di bawah ini :
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostFormRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'category_id' => ['required'],
'title' => ['required', 'string'],
'content' => ['required'],
'status' => ['required'],
'image' => ['nullable', 'mimes:jpg,jpeg,png']
];
}
}
Sekarang kita Juga edit File Model Post.php yang berlokasi di app/Models lalu ubah semua code seperti ini :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $table = ('posts');
protected $fillable = [
'slug',
'title',
'image',
'content'
];
}
Jika sudah simpan lalu sekarang kita akan membuat file views
Membuat File Views Post
Setelah kita membuat Controller, Model dan Request sekarang kita akan membuat tampilan Crud Post Sehingga kita bisa akses Proses CRUD melalui Browser. Sekarang silahkan kalian menuju folder resources/views/admin kemudian buat folder baru dengan nama post. Kemudian di dalam folder post buat 4 file blade :
- index.blade.php
- create.blade.php
- edit.blade.php
- delete.blade.php
Pada file index.blade.php silahkan copy code berikut ini :
@extends('layouts.app')
@section('content')
<div class="container">
<div class="col-md-8 mx-auto">
@if (session('message'))
<div class="alert alert-success my-3">
{{session('message')}}
</div>
@endif
<div class="card">
<div class="card-header d-flex justify-content-between align-items-start">
<div>Post</div>
<a href="{{url('admin/posts/create')}}" class="btn btn-primary btn-sm">Add Post</a>
</div>
<div class="card-body">
<table class="table table-striped">
<thead>
<tr>
<th width="5%">No</th>
<th>title</th>
<th>Slug</th>
<th>Category</th>
<th>Status</th>
<th width="20%">Action</th>
</tr>
</thead>
<tbody>
@forelse($posts as $i => $data)
<tr>
<th>{{$i+1}}</th>
<td>{{$data->title}}</td>
<td>{{$data->slug}}</td>
<td>{{$data->category_name}}</td>
<td>
@if($data->status == 1)
<span class="badge text-success bg-success-subtle">Publish</span>
@else
<span class="badge text-dark bg-dark-subtle">Draft</span>
@endif
</td>
<td>
<a href="{{url('admin/posts/edit/' .$data->id)}}"
class="btn btn-primary btn-sm">edit</a>
@include('admin.post.delete')
</td>
</tr>
@empty
<th colspan="6" class="text-center">No Data Available</th>
@endforelse
</tbody>
</table>
</div>
<div class="card-body">
{{ $posts->links() }}
</div>
</div>
</div>
</div>
@endsection
Lalu untuk file create.blade.php codenya adalah seperti di bawah ini
@extends('layouts.app')
@section('content')
<div class="container">
<div class="col-md-6 mx-auto">
<div class="card">
@if($errors->any())
{{ implode('', $errors->all('<div>:message</div>')) }}
@endif
<div class="card-header">
Add Category
</div>
<div class="card-body">
<form action="{{url('admin/posts')}}" method="POST" enctype="multipart/form-data">
@csrf
<div class="mb-3">
<label class="form-label">Category</label>
<select class="form-select form-control @error('category_id') is-invalid @enderror"
name="category_id" aria-label="Default select example">
<option value="" selected>--Select Category--</option>
@foreach($categories as $key => $data)
<option value="{{$data->id}}">{{$data->name}}</option>
@endforeach
</select>
@error('category_id')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-3">
<label class="form-label">Post Title</label>
<input type="text" name="title" class="form-control @error('title') is-invalid @enderror">
@error('title')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-3">
<label class="form-label">Post Image</label>
<input type="file" name="image" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">Post Content</label>
<textarea type="text" name="content"
class="form-control @error('content') is-invalid @enderror"></textarea>
@error('content')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-3">
<label class="form-label">Status</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="status" value="1" id="flexRadioDefault1"
checked>
<label class="form-check-label" for="flexRadioDefault1">
Publish
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="status" value="0" id="flexRadioDefault2">
<label class="form-check-label" for="flexRadioDefault2">
Save to Draft
</label>
</div>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
</div>
</div>
@endsection
kemudian file edit.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="col-md-6 mx-auto">
<div class="card">
<div class="card-header">
Add Category
</div>
<div class="card-body">
<form action="{{url('admin/posts/'.$post->id)}}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="mb-3">
<label class="form-label">Category</label>
<select class="form-select form-control @error('category_id') is-invalid @enderror"
name="category_id" aria-label="Default select example">
<option value="" selected>--Select Category--</option>
@foreach($categories as $key => $data)
<option value="{{$data->id}}" @if ($post->category_id == $data->id)
{{'selected="selected"'}} @endif >{{$data->name}}</option>
@endforeach
</select>
@error('category_id')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-3">
<label class="form-label">Post Title</label>
<input type="text" name="title" value="{{$post->title}}"
class="form-control @error('title') is-invalid @enderror">
@error('title')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-3">
<label class="form-label">Post Image</label>
<input type="file" name="image" class="form-control">
@if($post->image == null)
@else
<div class="col-md-4 my-3">
<img class="img-fluid rounded" src="{{url('uploads/post/' .$post->image)}}">
</div>
@endif
</div>
<div class="mb-3">
<label class="form-label">Post Content</label>
<textarea type="text" name="content"
class="form-control @error('content') is-invalid @enderror">{{$post->content}}</textarea>
@error('content')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-3">
<label class="form-label">Status</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="status" value="1" id="flexRadioDefault1"
@if ($post->status == 1)
{{'checked="checked"'}} @endif
>
<label class="form-check-label" for="flexRadioDefault1">
Publish
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="status" value="0" id="flexRadioDefault2"
@if ($post->status == 0)
{{'checked="checked"'}} @endif>
<label class="form-check-label" for="flexRadioDefault2">
Draft
</label>
</div>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
</div>
</div>
@endsection
dan yang terakhir adalah File delete.blade.php
<button type="button" class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#deleteModal{{$data->id}}">
Hapus
</button>
<div class="modal fade" id="deleteModal{{$data->id}}" tabindex="-1" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Data Category</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Are You Sure?? You want to delete this Data!!
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<a href="{{url('admin/posts/delete/' .$data->id)}}" class="btn btn-danger">Yes Delete</a>
</div>
</div>
</div>
</div>
Jika sudah, simpan semua file.
Setting Routes
Jika semua sudah di edit sekarang kita akan seting File Route kita akan menambahkan Route Group untuk post silahkan buka file web.php yang berada di folder routes. kemudian tambahkan code ini di dalam route group midleware auth :
// Post Route
Route::controller(PostController::class)->group(function () {
Route::get('/posts', 'index');
Route::get('/posts/create', 'create');
Route::post('/posts', 'store');
Route::get('/posts/edit/{post}', 'edit');
Route::put('/posts/{post}', 'update');
Route::get('/posts/delete/{post_id}', 'destroy');
});
Sehingga Secara keseluruhan kodenya adalah seperti ini :
<?php
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Admin\DashboardController;
use App\Http\Controllers\Admin\CategoryController;
use App\Http\Controllers\Admin\PostController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::prefix('admin')->middleware(['auth'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
// Category Route
Route::controller(CategoryController::class)->group(function () {
Route::get('/categories', 'index');
Route::get('/categories/create', 'create');
Route::post('/categories', 'store');
Route::get('/categories/edit/{category}', 'edit');
Route::put('/categories/{category}', 'update');
Route::get('/categories/delete/{category_id}', 'destroy');
});
// Post Route
Route::controller(PostController::class)->group(function () {
Route::get('/posts', 'index');
Route::get('/posts/create', 'create');
Route::post('/posts', 'store');
Route::get('/posts/edit/{post}', 'edit');
Route::put('/posts/{post}', 'update');
Route::get('/posts/delete/{post_id}', 'destroy');
});
});
Jika sudah silahkan aktifkan apache dan mysql yang ada di xampp dan juga jalankan server laravel dengan perintah php artisan serve, kemudian buka browser http://localhost:8000/login, kemudian pilih menu post atau akses url http://localhost:8000/admin/posts.
Oke demikian tutorial pembuatan CRUD untuk fungsi Post artikel pada kali ini, selanjutnya kita akan membuat bagian Frontend untuk menampilkan artikel yang sudah kita buat pada bagian admin. tetap stay di blog edikomputer.com, selain itu kamu juga bisa menonton video tutorial di youtube edikomputer