author Ahmad Muhardian

Tutorial Codeigniter 4: Migrasi Database


Codeigniter4 Migration

Sebelum kita masuk membahas tentang CRUD di Codeigniter 4, kita bahas dulu tentang migrasi database.

Apa itu migrasi database?

Mengapa kita membutuhkan migrasi database?

..dan bagaimana cara migrasi database di Codeigniter 4?

Mari kita mulai.

Apa itu Migrasi Database?

Migrasi artinya berpindah.

Migrasi manusia = perpindahan manusia dan menetap di suatu tempat.

human migration

Nah, kalau migrasi database apa?

Migrasi database adalah perpindahan database dari suatu tempat ke tempat yang lain. Misalnya database di localhost ke server production.

Perpindahan ini biasanya kita lakukan dengan manual, yakni dengan cara dump dan export database di localhost.. lalu mengimpornya di server production.

database migration

Cara ini memang bisa dilakukan.

Tapi masalanya:

Jika nanti kita bekerja dengan tim.. Saat perubahan skema database terjadi, maka tim yang lain juga harus mengikuti.

Mau tidak mau, kita harus dump dan export skema milik kita dan memberikan ke semua anggota tim yang terlibat. Belum lagi versi database yang mereka gunakan beragam.

Bisa jadi ini akan menghambat kita dalam membuat aplikasi.

Contoh kasus lain:

lupa backup

Karena itulah, kita membutuhkan migrasi database agar bisa menyimpan semua perubahan sekeman yang kita lakukan.

Salah satu program untuk melakukan migrasi database yang bisa digunakan di PHP adalah Spinx.

Buat kamu yang tertarik dengan Spinx, bisa baca-baca di:

Namun, pada tutorial ini.. kita tidak akan menggunakan Spinx, karena Codeigniter sendiri udah punya fitur untuk migrasi database.

Lalu, bagaimana cara menggunakannya?

Migrasi Database di Codeigntier

Migrasi database sebelumnya (pada Codeigniter 3) dilakukan dengan class CI_Migration, lalu memanggil class tersebut di Controller.

Pada Codeigniter 4.. kita sudah disediakan program khusus, yakni melalui spark.

Perintah-perintah untuk membuat migrasi database dengan spark, bisa kita lihat dengan perintah php spark --help.

perintah migrasi database

Ketujuh perintah inilah yang akan kita gunakan untuk membuat migrasi database. Berikut ini penjelasannya:

  • db:create untuk membuat database baru;
  • db:table untuk melihat informasi tabel;
  • db:seed untuk membuat data awal (benih data);
  • migrate untuk melakukan migrasi (menjalankan method up());
  • migrate:create atau make:migration untuk membuat file migrasi;
  • migrate:refresh untuk melakukan rollback dan melakukan migrasi perubahan terbaru;
  • migrate:rollback untuk melakukan rollback pada versi tertentu (menjalankan method down());
  • migrate:status untuk melihat status migrasi;
  • make:seeder untuk membuat file seeder.

Jika kamu bingung dengan cara menggunakan perintah tersebut, bisa lihat bantuannya dengan perintah:

php spark help <perintah>

Contoh:

php spark help migrate:create

Maka akan ditampilkan cara menggunaknya.

migrate help

Mungkin akan lebih jelas, jika kita mencobanya sendiri.

Baiklah..

Mari kita coba!

Tapi sebelum itu, lakukan dulu:

Konfigurasi Database di Codeigniter 4

Pertama, jangan lupa rename file env menjadi .env agar bisa dibaca di CI.

Kemudian buka file .env dan ubahlah konfigurasi database menjadi seperti ini:

#------------------------------------------------------------------
# DATABASE
#------------------------------------------------------------------

database.default.hostname = localhost
database.default.database = ci_news
database.default.username = root
database.default.password = 
database.default.DBDriver = MySQLi

Untuk username dan password, sesuaikan dengan username dan password pada server MySQL yang kamu gunakan.

Sebagai contoh:

Saya sudah pernah mengubha username dan password di server MySQL saya dengan admin dan password 123, maka dikonfigurasi saya harus mengisi seperti ini:

#------------------------------------------------------------------
# DATABASE
#------------------------------------------------------------------

database.default.hostname = localhost
database.default.database = ci_news
database.default.username = admin
database.default.password = 123
database.default.DBDriver = MySQLi

Jika kita salah memasukan username dan password, bisa jadi aplikasi tidak akan bisa terhubung dengan server database.

Setelah itu, buatlah database baru dengan nama ci_news. Ini bisa dilakukan melalui command line atau Phpmyadmin.

Membuat database baru dengan spark:

Jalankan perintah ini untuk membuat database baru.

php spark db:create ci_news

Perintah ini akan membuat database baru dengan nama ci_news.

Selain menggunakan cara ini, kamu juga bisa membuat database dari Phpmyadmin.

Membuat database baru melalui Phpmyadmin:

create database

..dam jika kamu ingin membuat database dari command line:

Buka shell MySQL, lalu ketik perintah berikut.

CREATE DATABASE ci_news;

Selanjutnya, kita bisa mulai membuat migrasi.

Membuat Migrasi untuk Tabel News

Pertama kita akan membuat sekema untuk tabel news. Sebenarnya akan lebih gampang jika kita sudah memiliki rancangan sekema atau ERD.

Berikut ini ERD sementara untuk project ci-news.

diagram untuk project ci-news

Catatan: Kita akan fokus mengerjakan untuk tabel news saja dulu. Untuk tabel yang lainnya bisa diabaikan atau kalau mau dikerjakan sendiri juga boleh.

Oke sekarang buka kembali project ci-news yang sudah kita buat di tutorial sebelumnya.

Kemudian ketik perintah berikut untuk membuat file migrasi:

php spark migrate:create news

Perintah ini akan membuat file baru dengan nama 2020-11-23-053942_news.php di dalam folder app/Database/Migration.

file migration baru

Tanggal dan waktu di awal nama file menandakan versi dari migrasi.

Berikut ini adalah isi file 2020-11-23-053942_news.php.

<?php namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class News extends Migration
{
	public function up()
	{
		//
	}

	//------------------------------------------------------

	public function down()
	{
		//
	}
}

Pada kode ini terdapat class News yang merupakan turunan dari class Migration.

Pada class News terdapat dua method, yakni up() dan down(). Method ini nantinya akan dijalankan saat melakukan migrasi.

Method up() akan dijalankan saat melakukan migrasi, sedangkan down() saat melakukan rollback.

Tips: contoh di atas menggunakan news sebagai nama file migrasi. Ada juga yang menyarankan sebaiknya menggunakan nama yang deskriptif agar memudahkan. Misalnya seperti create_news_table, add_views_to_news_table, dsb.

Oke..

Sekarang mari kita buat skema untuk tabel News. Silahkan ubah kode pada file 2020-11-23-053942_news.php menjadi seperti ini:

<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;

class News extends Migration
{
	public function up()
	{
		// Membuat kolom/field untuk tabel news
		$this->forge->addField([
			'id'          => [
				'type'           => 'INT',
				'constraint'     => 5,
				'unsigned'       => true,
				'auto_increment' => true
			],
			'title'       => [
				'type'           => 'VARCHAR',
				'constraint'     => '255'
			],
			'author'      => [
				'type'           => 'VARCHAR',
				'constraint'     => 100,
				'default'        => 'John Doe',
			],
			'content' => [
				'type'           => 'TEXT',
				'null'           => true,
			],
			'status'      => [
				'type'           => 'ENUM',
				'constraint'     => ['published', 'draft'],
				'default'        => 'draft',
			],
		]);

		// Membuat primary key
		$this->forge->addKey('id', TRUE);

		// Membuat tabel news
		$this->forge->createTable('news', TRUE);
	}

	//-------------------------------------------------------

	public function down()
	{
		// menghapus tabel news
		$this->forge->dropTable('news');
	}
}

Penjelasan kode:

Perhatikan pada method up(), pertama kita membuat field terlebih dahulu baru membuat tabel.

Field dibuat dengan fungsi $this->forge->addField() dan memberikan parameter berupa array yang berisi data dari field. Selain dalam bentuk array, bisa juga dalam bentuk string SQL seperti ini: 1

$this->forge->addField([
'id INT(5)',
'title VARCHAR(255)'
]);

Bahkan juga bisa digabung, string SQL dan array.

Selanjutnya kita membuat primary key dengan fungsi:

$this->forge->addKey('id', TRUE);

Paramater TRUE berfungsi untuk menyatakan key yang dibuat adalah Primary Key. Jika tidak diberikan TRUE maka akan dibuat menjadi key biasa atau foreign key.

Terakhir, kita membuat tabel dengan fungsi:

$this->forge->createTable('news', TRUE);

Nilai TRUE berfungsi untuk mengecek apakah tabel sudah ada di database atau belum, jika ada maka tidak dilakukan pembuatan tabel. Jika kita tidak memberikan nilai TRUE, maka tabel akan tetap dibuat.. meskipun sudah ada.

Terakhir kita menghapus tabel dengan fungsi:

$this->forge->dropTable('news');

Karena kita menulisnya di dalam method down(), maka ini nantinya akan dipanggil saat kita melakukan rollback.

Oke, sekarang mari kita coba lakuka migrasi pertama.

Lakukan migrasi dengan perintah:

php spark migrate

Jika tidak ada error..

spark migrate

Maka migrasi berhasil dilakukan.

Sekarang coba cek database melalui Phpmyadmin, pasti di sana sudah ada dua tabel, yakni tabel migrations dan tabel news.

tabel migration

Tabel migrations adalah tabel yang otomatis dibuat untuk menyimpan versi migrasi yang sudah dilakukan. Lalu tabel news adalah tabel yang kita buat berdasarkan file migrasi.

Coba buka tabel migrations, di sana akan ada data migrasi.

data migrations

Terdapat beberapa kolom:

  • id merukan id primary key;
  • version versi dari file migrasi dibuat dalam bentuk tanggal dan waktu;
  • class file class untuk migrasi;
  • group group yang digunakan, ada default, test, production, dll. Kita juga bisa membuat group sendiri;
  • namespace name space yang digunakan;
  • time waktu dalam format unix time stamp;
  • batch nomer batch yang menyatakan nomer kloter migrasi;

Nomer batch ini akan bertambah setiap kita melakukan migrasi yang baru. Karena ini migrasi pertama yang kita lakukan, maka nomernya adalah 1.

Jika kita membuat file migrasi baru dan menjalankan perintah php spark migrate, maka migrasi yang baru akan memiliki nomer 2.

Bagaimana Kalau ada Perubahan Skema?

Ada dua cara yang bisa dilakukan:

Pertama, membuat file migrasi baru dan menuliskan perubahannya di sana, lalu melakukan migrasi lagi.

Cara pertama ini cocok dilakukan jika kita sudah punya data, karena perubahanya akan bisa di-rollback.

Kedua, bisa malakukan rollback, lalu mengubah file migrasi yang sudah ada dan melakukan migrasi kembali atau ini bisa dipersingkat dengan migrate:refresh.

Cara kedua ini gampang dilakukan dan cocok dilakukan untuk migrasi awal. Namun kurang cocok dilakukan untuk aplikasi yang sudah punya data dan sudah melakukan migrasi berkali-kali, karena akan berpotensi menghapus data.

Kalau menurut saya, cara pertama lebih aman dibandingkan dengan cara kedua. Tapi tidak masalah jika migrasi ini dilakukan di server development.

Oke, sekarang mari kita coba kedua-duanya..

Pertama kita akan coba cara yang paling gampang, yakni migrate:refresh.

Ubahlah kode pada file 2020-11-23-053942_news.php menjadi seperti ini:

<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class News extends Migration
{
	public function up()
	{
		// Membuat kolom/field untuk tabel news
		$this->forge->addField([
			'id'          => [
				'type'           => 'INT',
				'constraint'     => 5,
				'unsigned'       => true,
				'auto_increment' => true
			],
			'title'       => [
				'type'           => 'VARCHAR',
				'constraint'     => '255'
			],
			'author'      => [
				'type'           => 'VARCHAR',
				'constraint'     => 100,
				'default'        => 'John Doe',
			],
			'content' => [
				'type'           => 'TEXT',
				'null'           => true,
			],
			'status'      => [
				'type'           => 'ENUM',
				'constraint'     => ['published', 'draft'],
				'default'        => 'draft',
			],
			'created_at DATETIME DEFAULT CURRENT_TIMESTAMP'
		]);

		// Membuat primary key
		$this->forge->addKey('id', TRUE);

		// Membuat tabel news
		$this->forge->createTable('news', TRUE);
	}

	//---------------------

	public function down()
	{
		// menghapus tabel news
		$this->forge->dropTable('news');
	}
}

Pada kode ini kita menambahkan kolom created_at dengan tipe DATETIME dan nilai default CURRENT_TIMESTAMP.

Setelah itu, jalankan perintah:

php spark migrate:refresh

Coba perihatikan output dari perintah ini:

migrate refresh

Dia melakukan rollback ke batch 0, lalu melakukan migrasi ulang ke batch 1.

Sekarang coba cek kembali tabel news, di sana akan ada kolom baru bernama created_at.

kolom created at

Jika tabel news sudah punya data, maka data tersebut akan dihapus karena dilakukan rollback (drop table).

Inilah mengapa cara ini kurang aman untuk aplikasi yang sudah punya data, tapi tidak masalah untuk dilakukan di awal.

Oke sekarang kita coba cara yang lain..

Misalkan, kita ingin menambahkan kolom slug pada tabel news, kita bisa membuat file migrasi baru dengan perintah:

php spark migrate:create alter_news

Kemudian mengisi file tersebut dengan kode berikut:

<?php namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class AlterNews extends Migration
{
	public function up()
	{
		$this->forge->addColumn('news', [
			'slug VARCHAR(100) UNIQUE'
		]);
	}

	//--------------------------------------------------------

	public function down()
	{
		$this->forge->dropColumn('news', 'slug');
	}
}

Pada kode ini kita menambahkan kolom slug pada tabel news dengan tipe VARCHAR, ukurannya 100 dan bersifat unik (key unique).

Lalu pada method down(), kita melakukan penghapusan kolom.

Setelah itu, coba lakukan migrasi dengan perintah:

php spark migrate

Jika tidak ada error..

migrate alter news

Maka migrasi berhasil dilakukan.

Coba cek kembali tabel news dari Phpmyadmin, maka akan ada kolom baru bernama slug.

kolom slug

Coba juga untuk melihat isi tabel migrations, di sana akan ada data baru dengan nomer batch 2.

data migration batch 2

Jika kita melakukan rollback ke batch 1, maka data dengan nomer batch 2 akan dihapus dan kondisi database akan kembali seperti saat batch 1.

Gampang kan?

Nah sekarang pertanyaanya:

Apakah setiap membuat file migrasi baru, kita harus melakukan migrasi (php spark migrate)?

Tidak harus, kita bisa membuat file migrasi sebanyak-banyaknya di awal. Misalnya aplikasi kita punya 10 tabel, maka kita bisa buat 10 file migrasi dulu baru melakukan migrasi.

Oh iya, jangan lupa untuk selalu mengecek status migrasi dengan perintah:

php spark migrate:status

Tujuannya untuk tahu migrasi apa saja yang sudah dilakukan.

migrate status

Berikutnya kita akan membuat seed data awal.

Membuat Seed Data untuk News

Seed data adalah data awal untuk mengisi tabel. Seed data kadang kita butuhkan untuk mengetes, dan menyiapkan data yang diperlukan di awal seperti user pertama pada aplikasi.

Untuk membuat seed data, kita membutuhkan file seeder. File seeder ini dapat dibuat dengan perintah:

php spark make:seeder <nama_seed>

Contoh:

php spark make:seeder news

Maka kita akan memiliki file baru di dalam folder app/Database/Seeds dengan nama news.php.

file seeder

Ubahlah isi file news.php menjadi seperti ini:

<?php namespace App\Database\Seeds;

use CodeIgniter\Database\Seeder;

class News extends Seeder
{
	public function run()
	{
		// membuat data
		$news_data = [
			[
				'title' => 'Selamat datang di Codeigntier',
				'slug'  => 'codeigniter-intro',
				'content' => 'Pengenalan Codeigniter untuk Pemula.'
			],
			[
				'title' => 'Hello World',
				'slug' => 'hello-world',
				'content' => 'Hello World, ini contoh artikel'
			],
			[
				'title' => 'Meetup komunitas Codeigniter Indonesia',
				'slug'	=> 'codeigniter-meetup',
				'content' => 'Seru sekali meetup perdana komunitas codeigniter..'
			]
		];

		foreach($news_data as $data){
			// insert semua data ke tabel
			$this->db->table('news')->insert($data);
		}

	}
}

Perhatikan, pada method run() kita membuat array yang berisi data yang akan disimpan dalam tabel news.

Lalu kita menggunakan perulangan foreach untuk menyimpan semuanya. Jika hanya satu data saja, maka tidak perlu menggunakan perulangan.

Method run() akan dijalankan ketika kita menjalankan perintah db:seed.

Mari kita coba..

Jalankan seeder dengan perintah berikut:

php spark db:seed

Kemudian isi nama seeder.

seeding

Atau bisa juga dilakukan dengan langsung memberikan nama seeder di awal seperti ini:

php spark db:seed news

Maka sekarang tabel news akan memiliki data awal.

data awal news

Apa Selanjutnya?

Sejauh ini kita sudah mengetahui cara melakukan migrasi di Codeigniter 4. Buat kamu yang baru pertama belajar tentang migrasi, mungkin akan bingung.

Tapi percayalah, kelak saat aplikasi kita pindah-pindah sever dan bekerja dengan tim.. migrasi ini akan terasa manfaatnya.

Selanjutnya silahkan lanjut ke:

Untuk tutorial Codeigniter yang lainnya, cek di 📚 List Tutorial Codeigniter