1. Pengertian
Pengertian MVC
Ada yang pernah nyoba buat web pake frame work gak? Klo udah pernah, pasti anda pernah ketemu dengan istilah
MVC, tapi ada yang tahu gak, pengertian MVC itu apa? Mungkin saya bisa kasih sedikit penjelasan tentang apa itu MVC.
MVC adalah singkatan dari Model, View, dan Controller. Lalu apa Model, View dan Control tersebut? MVC merupakan
suatu metode untuk memisahkan bagian-bagian dari suatu web aplikasi.Berikut penjelasan fungsi dari ketiga bagian
tersebut:
Model, kurang lebih adalah sebagai bagian pengolahan database, dimana kita dapat memanipulasi data sesuai
kebutuhan user, di bagian ini kita dapat mengedit data, menambah data, menghapus data, dan lain sebagainya.
View, adalah bagian interface atau dengan istilah lain berupa halaman web, bagian inilah yang akan di nikmati oleh user
nantinya.
Control, bagian inilah yang dibutuhkan untuk menghubungkan bagian Model dengan View, kurang lebih berisi tentang
code-code perintah untuk meminta data dari Model, jadi ketika user meminta data, yang bertugas memanggil bukanlah
View melainkan Control.
Nah itulah kurang lebih penjelasan tentang MVC, dan fungsinya adalah memisah antara Model dan View, sehingga
mempermudah dalam pengembangan aplikasi.
2. pengertian sesuai framework
1. Codeigniter Framework adalah salah satu dari sekian framework yang menggunakan sistem MVC (Model-View-
Controller). Jangan bingung dulu di awal, banyak programmer PHP di forum-forum luar mengatakan KISS (Keep It
Simple Stupid!) with MVC. Mari saya lanjutkan lagi.
2. Pengertian Framework merupakan suatu perangkat lunak (software) yang bersifat penggunaan ulang suatu library
atau classes yang ada di dalam sistem tersebut untuk menjadi suatu aplikasi. Di dalam framework PHP, sudah terdapat
beberapa classes, objects dan library. Dengan begitu ketika kita membuat aplikasi menggunakan framework, kita bisa
menggunakan fitur yang sudah ada di dalam software tersebut.
3. Sebagai contoh, kita ingin mengirimkan email dan di dalam framework sudah ada library email, jadi tidak usah membuat
code pengirim email, cukup kita panggil function library email. Di dalam Framework Codeigniter sendiri telah terdapat
beberapa library di dalamnya, seperti library email, cart (keranjang belanja web ecommerce), validasi form, pagination,
session, dan lain-lain. Menarik bukan?
4. MVC itu sendiri adalah suatu konsep Model View Controller. Pada dasarnya dalam konsep MVC
ini, Model merupakan pengolah data dan berkomunikasi dengan database, View adalah tampilan yang ditampilkan ke
user, sedangkan Controller merupakan pengolah request user dan mengembalikan request user dalam bentuk View.
5.
3. Konfigurasi
Sekarang kita membahas bagaimana berkerja dengan database pada Model di MVC. Diharapkan
telah mengerti tentang kelas library dan kelas model untuk database. Karena disini akan
digunakan library database dan kelas model tersebut untuk proses koneksi dan manipulasi
database pada MVC
Isi Tutorial :
1. Configs
2. Database
o Mysql_Adapter
o Mysql_Select
3. Helper
o DatabaseObject
o Breadcrumbs
4. Functions
5. Request
6. Index
7. Model
o Category
o Product
8. Router
9. Controller
o BaseController
o IndexController
o ProductController
10. Views
o Index
o Product
Configs
Direktori application/configs digunakan untuk konfigurasi database. Sekarang buat file config.ini,
sesuaikan konfigurasi database berikut :
1
2
3
4
5
[db] host = localhost username = root password = dbname = db_buku
Database
Database db_buku yang telah dibuat tambahkan kolom url dan deskripsi pada tabel produk.
Untuk menghemat waktu, hapus tabel produk dan tulis SQL berikut :
+ expand source
Mysql_Adapter
Kelas DatabaseObject sebelumnya, dibuat secara keseluruhan atau bersifat meluas mulai dari
proses koneksi, proses logic, hingga manipulasi data. Sekarang proses koneksi dan proses
manipulasi data dijadikan sebagai adapter.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Mysql_Adapter { public $db;
public $id;
public $bind;
protected $_fetchMode = PDO::FETCH_ASSOC;
public function __construct($host, $user, $password, $database) { try { $this->db = new PDO ('mysql:host='.$host.';dbname=' . $database, $user, $password); $this->db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION
); } catch (PDOException $e) { print 'Kesalahan : '. $e->getMessage() . ''; die(); } }
public function getDb() { return $this->db; }
public function getBind() { return $this->bind; }
public function clearBind() { unset($this->bind); }
public function quote($query, $value, $key = 'col') { $ph = ':'.$key; $query = str_replace('?', $ph, $query); $this->bind[$key] = $value;
return $query; }
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
public function query($sql, $bind = array()) { if($sql instanceof Mysql_Select){ if(empty($bind)) $bind = $sql->getBind();
$sql = $sql->getSql(); } else { if(empty($bind)) $bind = $this->bind; }
if(!is_array($bind)) $bind = array($bind);
$stmt = $this->db->prepare($sql); $stmt->execute($bind); $stmt->setFetchMode($this->_fetchMode);
$this->clearBind();
return $stmt; }
public function insert($table, $bind) { $vals = array(); foreach ($bind as $k => $v) { $vals[] = ':' . $k; } $query = sprintf('INSERT INTO %s (%s) VALUES (%s)', $table, implode(',', array_keys($bind)), implode(', ', $vals) );
$stmt = $this->query($query, $bind); $result = $stmt->rowCount(); $this->id = $this->db->lastInsertId(); return $result; }
public function lastInsertId() { return $this->id; }
public function update($table, $data, $where) { $vals = array(); foreach ($data as $k => $v) { $vals[] = $k . ' = :' . $k; $this->bind[$k] = $v; }
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
if(is_array($where)) $where = implode(' AND ', $where);
$query = sprintf('UPDATE %s SET %s WHERE %s', $table, implode(',', $vals), $where );
$stmt = $this->query($query); $result = $stmt->rowCount(); return $result; }
public function delete($table, $where) { if(is_array($where)) $where = implode(' AND ', $where);
$query = sprintf('DELETE FROM %s WHERE %s', $table, $where );
$stmt = $this->query($query); $result = $stmt->rowCount(); return $result; }
public function select() { return new Mysql_Select($this); }
public function fetchAll($query, $bind = array(), $fetchMode = null) { if ($fetchMode === null) $fetchMode = $this->_fetchMode;
$stmt = $this->query($query, $bind); return $stmt->fetchAll($fetchMode); }
public function fetchAssoc($query, $bind = array()) { $stmt = $this->query($query, $bind); return $stmt->fetchAll(PDO::FETCH_ASSOC); }
public function fetchObj($query, $bind = array()) { $stmt = $this->query($query, $bind); return $stmt->fetchAll(PDO::FETCH_OBJ); }
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
public function fetchNum($sql, $bind = array()) { $stmt = $this->query($sql, $bind); return $stmt->fetchAll(PDO::FETCH_NUM); }
public function fetchPairs($sql, $bind = array()) { $stmt = $this->query($sql, $bind); $data = array(); while ($row = $stmt->fetch(PDO::FETCH_NUM)) { $data[$row[0]] = $row[1]; } return $data; }
public function fetchOne($sql, $bind = array()) { $stmt = $this->query($sql, $bind); return $stmt->fetchColumn(0); } }
Mysql_Select
Kelas ini hampir sama dengan kelas Db_Select, hanya saja namanya yang
menjadiMysql_Select, dan ada beberapa perubahan sebagai berikut :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Mysql_Select { ...
public function __construct(Mysql_Adapter $adapter) { $this->_adapter = $adapter; $this->_parts = self::$_partsInit; }
...
protected function _join($type, $name, $columns, $cond) { if(is_array($name)){ foreach($name as $alias => $table){ $using = array($type, $table, $alias, $cond); }
$this->_parts[self::JOIN][] = implode('
', $using); } else if($name !== null) $this->_parts[self::JOIN][] = $type . ' ' . $name;
if($columns) $this->_parts[self::COLUMNS][] =
implode(', ', $columns); }
... }
Helper
Kelas direktori helper ini adalah kelas bantuan, diantaranya kelas DatabaseObject dan kelas
Breadcrumbs.
DatabaseObject
Kelas DatabaseObject adalah kelas bantuan digunakan sebagai proses logic, sedangkan proses
manipulasi dilakukan oleh kelas Mysql_Adapter.
Hapus proses manipulasi data, yaitu
method _insert(), _update(), _delete(),select(), selectQuery(). Kemudian ubah
method __construct, load(),_load(), save(), delete() sperti berikut :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
abstract class DatabaseObject { // hapus konstanta konfigurasi database // dan tambah parameter Mysql_Adapter $db ...
public function __construct(Mysql_Adapter $db, $table, $idField) { $this->_db = $db; $this->_table = $table; $this->_idField = $idField; }
...
Tambahkan parameter pada method __construct untuk database dari kelas Mysql_Adapter dan
buat variabel untuk database.
Pada method load buat placeholders dengan method quote dari adapter.
1
2
3
4
5
6
7
8
9
10
11
12
...
public function load($id, $field = null) { ...
$query = $this->_db->quote($query, $id);
return $this->_load($query); }
...
Pada method save, ubah proses manipulasi update dan insert.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
public function save() { ...
if (count($row) > 0) { if ($update) { $this->_db->update($this->_table, $row, sprintf('%s = %d', $this->_idField,
$this->getId())); } else { $this->_db->insert($this->_table, $row); $this->_id = $this->_db->lastInsertId(); } }
if ($commit) { if ($update)
17
18
19
20
21
22
23
24
25
26
27
$commit = $this->postUpdate(); else $commit = $this->postInsert(); }
return $commit; }
...
Dan pada method delete, ubah proses manipulasi delete.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
public function delete() { ...
if ($commit) $this->_db->delete($this->_table, sprintf('%s = %d', $this->_idField,
$this->getId())); else return false;
... }
...
Breadcrumbs
Kelas Breadcrumbs gunanya untuk membuat site navigation dan title. Nilai navigation/title
berasal dari pendefinisian setiap aksi kontroller menggunakan method add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
}
public function getTitle() { if(count($this->_trail) == 0) return null;
return $this->_trail[count($this->_trail) - 1]['title']; } } ?>
Functions
Buat fungsi untuk membuat navigasi. Nilai dari parameter pertama adalah variabel array
method getTitle kelas Breadcrumbs dan parameter kedua adalah pemisah (separator) navigasi,
secara default separatornya >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
function breadcrumbs($params, $sptr = null) { $separator = (is_null($sptr)) ? ' ' : $sptr; $truncate = 25;
$links = array(); $numSteps = count($params); for ($i = 0; $i < $numSteps; $i++) { $step = $params[$i];
if(strlen($step['title']) > $truncate) $step['title'] = substr($step['title'], 0 ,$truncate) .
'...';
if (strlen($step['link']) > 0 && $i < $numSteps - 1) { $links[] = sprintf('%s', htmlSpecialChars($step['link']), htmlSpecialChars($step['title']), htmlSpecialChars($step['title'])); } else { $links[] = htmlSpecialChars($step['title']); } }
print join($separator, $links); }
Request
Kelas Request untuk mengambil request yang dikirmkan oleh url. Bisa dibilang kelas ini opsional
saja, karena bisa dilakukan secara manual.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
{ $url = $this->url($action, $controller); header('location:'.$url); exit(); } } ?>
Method url berisi tiga parameter, yaitu nilai aksi, nilai kontroller dan nilai atribut. Jika parameter
kosong nilai dari url adalah kontoller itu sendiri dengan aksi index. contoh :
1
2
3
4
// dipanggil dari kontroller product aksi view ->url(); // >>> http://mvc/product ->url('category'); // >>>
http://mvc/product/category ->url('category', 'product'); // >>>
http://mvc/product/category
Index
Ambil konfigurasi database config.ini dengan fungsi parse_config_ini, lalu buat objek
Mysql_Adapter dengan konfigurasi database tersebut. Setelah itu daftarkan objek request dan
adapter tadi ke registri.
1
2
3
4
5
6
7
8
9
10
11
...
$registry = new Registry;
$registry->request = new Request($registry);
$config = parse_ini_file(ROOT . '/application/configs/config.ini', true);
$registry->db = new Mysql_Adapter($config['db']['host'], $config['db']['username'], $config['db']['password'], $config['db']['dbname']);
...
Model
Setiap kelas model adalah turunan dari kelas DatabaseObject. Karena kelas DatabaseObject tidak
mempunyai koneksi database hanya proses logic saja, tambahkan database ke parameter
constructor di setiap kelas model. Untuk lebih detail tentang kelas model dapat dilihat disini.
Category
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
private static function _GetBaseQuery($db, $options) { $defaults = array(
'order' => 'k.id_kategori DESC' );
foreach ($defaults as $k => $v) { $options[$k] = array_key_exists($k, $options) ?
$options[$k] : $v; }
$select = $db->select();
$select->from(array('k' => 'kategori'), array());
$select->order($options['order']);
return $select; }
} ?>
Product
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
Buat callback method postLoad() untuk mengambil data tabel kategori dari table produk.
Kemudian method static deleteByCategory untuk menghapus semua produk pada kategori
1
2
3
4
5
6
7
8
9
10
...
public static function DeleteByCategory($db, $id_kategori) { $select = self::_GetBaseQuery($db, array('id' => $id_kategori)); $data = $db->fetchAll($select); return parent::BuildMultiple($db, __CLASS__, $data); }
...
Mengambil semua data di tabel product pada method static GetProducts. Disini kita bisa
menggunakan klausa seperti JOIN, WHERE, LIMIT, dan ORDER.
Dan method static getCount untuk menghitung jumlah baris menggunakan fetchOne.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...
public static function GetCount($db, $options = array()) { $select = self::_GetBaseQuery($db, $options); $select->from(null, array('count(*)'));
return $db->fetchOne($select); }
public static function GetProducts($db, $options = array()) { $defaults = array( 'offset' => 0,
'limit' => 0 );
foreach ($defaults as $k => $v) { $options[$k] = array_key_exists($k, $options) ?
$options[$k] : $v; }
$select = self::_GetBaseQuery($db, $options);
$select->join(array('k' => 'kategori'), array(), 'id_kategori');
if ($options['limit'] > 0) $select->limit($options['offset'],
$options['limit']);
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
return $db->fetchObj($select); }
private static function _GetBaseQuery($db, $options) { $defaults = array(
'id' => 0,
'order' => 'p.id_produk DESC' );
foreach ($defaults as $k => $v) { $options[$k] = array_key_exists($k, $options) ?
$options[$k] : $v; }
$select = $db->select(); $select->from(array('p' => 'produk'), array());
if($options['id'] > 0) $select->where('p.id_kategori IN (?)',
$options['id']);
$select->order($options['order']);
return $select; } } ?>
Router
Terkadang diperlukan atribut tambahan url guna mengirimkan nilai untuk halaman. Contohnya : http://mvc/product/?search=mobile&tag=android&limit=5
Namun disini kita tidak bisa mengambil nilai atribut menggunakan method $_GET. Tanda ?
tidak bisa digunakan dua kali di url, karena sebelumnya sudah dipakai di index.php. Terkecuali
tanda ? diganti &, maka method $_GET bisa digunakan. Tetapi cara tersebut sedikit terlihat
aneh, mungkin bisa diakali seperti ini : http://mvc/product/search/mobile/tag/android/limit/5
Walaupun hanya akal-akalan tapi terlihat lebih SEO friendly. Sekarang ubah method loader agar
bisa menangkap nilai atribut url diatas :.
1
2
3
4
5
6
7
class Router { ...
public function loader() { ...
if (is_callable(array($controller, $this->action))
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
== false){ $action = 'index'; } else { $action = $this->action; }
// ubah $controller->$action() seperti dibawah :
$arguments = array(); $i = 0; foreach ($this->route as $key => $val){ if ($key > 1){ $arguments[$this->route[$key-1]] = $val; $i++; } }
if($i > 1) call_user_func(array($controller, $action),
$arguments); else call_user_func_array(array($controller,
$action), $arguments); } } ?>
Jika url dijabarkan sesuai dengan aturan router url kita, terlihat seperti ini : http://mvc/product/search/mobile/tag/android/limit/5
page :
product/search/mobile/tag/android/limit/5 kontroller : product aksi/method : search atribut : mobile/tag/android/limit/5
Dengan menggunakan fungsi call_user_func/call_user_func_array akan mengirimkan
array atribut tersebut sebagai arguments untuk aksi kontroller. Perbedaan fungsi yang dipanggil
dan cara menangkap nilai atribut tersebut :
Pertama, untuk jumlah atribut hanya satu
1
2
3
4
5
6
7
8
9
// contoh url : product/category/3 // fungsi yang dipanggil call_user_func_array(array($controller,
$action), $arguments)
// desfinisikan variabel paramater aksi
kontroller public function view($id) { echo $id; // 3 }
Kedua, jumlah atribut lebih dari satu atau banyak
1
2
3
4
5
6
7
8
9
10
11
12
// contoh url :
product/search/mobile/tag/android/limit/5 // fungsi yang dipanggil call_user_func (array($controller,
$action), $arguments)
// tangkap arguments dengan fungsi
func_get_args public function search() { $args = func_get_args(); echo $args[0]['search']; // mobile echo $args[0]['tag']; // android echo $args[0]['limit']; // 5 }
Controller
Untuk kontroller setiap instansi kelas model tambahkan database pada parameternya.
Sebelumnya kita bahas dulu BaseController
BaseController
Disini akan dibuat navigasi, tambahkan variabel breadcrumbs untuk kontroller dan
method getRequest untuk ambil objek kelas request
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{ $this->preDistpatch(); $this->view->dispatch(); } } ?> Sebelum ditampilkan kirim variabel breadcrumbs dan title pada method
preDispatch()
IndexController
IndexController hanya memiliki satu aksi yaitu menampilkan semua kategori.
1
2
3
4
5
6
7
8
9
10
11
class IndexController extends BaseController { public function index() { $categories = Category::GetCategories($this->_db); $count = Product::GetCount($this->_db);
$this->view->count = $count; $this->view->categories =
$categories; } }
ProductController
Aksi index menampilkan semua produk dan tambahkan navigasi buku
1
2
3
4
5
6
7
8
9
10
11
12
akan dialihkan ke halaman error notfound. Jika kategori ada, ambil semua produk berdasarkan id
kategori. Tambahkan navigasi buku dan nama kategori.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
public function category($id) { $category = new Category($this->_db); if(!$category->load($id)) $this->getRequest()->redirect('notfound',
'error');
$products = Product::GetProducts($this->_db, array('id' => $id));
$this->breadcrumbs->add('Buku', $this-
>getRequest()->url()); $this->breadcrumbs->add('Kategori'); $this->breadcrumbs->add($category-
>nama_kategori);
$this->view->products = $products; $this->view->category = $category; }
...
Hampir sama, aksi view menampilkan buku berdasarkan url. Jika tidak ditemukan, akan
dialihkan ke halaman error notfound. Tambahkan navigasi buku dan nama buku
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
...
public function view($url) { $product = new Product($this->_db); if(!$product->load($url, 'url')) $this->getRequest()->redirect('notfound', 'error');
$this->breadcrumbs->add('Buku', $this->getRequest()-
>url()); $this->breadcrumbs->add($product->nama_produk); $this->view->product = $product; } } ?>
Views
Header
Beri title dan tampilan navigasi diletakkan di header. Gunakan fungsi breadcrumbsseperti berikut :
views/header.php
1
2
3
4
5
6
7
8
index
Aksi index untuk kontroller index
index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Kategori
8
9
10
11
12
13
14
15
Aksi category untuk kontroller product
category.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Buku Kategori
Aksi view untuk kontroller product
view.php
1
2
3
4
5
6
7
8
Harga
Download
Selanjutnya
Membuat pagination dan form beserta filtering input untuk proses CRUD (create, update, delete) pada
MVC di bagian ketiga
Incoming search terms:
panduan praktis oop di php (2)
pagination php pdo (2)
pengolahan gambar dengan php (1)
panduan-praktis-oop-di-php (1)
panduan praktis oop di php Insert Record ke Database MySQL dengan OOP (1)
panduan praktis oop di php free (1)
update data array ke database menggunakan foreach di php (1)
panduan membuat mvc (1)
mysql mvc (1)
merubah agar seo friendly (1)
Top Related