Thursday, November 12, 2015

Penggunaan Callback pada GroceryCrud

Dear all coder seantero jagad raya. Kemarin Kang Cahya sudah membahas mengenai Grocery Crud, yaitu sebuah pugins codeigniter untuk menampilkan data dari database, lengkap dengan proses CRUD-nya. Grocery Crud ini sangat powerfull dan cukup membantu untuk membuat sebuah aplikasi CRUD dengan cepat. Pada form insert/update juga sudah dilakukan rules dan validasi secara otomatis (sesuai rules yang ditetapkan dari database).

Pada tulisan singkat kali ini, saya akan membahas tentang callback pada Grocery Crud dan kasus-kasus umum yang bakal terjadi dalam dunia programming.  Ada beberapa tipe callback pada Grocery Crud, antara lain :

  • Callback Colum
  • Callback Delete
  • Callback After (delete, insert, update, upload)
  • Callback Before (delete, insert, update, upload)
  • Callback add field
  • Callback edit field
  • Callback Insert / Callback Update / Callback Delete

Fungsi callback ini berfungsi untuk melakukan escaping terhadap suatu proses operasi dan memasukkan logika sebelum meneruskan ke proses akhir. Grocery Crud membentuk form input data secara otomatis, jika kita hanya memiliki data sederhana, maka tidak ada masalah untuk menggunakan form yang dibentuk oleh Grocery Crud. Namun jika kita membutuhkan modifikasi terhadap data yang akan dimasukkan ke database, maka akan timbul kesulitan baru.
Marilah kita bahas case berikut ini…...
Terdapat sebuah form untuk mengisikan data dari tabel users. Berikut adalah struktur table pada users:
ColumnTypeLength
idint11
group_idint11
usernameVarchar100
passwordVarchar150
emailvarchar100
first_namevarchar50
last_namevarchar50
created_atDate
updated_atDate

Dan di bawah ini adalah struktur table pada tabel usergroup:
ColumnTypeLength
idint11
group_namevarchar20
descriptionVarchar200

Column id adalah colum type int, merupakan Primary Key dari tabel tersebut. Set autoincrement dari column id ini dengan nilai true.

Sekarang kita masuk ke bagian peng-coding-an. Pada tutorial ini sudah saya sertakan sebuah aplikasi yang dilengkapi dengan Grocery Crud + Code Igniter + SB Admin template. Jadi kita hanya focus di coding nya saja.

Tambahkan fungsi berikut pada controller latihan:

public function user_management(){
try{
$crud = new grocery_CRUD();
$crud->set_theme('flexigrid');
$crud->set_table('users');
$crud->set_subject('Users');

$data['judul'] = 'Manajemen User';
$data['output'] = $crud->render();
$this->load->view('main_view', $data);
}catch(Exception $e){
show_error($e->getMessage().' --- '.$e->getTraceAsString());
}
}

Jika sudah selesai menambahkan coding di atas, jalankanlah aplikasi di web browser. Kalau di tempat saya, link untuk menjalankan aplikasi tersebut adalah:

http://localhost:8080/codeignitergrocerycrud/index.php/latihan/user_management

Kemungkinan link akan berbeda, sesuai dengan konfigurasi port server di server apache yang terinstall di computer. Jika berhasil, maka akan muncul seperti gambar di bawah ini:

Grocery Crud Callback Tutorial


Jika di klik tombol Add User, maka akan muncul form input data seperti gambar di bawah:



Sebenarnya pada tahapan ini, Grocery Crud sudah dapat bekerja dan dapat memasukkan data ke dalam tabel. Tetapi ada beberapa hal yang membutuhkan kustomisasi agar aplikasi dapat berjalan dengan bagus. Pada form tersebut, lihatlah input Group id yang berupa textbox. Kenyataannya yang kita inginkan adalah Group id berupa select combobox, yang dipopulasikan dari sebuah table lain. Untuk itu kita harus melakukan relasi dari tabel users ke tabel usergroup.

Untuk melakukan relation dari tabel users ke tabel usergroup, tambahkanlah script berikut pada fungsi user_management, posisi script tidak boleh setelah baris render dari Grocery Crud, harus sebelumnya.

$crud->set_relation('group_id','usergroup','group_name');

Kemudian jalankan lagi atau refresh halaman web pada browser. Maka field group_id akan berubah dari textbox menjadi select combobox. Lihat pada gambar di bawah.



Masalah selanjutnya adalah username, sebuah aplikasi yang baik, harus mampu melakukan check data apakah data yang diinput sudah ada di database atau tidak. Untuk itu kita harus melakukan callback terhadap field username. Mengintip database, apakah input yang di post mempunyai value yang sama atau tidak terhadap data yang sudah ada. Jika data sudah ada, maka kita cegah proses penyimpanan data dan melempar pesan error kepada user.

Untuk mewujudkan hal tersebut, maka kita buat dulu sebuah fungsi untuk melakukan pengecekan ke database. Misal nama fungsinya adalah: cek_user_before_user_save,

function cek_user_before_user_save($post_array){
$i = $this->db->where('username', $post_array['username'])->get('users')->num_rows();
if($i == 0 ){
return true;
}else{
return false;
}
}

$post_array yang di passing ke dalam fungsi itu adalah post data pada form input user yang di generate oleh Grocery Crud. Untuk mengaksesnya sama dengan mengakses data array pada php. Misalkan nama field kita adalah field username, maka untuk mendapatkan nilai username yang di post oleh form adalah sebagai berikut: $post_ array['username']

Bagaimana memanggil fungsi ini? Untuk memanggil fungsi ini, maka kita harus melakukan callback sebelum data diinpute ke database. Pada kasus ini kita gunakan callback before insert yang telah disediakan oleh Grocery Crud.

Script umum dari callback before insert adalah:

$crud->callback_before_insert(array($this,’nama fungsi callback nya….’));

Untuk lebih lengkapnya, fungsi user_management setelah ditambahkan perintah callback dan custom error message adalah sebagai berikut:

public function user_management(){
try{
$crud = new grocery_CRUD();
$crud->set_lang_string('insert_error','Username sudah ada di database');
$crud->set_theme('flexigrid');
$crud->set_table('users');
$crud->set_subject('Users');
$crud->set_relation('group_id','usergroup','group_name');
$crud->callback_before_insert(array($this,'cek_user_before_user_save'));

$data['judul'] = 'Manajemen User';
$data['output'] = $crud->render();
$this->load->view('main_view', $data);
}catch(Exception $e){
show_error($e->getMessage().' --- '.$e->getTraceAsString());
}
}

Perhatikan script tersebut, ada penambahan perintah set_lang_string dan callback_before_insert. Perintah set_lang_string adalah perintah untuk mengubah isi pesan pada saat state tertentu terjadi. Dalam hal ini yang kita ingin ubah isi pesannya adalah pada saat state insert_error (ada berbagai macam state pada Grocery Crud, bukan hanya insert_error saja). Sekarang coba refresh kembali page di browser, kemudian masukkan sebuah username yang value nya identic dengan username yang ada pada database. Pada database saya, sudah ada username dengan value admin.



Pada kasus ini, berlaku juga untuk state update field username. Post data update juga harus dilakukan pengecekan, apakah sudah ada di database atau tidak. Untuk itu kita tambah satu perintah callback lagi, yaitu callback_before_update. Selengkapnya dapat anda download pada link yang telah disediakan.

Setelah username, field selanjutnya yang membutuhkan perhatian khusus adalah field password. Beberapa hal yang perlu diperhatikan untuk field password ini adalah sebagai berikut :

  • Field password disimpan terenkripsi di database
  • Password harus diuji dengan length tertentu.
  • Pada saat input data, value dari password tidak terlihat.
  • Pada saat update data, field password dibiarkan kosong, jika password diubah, maka ada post data password untuk di masukkan ke database. Jika password tidak diubah atau dibiarkan kosong, maka tidak ada post data password, dan password lama tidak diupdate.

Untuk menyelesaikan bagian nomor 1, maka kita harus edit sedikit fungsi cek_user_before_save, lihat gambar di bawah:



Ganti bagian yang saya kotakin dengan script ini :

$this->load->library('encrypt');
$key = '!@#$%^&*()_+QWERTYUIOP';
$post_array['password'] = $this->encrypt->encode($post_array['password'], $key);
return $post_array;

sehingga fungsi cek_user_before_user_save menjadi seperti gambar di bawah ini:



Fungsi tersebut akan mengembalikan post data password yang sudah di encode. Saya meminjam library encrypt dari codeigniter. Lakukan hal yang sama pada fungsi cek_user_before_user_update. Jika sudah selesai, maka pada datagrid user akan menjadi seperti gambar di bawah ini:



Permasalahan selanjutnya adalah pada saat kita melakukan edit pada user. Jika kita klik tombol edit, maka akan muncul form edit seperti berikut ini:



Perhatikan pada bagian password. Bentuk password adalah bentuk yang telah di enkripsi, jika kita klik button Update changes, maka password akan disimpan kembali dalam bentuk terenkrip dikarenakan adanya proses callback saat melakukan update.

Jadi prosesnya seperti ini:
Password awal (plain text) -> save (password sudah di encrypt) -> buka form update (password ter-encrypt ditampilkan) -> update changes (password ter-encrypt di encrypt lagi)
Jika proses ini yang terjadi, maka setiap melakukan update data user, maka password akan berubah.

Bagaimana mengantisipasi hal ini? Mudah saja, Grocery Crud menyediakan apa yang anda butuhkan dengan callback. Pada proses update data user yang mempunyai field password, maka harus melalui langkah-langkah sebagai berikut:

  • Pada saat membuka form update, biarkan field password kosong.
  • Pada saat melakukan update, gunakan callback dengan melakukan cek pada post data password, jika post data kosong, artinya column password tidak di update, maka kita lakukan unset terhadap post data password. Jika di unset, maka grocery crud tidak akan melakukan update terhadap password.

Untuk langkah 1, pada fungsi user_management, saya tambahkan baris berikut:

$crud->change_field_type('password', 'password');
$crud->callback_edit_field('password',array($this,'set_empty_password_field'));
$crud->callback_add_field('password',array($this,'set_empty_password_field'));

Kemudian tambahkan fungsi set_empty_password_field:

function set_empty_password_field(){
return "<input name="password" type="password" value="" />";
}

Langkah 1 sudah selesai, pada tahapan ini, jika semuanya sudah benar, maka field password akan bernilai string kosong jika kita membuka form insert/update. Oya, di atas ada perintah change_field_type, ini berfungsi untuk mengubah type input dari input text biasa menjadi input password. Coba jalankan kembali aplikasi ini, maka terjadi perubahan pada grid, field password akan berganti menjadi tanda bintang. Kemudian jika kita masuk ke insert/update form, kemudian kita ketik pada field password, maka akan muncul karakter “dot” untuk menyamarkan value password.

Selanjutnya, untuk langkah ke 2, saya hanya akan menambahkan decision If untuk melakukan pengecekan apakah field password empty atau tidak. Penambahan ini saya sisipkan ke dalam fungsi callback cek_user_before_user_update.

Nah, sekarang tinggal langkah terakhir untuk menyelesaikan case user_management ini, yaitu tanggal record dibuat dan tanggal record di update. Jika kita lihat kembali pada form insert atau form update, maka ada field created_at dan updated_at. Field ini perlu kita sembunyikan agar bukan user yang mengisikan data ini. Data ini hanya akan tercatat pada saat user melakukan insert sebuah record (created_at) dan pada saat user melakukan update pada sebuah record (updated_at).

Aplikasi hanya akan menampung variable created_at hanya pada statement insert. Dan hanya dapat menampung variable updated_at hanya pada statement update. Untuk itu, kita akan tambahkan perintah berikut ini pada function user_management :

$crud->unset_add_fields('updated_at');
$crud->unset_edit_fields('created_at');
$crud->field_type('updated_at','invisible');
$crud->field_type('created_at','invisible');

Setelah selesai, fungsi user_management akan menjadi seperti ini:



Silahkan download code dari artikel ini di link berikut:




Mohon saran dan kritikannya.

Saya hanya seorang "newbie" yang baru bisa ngoding lohor kemarin.

2 komentar

Kang cahya, apakah bisa melakukan call back before insert sebanyak 2 kali, 1. Untuk enkripsi password 2.cek password yg kedua sama dengan password yg pertama, ini saat proses sign up pelapor

Bisa saja. Tapi kenapa harus dibikin 2 callback? kan 2 fungsi itu dicombine dalam 1 callback :)


EmoticonEmoticon