author Ahmad Muhardian

Tutorial Codeigniter #07: Membuat Halaman Admin (CRUD)


Codeigniter Admin

Ini adalah tutorial lanjutan dari tutorial sebelumnya:

Pada tutorial ini, kita akan fokus mengerjakan halaman Admin.

Saya tidak akan banyak berteori di tutorial ini, karena penjelasan tentang dasar-dasar Codeigniter sudah dijelaskan di tutorial-tutorial sebelumnya.

Seperti:

Mari kita langsung saja praktek dan melanjutkan project beritacoding.

Membuat Controller Admin

Buatlah folder baru di dalam folder application/controllers/ dengan nama admin.

Kemudian di dalam folder admin, buatlah Controller berikut:

  • Dashboard.php untuk halaman awal admin;
  • Post.php untuk CRUD artikel;
  • Feedback.php untuk menampikan feedback dari contact form;
  • Setting.php untuk setting website.

file controller admin

Berikut ini isi untuk masing-masing Controller:

📜 controllers/admin/Dashboard.php

<?php

class Dashboard extends CI_Controller
{
	public function index()
	{
		$this->load->view('admin/dashboard.php');
	}
}

📜 controllers/admin/Feedback.php

<?php

class Feedback extends CI_Controller
{
	public function index()
	{
		$this->load->view('admin/feedback_list');
	}

}

📜 controllers/admin/Post.php

<?php

class Post extends CI_Controller
{
	public function index()
	{
		$this->load->view('admin/post_list.php');
	}
}

📜 controllers/admin/Setting.php

<?php

class Setting extends CI_Controller
{
	public function index()
	{
		$this->load->view('admin/setting');
	}
}

Untuk saat ini, semua controller Admin yang kita buat hanya bertugas untuk menampilkan view admin.

Nanti kita akan buat semua View-nya.

Berikutnya silakan lanjutkan ke:

Membuat Route Default untuk Admin

Buka file config/routes.php kemudian tambahkan route default untuk admin seperti ini:

$route['admin'] = 'admin/dashboard';

Artinya, kita akan menggunakan Controller admin/dashboard sebagai Controller yang menerima request dari index.php/admin.

route default untuk admin

Setelah itu silakan lajutkan ke:

Membuat Template Admin

Kita ingin memisah template untuk halaman admin dan halaman depan, karena bentuk layoutnya berbeda.

Berikut ini bentuk rancangan atau desain dari halaman admin yang akan kita buat:

desain halaman admin

Mari kita mulai membuat template.

Buatlah folder baru di dalam 📁 views dengan nama 📁 admin.

folder template admin

Kemudian di dalamnya folder 📁 admin, buat lagi folder baru dengan nama 📁 _partials.

folder partial admin

Folder _partials akan berisi partial atau bagian dari view yang akan digunakan pada view admin.

Nama dengan underscore di depan berfungsi sebagai penanda kalau ini partial, bukan view yang di-load dari Controller. Ini sebenarnya tidak wajib, namun agar lebih mudah dibaca kita pakai nama ini saja.

Oke berikutnya mari kita buat partial untuk admin.

Buatlah file baru di dalam 📁 admin/_partials dengan nama dan isi sebagai berikut:

📜 head.php

<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>Admin - Beritacoding</title>

<link rel="stylesheet" href="<?= base_url('assets/css/admin.css') ?>" />

Pada kode partial ini, kita menggunakan admin.css sebagai CSS untuk halaman admin. File ini akan kita buat nanti.

📜 footer.php

<footer class="footer">
	&copy; <?= Date('Y') ?> Beritacoding.com Version 1.0.0
</footer>

📜 side_nav.php

<aside class="side-nav">
	<div class="brand">
		<h2>Berita Coding</h2>
	</div>
	<nav>
		<a href="<?= site_url('admin/dashboard') ?>">Overview</a>
		<a href="<?= site_url('admin/post') ?>">Post</a>
		<a href="<?= site_url('admin/feedback') ?>">Feedback</a>
		<a href="<?= site_url('admin/setting') ?>">Setting</a>
		<a href="<?= site_url('auth/logout') ?>">Logout</a>
	</nav>
</aside>

Nah, berikutnya karena kita menggunakan file CSS admin.css di dalam partial head.php maka kita perlu membuatnya.

Buatlah file baru di dalam folder 📁 assets/css/ dengan nama admin.css dengan isi sebagai berikut:

body {
	margin: 0;
	padding: 0;
}

.main {
	display: flex;
}

.side-nav {
	background: teal;
	width: 25vw;
	max-width: 200px;
	height: 100vh;
}

.side-nav .brand {
	padding: 0 1rem;
	color: white;
}

.side-nav nav {
	display: flex;
	flex-direction: column;
}

.side-nav nav a {
	font-family: sans;
	text-decoration: none;
	color: white;
	padding: 0.8rem;
}

.side-nav nav a:hover {
	background-color: rgba(0, 0, 0, 0.2);
}

.content {
	padding: 1rem;
	padding-right: 2rem;
	width: 100%;
	position: static;
}

.toolbar {
	display: flex;
	margin: 1rem 0;
}

.table {
	width: 100%;
	border-collapse: collapse;
}

.table,
th,
td {
	border: 1px solid grey;
	border-left: none;
	border-right: none;
	padding: 0.5rem;
	text-align: left;
}

.action {
	display: flex;
	justify-content: center;
	gap: 0.8rem;
}

.footer {
	position: absolute;
	bottom: 1rem;
	text-align: center;
	font-family: sans-serif;
	font-size: 0.7rem;
}

/* Form */
form {
	box-sizing: border-box;
	padding: 0rem;
}
label {
	display: inline-block;
	margin-bottom: 0.5rem;
}
input, textarea {
	display: inline-block;
	padding: 0.5rem;
	margin-bottom: 1rem;
	width: 100%;
}
input:focus, textarea:focus {
	outline-color: dodgerblue;
}

/* Card */
.card {
	border: 1px solid lightgray;
	padding: 1rem;
	margin: 1rem 0;
}

.card-header {
	display: flex;
	justify-content: space-between;
	font-family: sans-serif;
}

/* Button */
.button {
	background-color: #e7e7e7;
	border: 2px solid transparent;
	border-radius: 8px;
	color: black;
	padding: 8px 32px;
	text-align: center;
	text-decoration: none;
	display: inline-block;
	font-size: 1rem;
	font-family: sans-serif;
}

.button:hover {
	opacity: 0.8;
}

.button:active {
	border: 2px solid rgba(0, 0, 0, 0.5);
}

.button-success {
	background-color: #4caf50;
	color: white;
}
.button-primary {
	background-color: #008cba;
	color: white;
}
.button-danger {
	background-color: #f44336;
	color: white;
}

.button-small {
	font-size: 0.7rem;
}

/* Text */
.text-green {
	color: #4caf50;
}

.text-gray {
	color: grey;
}

.text-center {
	text-align: center;
}

Template partial sudah selesai. Berikutnya kita akan menggunakannya di dalam View.

Mari kita lanjut:

Membuat View Admin

View yang harus kita buat sebenarnya sudah ditentukan di Controller. Kita bisa lihat, view apa saja yang dibutuhkan di sana.

Berikut ini view yang di-load pada Controller admin:

  • dashboard.php
  • feedback_list.php
  • post_list.php
  • setting.php

Mari kita buat semuanya.

Buatlah file baru di dalam folder views/admin/ dengan nama dan isi sebagai berikut:

📜 dashboard.php

<!DOCTYPE html>
<html lang="en">

<head>
	<?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
	<main class="main">
		<?php $this->load->view('admin/_partials/side_nav.php') ?>

		<div class="content">
			<h1>Overview</h1>
			<p><b>13</b> <span class="text-gray">Post</span></p>
			<p><b>11</b> <span class="text-gray">Feedback</span></p>	
			
			<?php $this->load->view('admin/_partials/footer.php') ?>
		</div>
	</main>
</body>

</html>

📜 feedback_list.php

<!DOCTYPE html>
<html lang="en">

<head>
	<?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
	<main class="main">
		<?php $this->load->view('admin/_partials/side_nav.php') ?>

		<div class="content">
			<h1>Feedback</h1>

			<div class="card">
				<div class="card-header">
					<div>
						<b>Dian</b> <small class="text-gray">[email protected]</small>
					</div>
					<div><small class="text-gray">19 Juli 2021</small></div>
				</div>
				<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Nemo atque
					delectus nihil voluptatibus odit temporibus tempora amet quasi omnis.
				</p>
				<a href="#" class="button button-danger button-small" role="button">Delete</a>
			</div>
			<div class="card">
			<div class="card-header">
					<div>
						<b>Dian</b> <small class="text-gray">[email protected]</small>
					</div>
					<div><small class="text-gray">19 Juli 2021</small></div>
				</div>
				<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Nemo atque
					delectus nihil voluptatibus odit temporibus tempora amet quasi omnis.
				</p>
				<a href="#" class="button button-danger button-small" role="button">Delete</a>
			</div>

			<?php $this->load->view('admin/_partials/footer.php') ?>
		</div>
	</main>
</body>

</html>

📜 post_list.php

<!DOCTYPE html>
<html lang="en">

<head>
	<?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
	<main class="main">
		<?php $this->load->view('admin/_partials/side_nav.php') ?>

		<div class="content">
			<h1>List Artikel</h1>

			<div class="toolbar">
				<a href="#" class="button button-primary" role="button">+ Tulis Artikel</a>
			</div>

			<table class="table">
				<thead>
					<tr>
						<th>Title</th>
						<th style="width: 15%;" class="text-center">Status</th>
						<th style="width: 25%;" class="text-center">Action</th>
					</tr>
				</thead>
				<tbody>
					<tr>
						<td>
							<div>Hello World!</div>
							<div class="text-gray"><small>12 Jan 2021<small></div>
						</td>
						<td class="text-center text-gray">Draft</td>
						<td>
							<div class="action">
								<a href="#" class="button button-small" role="button">View</a>
								<a href="#" class="button button-small" role="button">Edit</a>
								<a href="#" class="button button-small button-danger" role="button">Delete</a>
							</div>
						</td>
					</tr>
					<tr>
						<td>
							<div>Hello World!</div>
							<div class="text-gray"><small>12 Jan 2021<small></div>
						</td>
						<td class="text-center text-green">Published</td>
						<td>
							<div class="action">
								<a href="#" class="button button-small" role="button">View</a>
								<a href="#" class="button button-small" role="button">Edit</a>
								<a href="#" class="button button-small button-danger" role="button">Delete</a>
							</div>
						</td>
					</tr>
				</tbody>
			</table>

			<?php $this->load->view('admin/_partials/footer.php') ?>
		</div>
	</main>
</body>

</html>

📜 setting.php

<!DOCTYPE html>
<html lang="en">

<head>
	<?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
	<main class="main">
		<?php $this->load->view('admin/_partials/side_nav.php') ?>

		<div class="content">
			<h1>Settings</h1>
			
			<p>Comming Soon..</p>

			<?php $this->load->view('admin/_partials/footer.php') ?>
		</div>
	</main>
</body>

</html>

Jika kita perhatikan, semua kode di view belum menggunakan data apapun.

Kita menampilkan view dengan hardcode data-data yang akan kita tampilkan. Ini agar nantinya kita mudah menentukan akan seperti apa datanya ditampilkan.

Mari kita coba lihat dulu hasilnya:

Halaman Dashboard Overview

halaman overview

Halaman List Artikel

halaman list artikel

Halaman List Feedback

list feedback

Halaman Setting

halaman setting

Terlihat bagus 😍

Tapi..

Ini hanya tampilan saja, datanya tidak dinamis karena hardcoding.

Nah, biar dinamis.. Kita akan menggunakan data dari database untuk halaman Post dan Feedback.

Mari kita mulai dari yang gampang dulu..

Yakni halaman Feedback.

Menampilkan List Feedback

Ubahlah Feedback_model.php menjadi seperti ini:

<?php

class Feedback_model extends CI_Model
{
	private $_table = "feedback";

	public function insert($feedback)
	{
		if(!$feedback){
			return;
		}

		return $this->db->insert($this->_table, $feedback);
	}

	public function get()
	{
		$query = $this->db->get($this->_table);
		return $query->result();
	}

	public function delete($id)
	{
		if(!$id){
			return;
		}

		$this->db->delete($this->_table, ['id' => $id]);
	}
}

Pada model ini kita menambahkan dua method, yakni get() dan delete().

  • Method get() berfungsi untuk mengambil semua data di tabel feedback;
  • Method delete() berfungsi untuk menghapus feedback.

Berikutnya, ubahlah Controller admin/Feedback.php menjadi seperti ini:

<?php

class Feedback extends CI_Controller
{
	public function index()
	{
		$this->load->model('feedback_model');
		$data['feedbacks'] = $this->feedback_model->get();
		$this->load->view('admin/feedback_list', $data);
	}

	public function delete($id = null)
	{
		if(!$id){
			show_404();
		}

		$this->load->model('feedback_model');
		$this->feedback_model->delete($id);

		$this->session->set_flashdata('message', 'Data was deleted');
		redirect(site_url('admin/feedback'));
	}
}

Jika kita perhatikan, pada Controller ini.. kita menggunakan library session untuk menampilkan feedback saat berhasil dihapus.

Library ini belum kita load.

Karena itu, silakan tambahkan di config/autoload.php pada bagian libraries menjadi seperti ini:

$autoload['libraries'] = array('database', 'session');

Oke, sekarang ubahlah view feedback_list.php menjadi seperti ini:

📜 views/admin/feedback_list.php

<!DOCTYPE html>
<html lang="en">

<head>
	<?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
	<main class="main">
		<?php $this->load->view('admin/_partials/side_nav.php') ?>

		<div class="content">
			<h1>Feedback</h1>

			<?php foreach($feedbacks as $feedback): ?>
			<div class="card">
				<div class="card-header">
					<div>
						<b><?= $feedback->name ?></b> <small class="text-gray"><?= $feedback->email ?></small>
					</div>
					<div><small class="text-gray"><?= $feedback->created_at ?></small></div>
				</div>
				<p><?= $feedback->message ?></p>
				<a href="#" 
					data-delete-url="<?= site_url('admin/feedback/delete/'.$feedback->id) ?>" 
					class="button button-danger button-small" 
					role="button"
					onclick="deleteConfirm(this)">Delete</a>
			</div>
			<?php endforeach ?>

			<?php $this->load->view('admin/_partials/footer.php') ?>
		</div>
	</main>

	<script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script>
	<script>
		function deleteConfirm(event){
			Swal.fire({
				title: 'Delete Confirmation!',
				text: 'Are you sure to delete the item?',
				icon: 'warning',
				showCancelButton: true,
				cancelButtonText: 'No',
				confirmButtonText: 'Yes Delete',
				confirmButtonColor: 'red'
			}).then(dialog => {
				if(dialog.isConfirmed){
					window.location.assign(event.dataset.deleteUrl);
				}
			});
		}
	</script>

	<?php if($this->session->flashdata('message')): ?>
		<script>
			const Toast = Swal.mixin({
				toast: true,
				position: 'top-end',
				showConfirmButton: false,
				timer: 3000,
				timerProgressBar: true,
				didOpen: (toast) => {
					toast.addEventListener('mouseenter', Swal.stopTimer)
					toast.addEventListener('mouseleave', Swal.resumeTimer)
				}
			})

			Toast.fire({
				icon: 'success',
				title: '<?= $this->session->flashdata('message') ?>'
			})
		</script>
	<?php endif ?>
</body>

</html>

Pada view ini, kita menggunakan library SweetAlert2 untuk menampilkan dialog konfirmasi dan pesan Toast saat datanya berhasil dihapus.

Mari kita uji coba!

Wuhuuu.. keren 😍

Nah, biar makin bagus..

Tampilkan juga view saat feedback-nya kosong.

Kita bisa buat view baru dengan nama feedback_empty.php di dalam folder views/admin/ dengan isi seperti ini:

<!DOCTYPE html>
<html lang="en">

<head>
	<?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
	<main class="main">
		<?php $this->load->view('admin/_partials/side_nav.php') ?>

		<div class="content">
			<h1>Feedback is Empty</h1>

			<p>No Feedback to show</p>

			<?php $this->load->view('admin/_partials/footer.php') ?>
		</div>
	</main>
</body>

</html>

Kemudian, ubah Controller Feedback pada method index() menjadi seperti ini:

public function index()
{
	$this->load->model('feedback_model');
	$data['feedbacks'] = $this->feedback_model->get();
	if(count($data['feedbacks']) <= 0){
		$this->load->view('admin/feedback_empty');
	} else {
		$this->load->view('admin/feedback_list', $data);
	}
}

Maka hasilnya:

feedback empty

Yoshh!! Halaman feedback sudah beres.

Berikutnya silakan lanjut ke:

Membuat CRUD Artikel

Kita sudah membuat view untuk halaman artikel secara hardcode.

Nah, sekarang saatnya kita membuatnya hidup dan berfungsi seperti yang kita harapkan.

Baiklah, mari kita mulai!

1. Ubah Model Article

Ubahlah model Article_model.php menjadi seperti ini:

<?php

class Article_model extends CI_Model
{

	private $_table = 'article';

	public function get()
	{
		$query = $this->db->get($this->_table);
		return $query->result();
	}

	public function get_published($limit = null, $offset = null)
	{
		if (!$limit && $offset) {
			$query = $this->db
				->get_where($this->_table, ['draft' => 'FALSE']);
		} else {
			$query =  $this->db
				->get_where($this->_table, ['draft' => 'FALSE'], $limit, $offset);
		}
		return $query->result();
	}

	public function find_by_slug($slug)
	{
		if (!$slug) {
			return;
		}
		$query = $this->db->get_where($this->_table, ['slug' => $slug]);
		return $query->row();
	}

	public function find($id)
	{
		if (!$id) {
			return;
		}

		$query = $this->db->get_where($this->_table, array('id' => $id));
		return $query->row();
	}

	public function insert($article)
	{
		return $this->db->insert($this->_table, $article);
	}

	public function update($article)
	{
		if (!isset($article['id'])) {
			return;
		}

		return $this->db->update($this->_table, $article, ['id' => $article['id']]);
	}

	public function delete($id)
	{
		if (!$id) {
			return;
		}

		return $this->db->delete($this->_table, ['id' => $id]);
	}
}

Pada Model Article_model.php kita menambahkan beberapa method yang akan dibutuhkan untuk operasi data.

  • Method get() untuk mengambil semua artikel dari database;
  • Method find() untuk mengambil satu artikel saja dengan id tertentu;
  • Method insert() untuk menambahkan artikel baru;
  • Method update() untuk meng-update artikel;
  • dan method delete() untuk menghapus artikel.

Berikutnya, lanjutkan:

2. Ubah Controller Admin Post

Ubahlah Controller admin/Post.php menjadi seperti ini:

<?php

class Post extends CI_Controller
{
	public function __construct()
	{
		parent::__construct();
		$this->load->model('article_model');
	}

	public function index()
	{
		$data['articles'] = $this->article_model->get();
		$this->load->view('admin/post_list.php', $data);
	}

	public function new()
	{
		if ($this->input->method() === 'post') {
			// TODO: Lakukan validasi sebelum menyimpan ke model

			// generate unique id and slug
			$id = uniqid('', true);
			$slug = url_title($this->input->post('title'), 'dash', TRUE) . '-' . $id;

			$article = [
				'id' => $id,
				'title' => $this->input->post('title'),
				'slug' => $slug,
				'content' => $this->input->post('content'),
				'draft' => $this->input->post('draft')
			];

			$saved = $this->article_model->insert($article);

			if ($saved) {
				$this->session->set_flashdata('message', 'Article was created');
				return redirect('admin/post');
			}
		}

		$this->load->view('admin/post_new_form.php');
	}

	public function edit($id = null)
	{
		$data['article'] = $this->article_model->find($id);

		if (!$data['article'] || !$id) {
			show_404();
		}

		if ($this->input->method() === 'post') {
			// TODO: lakukan validasi data sebelum simpan ke model
			$article = [
				'id' => $id,
				'title' => $this->input->post('title'),
				'content' => $this->input->post('content'),
				'draft' => $this->input->post('draft')
			];
			$updated = $this->article_model->update($article);
			if ($updated) {
				$this->session->set_flashdata('message', 'Article was updated');
				redirect('admin/post');
			}
		}

		$this->load->view('admin/post_edit_form.php', $data);
	}

	public function delete($id = null)
	{
		if (!$id) {
			show_404();
		}

		$deleted = $this->article_model->delete($id);
		if ($deleted) {
			$this->session->set_flashdata('message', 'Article was deleted');
			redirect('admin/post');
		}
	}
}

Ada beberapa method yang kita tambahkan dan ubah di sini:

  • Method __construct() konstruktor untuk load model Article_model.php secara default;
  • Method index() untuk menampilkan list artikel baik yang statusnya sudah terbit maupun draft;
  • Method new() untuk membuat atau menambahkan artikel baru;
  • Method edit() untuk mengubah artikel tertentu;
  • dan method delete() untuk menghapus artikel.

Pada method new() kita menggunakan fungsi url_title() dari helper url untuk membuat slug dan uniqid() untuk membuat id unik.

// generate unique id and slug
$id = uniqid('', true);
$slug = url_title($this->input->post('title'), 'dash', TRUE) . '-' . $id;

Kita juga menggunakan library session pada method new(), edit(), dan delete() untuk menampilkan flash data atau message.

$this->session->set_flashdata('message', 'Article was updated');

Ini nanti akan ditampilkan dengan Toast dari SweetAlert2.

Sekarang mari kita lanjut mengubah view.

3. Ubah View Admin Post

Pertama ubahlah view admin/post_list.php menjadi seperti ini:

📜 views/admin/post_list.php

<!DOCTYPE html>
<html lang="en">

<head>
	<?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
	<main class="main">
		<?php $this->load->view('admin/_partials/side_nav.php') ?>

		<div class="content">
			<h1>List Artikel</h1>

			<div class="toolbar">
				<a href="<?= site_url('admin/post/new') ?>" class="button button-primary" role="button">+ Tulis Artikel</a>
			</div>

			<table class="table">
				<thead>
					<tr>
						<th>Title</th>
						<th style="width: 15%;" class="text-center">Status</th>
						<th style="width: 25%;" class="text-center">Action</th>
					</tr>
				</thead>
				<tbody>
					<?php foreach($articles as $article): ?>
					<tr>
						<td>
							<div><?= $article->title ?></div>
							<div class="text-gray"><small><?= $article->created_at ?><small></div>
						</td>
						<?php if($article->draft === 'true'): ?>
							<td class="text-center text-gray">Draft</td>
						<?php else: ?>
							<td class="text-center text-green">Published</td>
						<?php endif ?>
						<td>
							<div class="action">
								<a href="<?= site_url('article/'.$article->slug) ?>" class="button button-small" target="_blank" role="button">Preview</a>
								<a href="<?= site_url('admin/post/edit/'.$article->id) ?>" class="button button-small" role="button">Edit</a>
								<a href="#" 
									data-delete-url="<?= site_url('admin/post/delete/'.$article->id) ?>" 
									class="button button-small button-danger" 
									role="button"
									onclick="deleteConfirm(this)">Delete</a>
							</div>
						</td>
					</tr>
					<?php endforeach ?>
				</tbody>
			</table>

			<?php $this->load->view('admin/_partials/footer.php') ?>
		</div>
	</main>

	<script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script>
	<script>
		function deleteConfirm(event){
			Swal.fire({
				title: 'Delete Confirmation!',
				text: 'Are you sure to delete the item?',
				icon: 'warning',
				showCancelButton: true,
				cancelButtonText: 'No',
				confirmButtonText: 'Yes Delete',
				confirmButtonColor: 'red'
			}).then(dialog => {
				if(dialog.isConfirmed){
					window.location.assign(event.dataset.deleteUrl);
				}
			});
		}
	</script>

	<?php if($this->session->flashdata('message')): ?>
		<script>
			const Toast = Swal.mixin({
				toast: true,
				position: 'top-end',
				showConfirmButton: false,
				timer: 3000,
				timerProgressBar: true,
				didOpen: (toast) => {
					toast.addEventListener('mouseenter', Swal.stopTimer)
					toast.addEventListener('mouseleave', Swal.resumeTimer)
				}
			})

			Toast.fire({
				icon: 'success',
				title: '<?= $this->session->flashdata('message') ?>'
			})
		</script>
	<?php endif ?>
</body>

</html>

Berikutnya kita membutuhkan view untuk form add dan form edit.

Silakan buat view baru di dalam folder 📁 views/admin/ dengan nama post_new_form.php dan post_edit_form.php dengan isi sebagai berikut:

📜 views/admin/post_new_form.php

<!DOCTYPE html>
<html lang="en">

<head>
	<?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
	<main class="main">
		<?php $this->load->view('admin/_partials/side_nav.php') ?>

		<div class="content">
			<h1>Write new Article</h1>

			<form action="" method="POST">
				<label for="title">Title*</label>
				<input type="text" name="title" placeholder="Judul artikel" required title="Wajib tulis judul artikel"/>
				
				<label for="content">Konten</label>
				<textarea name="content" cols="30" rows="10" placeholder="Tuliskan isi pikiranmu..."></textarea>

				<div>
					<button type="submit" name="draft" class="button" value="true">Save to Draft</button>
					<button type="submit" name="draft" class="button button-primary" value="false">Publish</button>
				</div>
			</form>

			<?php $this->load->view('admin/_partials/footer.php') ?>
		</div>
	</main>
</body>

</html>

📜 views/admin/post_edit_form.php

<!DOCTYPE html>
<html lang="en">

<head>
	<?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
	<main class="main">
		<?php $this->load->view('admin/_partials/side_nav.php') ?>

		<div class="content">
			<h1>Edit Article</h1>

			<form action="" method="POST">
				<label for="title">Title*</label>
				<input type="text" name="title" 
					placeholder="Judul artikel" 
					required 
					title="Wajib tulis judul artikel"
					value="<?= $article->title ?>"/>
				
				<label for="content">Konten</label>
				<textarea name="content" cols="30" rows="10" placeholder="Tuliskan isi pikiranmu..."><?= $article->content ?></textarea>

				<div>
					<button type="submit" name="draft" class="button" value="true">Save to Draft</button>
					<button type="submit" name="draft" class="button button-primary" value="false">Publish Update</button>
				</div>
			</form>

			<?php $this->load->view('admin/_partials/footer.php') ?>
		</div>
	</main>
</body>

</html>

Nah, sekarang semua sudah siap..

Mari kita lakukan:

4. Percobaan

Percobaan membuka halaman admin list artikel:

admin test list artikel

Jika kita sudah pernah menambahkan artikel, maka artikelnya akan ditampilkan.

Berikutnya, cobalah untuk membuat artikel baru.

Coba juga untuk edit artikelnya.

Terakhir coba hapus artikelnya.

Semua berhasil tanpa error.

Tinggal sentuhan terakhir untuk artikel:

5. Membuat View Saat Artikel Kosong

Saat artikel kosong, halaman admin post hanya akan menampilkan header dari tabel saja seperti ini:

admin post empty

Namun, kita ingin yang ditampilkan adalah pesan kalau artikelnya kosong.

Kita bisa melakukannya dengan membuat view baru seperti halaman feedback, atau juga membuat logika di dalam view untuk menampilkan pesan “artikel kosong”.

Biar konsisten, kita ikuti cara seperti yang di halaman feedback. Yakni membuat view baru.

Buatlah view baru dalam folder views/admin dengan nama post_empty.php dengan isi sebagai berikut:

📜 views/admin/post_empty.php

<!DOCTYPE html>
<html lang="en">

<head>
	<?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
	<main class="main">
		<?php $this->load->view('admin/_partials/side_nav.php') ?>

		<div class="content">
			<h1>Article is Empty</h1>
			<p>No Article to show. Please create new article.</p>

			<div>
				<a href="<?= site_url('admin/post/new') ?>" class="button button-primary">+ Create New Article</a>
			</div>

			<?php $this->load->view('admin/_partials/footer.php') ?>
		</div>
	</main>
</body>

</html>

Kemudian ubah method index() pada Controller admin/Post.php menjadi seperti ini:

public function index()
{
	$data['articles'] = $this->article_model->get();
	if(count($data['articles']) <= 0){
		$this->load->view('admin/post_empty.php');
	} else {
		$this->load->view('admin/post_list.php', $data);
	}
}

Sekarang coba hapus semua artikel, maka hasilnya:

post empty

Mantap!

Tinggal terakhir nih:

Perbaiki Halaman Overview

Halaman overview akan kita gunakan untuk menampilkan ada berapa total artikel yang sudah dibuat dan total feedback yang sudah didapatkan.

Mari kita buat modelnya terlebih dahulu.

Silakan tambahkan method count() pada model Article_model.php dan Feedback_model.php seperti ini:

📜 models/Article_model.php

public function count(){
	return $this->db->count_all($this->_table);
}

📜 models/Feedback_model.php

public function count(){
	return $this->db->count_all($this->_table);
}

Fungsi ini akan mengembalikan nilai berupa integer sesuai dengan jumlah data yang ada pada tabel.

Berikutnya silakan ubah controller admin/Dashboad.php menjadi seperti ini:

<?php

class Dashboard extends CI_Controller
{
	public function index()
	{
		$this->load->model('article_model');
		$this->load->model('feedback_model');
		
		$data = [
			"article_count" => $this->article_model->count(),
			"feedback_count" => $this->feedback_model->count()
		];

		$this->load->view('admin/dashboard.php', $data);
	}
}

Nah, sekarang ubahlah view untuk halaman overview menjadi seperti ini:

📜 views/admin/dashboard.php

<!DOCTYPE html>
<html lang="en">

<head>
  <?php $this->load->view('admin/_partials/head.php') ?>
</head>

<body>
  <main class="main">
    <?php $this->load->view('admin/_partials/side_nav.php') ?>

    <div class="content">
      <h1>Overview</h1>

      <div style="display:flex; gap: 1em">
        <div class="card text-center" style="width: 100px;">
          <h2>
            <?= $article_count ?>
          </h2>
          <p><a href="<?= site_url('admin/post') ?>">Artikel</a></p>
        </div>
        <div class="card text-center" style="width: 100px;">
          <h2>
            <?= $feedback_count ?>
          </h2>
          <p><a href="<?= site_url('admin/feedback') ?>">Feedback</a></p>
        </div>
      </div>

      <?php $this->load->view('admin/_partials/footer.php') ?>
    </div>
  </main>
</body>

</html>

Hasilnya:

overview page

Mantap!

Apa Selanjutnya?

Halaman admin hampir jadi. Tinggal membuat fitur untuk Setting dan Login/Logout aja nih.

Tapi sebelum itu, silakan pelajari dulu tentang validasi data.

Jika kamu mendapatkan masalah atau error dan ingin bertanya, mari sampaikan di komentar.

Source code dari tutorial ini bisa kamu download di Github.

[🎁 Download Source Code]