author Ahmad Muhardian

Tutorial Codeigniter #09: Membuat Fitur Login untuk Admin


Tutorial Membuat Login di Codeigniter

Tutorial ini merupakan lanjutan dari tutorial sebelumnya:

Pada tutorial ini, kita akan membuat fitur login untuk admin dengan library session bawaan dari Codeigniter.

Mari kita mulai..

Apa itu Session?

Dalam ilmu komputer atau jaringan komptuer, Session atau sesi merupakan informasi sementara yang disimpan saat dua buah pernagkat atau komputer saat saling berkomunikasi atau bertukar data. 1

Ingat kata kucinya: Informasi sementara

Jadi, ketika kita membuka website.. di sana bisa kita katakan sedang memulai sebuah sesi baru.

Lalu ketika kita menutup website, berarti sesi kita akhiri.

Data sementara yang disimpan di dalam session, bisa kita pakai untuk authentication atau login.

Data session bisa kita simpan di dalam client dan juga server.

Data session yang disimpan di dalam client, akan hilang saat browser atau tab ditutup. Sedangkan session yang disimpan di dalam server akan hilang saat server malakukan restart atau dihapus manual.

Nah, pada tutorial ini.. kita akan membuat login dengan menyimpan session di dalam server.

Mengenal Library Session

Sebenarnya PHP sendiri sudah menyediakan fitur session yang bisa diakses dari variabel global $_SESSION.

Namun, jika kita menggunakan session bawaan PHP, kita harus memanggil fungsi session_start() di awal eksekusi.

Nah, pada Codeigniter.. kita tidak perlu memanggil fungsi session_start().

Kita cukup pakai library session yang sudah disediakan oleh Codeigniter.

Cara Load Library Session

Silahkan buka file config/autoload.php kemudian, pada bagian libraries.. tambahkan session seperti ini:

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

Maka library session sudah diload otomatis dan akan bisa kita gunakan dari aplikasi Codeigniter.

Cara Menggunakan Library Session

Kita bisa menggunakan library session dengan method seperti ini:

$this->session->nama_method_session();

Ada beberapa method yang akan sering kita gunakan pada library session.

// flash data untuk data sementara
$this->session->set_flashdata('key');
$this->session->flash_data('key');

// user data untuk authenikasi
$this->session->set_userdata('key');
$this->session->userdata('key');
$this->session->has_userdata('key');

// menghapus session
$this->session->unset_userdata('key');
// hapus semua session
$this->session->sess_destory();

Parameter key kita perlukan untuk membuat dan mengakses isi session.

Penjelasan lebih detail tentang library ini, bisa juga kamu baca di dokumentasi library session.

Oke sekarang..

Biar lebih paham, langsung saja kita praktik.

1. Membuat Tabel User

Buatlah tabel baru bernama user dengan struktur seperti ini:

struktur tabel user

Biar cepat, Kamu bisa gunakan query SQL berikut:

CREATE TABLE `user` (
  `id` varchar(32) NOT NULL,
  `name` varchar(32) NOT NULL,
  `email` varchar(64) NOT NULL,
  `username` varchar(64) NOT NULL,
  `password` varchar(255) NOT NULL,
  `avatar` varchar(32) DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `last_login` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

Jalankan kode SQL ini pada database beritacoding di menu SQL.

menjalankan kode sql

Setelah itu, tambahkan satu data dengan menjalankan kode SQL berikut.

INSERT INTO `user` (`id`, `name`, `email`, `username`, `password`, `avatar`, `created_at`, `last_login`) VALUES
('6118b2a943acc2.78631959', 'Administrator', '[email protected]', 'admin', '$2y$10$hRi1qju2KOeEPcBZ0wYfhu/PN5e9Wl.ddWeDTds8Uokad764X9D1a', NULL, '2021-08-15 06:22:33', '2021-08-19 15:55:42');

Maka kita akan punya data baru dengan:

Password kita simpan dalam bentuk hash dengan fungsi password_hash() dan algoritma PASSWORD_DEFAULT.

2. Membuat Model Auth

Buatlah model baru dengan nama Auth_model.php dengan isi sebagai berikut:

<?php

class Auth_model extends CI_Model
{
	private $_table = "user";
	const SESSION_KEY = 'user_id';

	public function rules()
	{
		return [
			[
				'field' => 'username',
				'label' => 'Username or Email',
				'rules' => 'required'
			],
			[
				'field' => 'password',
				'label' => 'Password',
				'rules' => 'required|max_length[255]'
			]
		];
	}

	public function login($username, $password)
	{
		$this->db->where('email', $username)->or_where('username', $username);
		$query = $this->db->get($this->_table);
		$user = $query->row();

		// cek apakah user sudah terdaftar?
		if (!$user) {
			return FALSE;
		}

		// cek apakah passwordnya benar?
		if (!password_verify($password, $user->password)) {
			return FALSE;
		}

		// bikin session
		$this->session->set_userdata([self::SESSION_KEY => $user->id]);
		$this->_update_last_login($user->id);

		return $this->session->has_userdata(self::SESSION_KEY);
	}

	public function current_user()
	{
		if (!$this->session->has_userdata(self::SESSION_KEY)) {
			return null;
		}

		$user_id = $this->session->userdata(self::SESSION_KEY);
		$query = $this->db->get_where($this->_table, ['id' => $user_id]);
		return $query->row();
	}

	public function logout()
	{
		$this->session->unset_userdata(self::SESSION_KEY);
		return !$this->session->has_userdata(self::SESSION_KEY);
	}

	private function _update_last_login($id)
	{
		$data = [
			'last_login' => date("Y-m-d H:i:s"),
		];

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

Terdapat empat method di dalam model ini:

  1. Method login() untuk melakukan login dengan input berupa username dan password. Fungsi ini mengembalikan nilai TRUE jika berhasil login, sebaliknya akan mengembalikan FALSE jika gagal login;
  2. Method current_user() untuk mendapatkan data user yang sedang login. Fungsi ini akan menghasilkan null jika user tidak sedang login, dan akan menghasilkan data objek dari user yang sedang login jika status user sedang login.
  3. Method logout() untuk melakukan logout atau menghapus session;
  4. Method _update_last_login() berfungsi untuk mengupdate tanggal last_login.

3. Membuat Controller Auth

Buatlah Controller baru dengan nama Auth.php dengan isi sebagai berikut:

<?php

class Auth extends CI_Controller
{
	public function index()
	{
		show_404();
	}

	public function login()
	{
		$this->load->model('auth_model');
		$this->load->library('form_validation');

		$rules = $this->auth_model->rules();
		$this->form_validation->set_rules($rules);

		if($this->form_validation->run() == FALSE){
			return $this->load->view('login_form');
		}

		$username = $this->input->post('username');
		$password = $this->input->post('password');

		if($this->auth_model->login($username, $password)){
			redirect('admin');
		} else {
			$this->session->set_flashdata('message_login_error', 'Login Gagal, pastikan username dan passwrod benar!');
		}

		$this->load->view('login_form');
	}

	public function logout()
	{
		$this->load->model('auth_model');
		$this->auth_model->logout();
		redirect(site_url());
	}
}

Pada Controller Auth, kita membuat dua method penting yakni:

  1. login() untuk menampilkan form login dan memproses login;
  2. dan logout() untuk melakukan logout.

Sementara itu, method index() tidak kita pakai. Maka kita bisa panggil show_404() di sana.

Oke lanjut..

Sekarang kita harus:

4. Membuat View Form Login

Kita membutuhkan view untuk menampilkan form login.

Buatlah file baru bernama login_form.php di dalam folder views dengan isi sebagai berikut:

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

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

<body>
	<?php $this->load->view('_partials/navbar.php'); ?>

	<div class="container">
		<h1>Login</h1>
		<p>Masuk ke Dashboard</p>

		<?php if($this->session->flashdata('message_login_error')): ?>
			<div class="invalid-feedback">
					<?= $this->session->flashdata('message_login_error') ?>
			</div>
		<?php endif ?>

		<form action="" method="post" style="max-width: 600px;">
			<div>
				<label for="name">Email/Username*</label>
				<input type="text" name="username" class="<?= form_error('username') ? 'invalid' : '' ?>"
					placeholder="Your username or email" value="<?= set_value('username') ?>" required />
				<div class="invalid-feedback">
					<?= form_error('username') ?>
				</div>
			</div>
			<div>
				<label for="password">Password*</label>
				<input type="password" name="password" class="<?= form_error('password') ? 'invalid' : '' ?>"
					placeholder="Enter your password" value="<?= set_value('password') ?>" required />
				<div class="invalid-feedback">
					<?= form_error('password') ?>
				</div>
			</div>

			<div>
				<input type="submit" class="button button-primary" value="Login">
			</div>
		</form>
	</div>
	<?php $this->load->view('_partials/footer.php'); ?>
</body>

</html>

Sejauh ini, fitur login sudah bisa dicoba.

Namun, belum bisa melindungi halaman admin.

Karena itu, silahkan lanjutkan ke:

5. Mengubah Controller Admin

Kita ingin setiap membuat halaman admin, user harus login terlebih dahulu.

Ini bisa kita lakukan dengan memanggil fungsi current_user() pada konstruktor Controller halaman admin.

Mari kita ubah semuanya..

Ubahlah Controller πŸ“œ admin/Dashboard.php menjadi seperti ini:

<?php

class Dashboard extends CI_Controller
{
	public function __construct()
	{
		parent::__construct();
		$this->load->model('auth_model');
		if(!$this->auth_model->current_user()){
			redirect('auth/login');
		}
	}

	// ... ada kode lain di sini ...
}

Lalu ubah juga Controller πŸ“œ admin/Feedback.php menjadi seperti ini:

<?php

class Feedback extends CI_Controller
{
	public function __construct()
	{
		parent::__construct();
		$this->load->model('auth_model');
		if(!$this->auth_model->current_user()){
			redirect('auth/login');
		}
	}

	// ... ada kode lain di sini ...
}

Ubah Controller πŸ“œ admin/Post.php menjadi seperti ini:

<?php

class Post extends CI_Controller
{
	public function __construct()
	{
		parent::__construct();
		$this->load->model('article_model');
		$this->load->model('auth_model');
		if(!$this->auth_model->current_user()){
			redirect('auth/login');
		}
	}
	
	// ... ada kode lain di sini ...
}

Terakhir, ubah Controller πŸ“œ admin/Setting.php menjadi seperti ini:

<?php

class Setting extends CI_Controller
{
	public function __construct()
	{
		parent::__construct();
		$this->load->model('auth_model');
		if(!$this->auth_model->current_user()){
			redirect('auth/login');
		}
	}

	// ... ada kode lain di sini ...
}

Dengan begini, saat kita membuka controller admin, maka kita akan diminta login terlebih dahulu.

6. Percobaan

Sekarang cobalah melakukan login dengan membuka

localhost/beritacoding/index.php/auth/login

atau

beritacoding.test/index.php/auth/login

Silahkan isi username dengan admin dan password admin.

form login

Jika berhasil login, maka kita akan dialihkan ke halaman admin.

Akan tetapi, jika kita memasukan username dan password yang salah.. maka login akan gagal dan tetap akan berada di halaman login.

form login error

Setelah berhasil login, coba sekarang lakukan logout.

Tombol logout

Maka kita akan dibawa lagi ke halaman login.

Untuk memastikan halaman admin diproteksi dengan login, coba buka kembali halaman admin setelah melakukan logout.

beritacoding.test/index.php/admin

Jika halaman admin berhasil terbuka, berarti fitur login belum bekerja sesuai yang diharapkan.

Akan tetapi, jika kita dialihkan ke halaman login. Berarti kita sudah berhasil membuat halaman login.

7. Menampilkan User yang Sedang Login

Kita ingin menampilkan data user yang sedang login di bagian navbar.

Gimana cara mendapatkan data usernya?

Kita bisa manfaatkan method current_user() dari model Auth_model.

Kita akan banyak mengubah controller admin, karena semua view admin melakukan load view navbar.

Mari kita kerjakan satu per satu!

1. Mengubah Controller Admin

Ubahlah Controller admin/Dashboard.php, pada method index() tambahkan data current_user seperti ini:

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

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

Berikutnya, ubahlah controller admin/Feedback.php pada method index(), tambahkan data current_user seperti ini:

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

Berikutnya, tambahkan data current_user pada controller admin/Post.php seperti ini:

<?php

class Post extends CI_Controller
{
	public function __construct()
	{
		parent::__construct();
		$this->load->model('article_model');
		$this->load->model('auth_model');
		if(!$this->auth_model->current_user()){
			redirect('auth/login');
		}
	}

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

	public function new()
	{
		$data['current_user'] = $this->auth_model->current_user();
		$this->load->library('form_validation');
		if ($this->input->method() === 'post') {
			// Lakukan validasi sebelum menyimpan ke model
			$rules = $this->article_model->rules();
			$this->form_validation->set_rules($rules);

			if($this->form_validation->run() === FALSE){
				return $this->load->view('admin/post_new_form.php', $data);
			}

			// 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', $data);
	}

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

		if (!$data['article'] || !$id) {
			show_404();
		}
		
		if ($this->input->method() === 'post') {
			// lakukan validasi data seblum simpan ke model
			$rules = $this->article_model->rules();
			$this->form_validation->set_rules($rules);

			if($this->form_validation->run() === FALSE){
				return $this->load->view('admin/post_edit_form.php', $data );
			}

			$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);
	}

	// ... ada kode lain di sini ...
}

Terakhir ubahlah controller admin/Setting.php, pada method index() tambahkan data current_user seperti ini:

public function index()
{
	$data['current_user'] = $this->auth_model->current_user();
	$this->load->view('admin/setting', $data);
}

Urusan dengan Controller sudah beres.

2. Mengubah View Side Nav

Berikutnya, ubahlah view views/admin/_partials/side_nav.php menjadi seperti ini:

<aside class="side-nav">
	<div class="brand">
		<h2>Berita Coding</h2>
		<div style="display: flex; gap: 0.8rem; margin:1rem 0;">
			<?php
			$avatar = $current_user->avatar ?
				base_url('upload/avatar/' . $current_user->avatar)
				: get_gravatar($current_user->email)
			?>
			<img src="<?= $avatar ?>" alt="<?= htmlentities($current_user->name, TRUE) ?>" height="32" width="32">
			<div>
				<b><?= htmlentities($current_user->name) ?></b>
				<small><?= htmlentities($current_user->email) ?></small>
			</div>
		</div>
	</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>

Pada view ini, kita menggunakan fungsi get_gravatar() untuk menampilkan avatar user secara default.

Fungsi ini belum kita buat.

Karena itu, silahkan lanjutkan:

3. Membuat Helper untuk Avatar

Buatlah file baru di dalam πŸ“application/helpers dengan nama gravatar_helper.php dan isi sebagai berikut:

<?php
/**
 * Get either a Gravatar URL or complete image tag for a specified email address.
 *
 * @param string $email The email address
 * @param string $s Size in pixels, defaults to 80px [ 1 - 2048 ]
 * @param string $d Default imageset to use [ 404 | mp | identicon | monsterid | wavatar ]
 * @param string $r Maximum rating (inclusive) [ g | pg | r | x ]
 * @param boole $img True to return a complete IMG tag False for just the URL
 * @param array $atts Optional, additional key/value attributes to include in the IMG tag
 * @return String containing either just a URL or a complete image tag
 * @source https://gravatar.com/site/implement/img/php/
 */
function get_gravatar( $email, $s = 80, $d = 'mp', $r = 'g', $img = false, $atts = array() ) {
    $url = 'https://www.gravatar.com/avatar/';
    $url .= md5( strtolower( trim( $email ) ) );
    $url .= "?s=$s&d=$d&r=$r";
    if ( $img ) {
        $url = '<img src="' . $url . '"';
        foreach ( $atts as $key => $val )
            $url .= ' ' . $key . '="' . $val . '"';
        $url .= ' />';
    }
    return $url;
}

Fungsi helper ini untuk mengambil gambar dari website gravatar.com berdasarkan alamat email yang kita berikan pada parameter.

Agar dapat menggunakan Helper ini, silahkan tambahkan di dalam autoload.

Buka file πŸ“œ application/config/autoload.php, kemudian pada bagian $autoload['helper'] tambahkan gravatar.

Sehingga kodenya akan menjadi seperti ini:

$autoload['helper'] = array('url', 'gravatar');

Dengan begitu, kita bisa menggunakan fungsi get_gravatar() di mana saja.

Oke sekarang mari kita coba:

4. Percobaan

Bukalah halaman admin..

Maka akan bisa melihat data user yang sedang login seperti ini:

logged user

Mantap πŸ‘

Apa Selanjutnya?

Kita sudah berhasil membuat fitur login untuk admin.

Namun, sepertinya masih ada yang kurang…

Yap! kita belum membuat fitur untuk setting atau ubah nama dan avatar admin.

Karena itu silahkan lanjutkan ke:

Jika ada pertanyaan pada tutorial ini, mari sampaikan di kometar!

[🎁 Download Source Code]