Pages

Wednesday, October 21, 2009

Membuat Formulir

Membuat Formulir

Menulis tampilan login adalah pekerjaan langsung. Kita mulai dengan sebuah tag form yang atribut aksinya berupa URL atas aksi login seperti dijelaskan sebelumnya. Kemudian kita menyisipkan label dan field input untuk atribut yang dideklarasikan dalam kelas LoginForm. Setelah itu kita menyisipkan tombol kirim yang dapat diklik oleh pengguna untuk mengirimkan formulir. Semua ini dapat dikerjakan dalam kode murni HTML.

Yii menyediakan beberapa kelas pembantu guna memfasilitasi komposisi tampilan. Sebagai contoh, untuk membuat sebuah field input teks, kita dapat memanggil CHtml::textField(); untuk membuat daftar drop-down, panggil CHtml::dropDownList().

Info: Orang mungkin heran apa untungnya pemakaian bantuan jika mereka memerlukan sejumlah kode yang mirip dibandingkan dengan kode HTML langsung. Jawabannya adalah bahwa pembantu dapat menyediakan lebih dari sekedar kode HTML. Sebagai example, the following code would generate a text input field which can pemicu pengiriman formulir jika nilainya diubah oleh pengguna.

CHtml::textField($name,$value,array('submit'=>''));

Ini akan memerlukan penulisan sejumlah JavaScript dimana-mana.

Dalam contoh berikut, kita menggunakan CHtml untuk membuat formulir login. Kita beranggapan bahwa variabel $user mewakili turunan LoginForm.

<div class="yiiForm">
php echo CHtml::beginForm(); ?>

php echo CHtml::errorSummary($user); ?>

<
div class="simple">
php echo CHtml::activeLabel($user,'username'); ?>
php echo CHtml::activeTextField($user,'username'); ?>
div>

<
div class="simple">
php echo CHtml::activeLabel($user,'password'); ?>
php echo CHtml::activePasswordField($user,'password');
?>
div>

<
div class="action">
php echo CHtml::activeCheckBox($user,'rememberMe'); ?>
Remember me next time<br/>
php echo CHtml::submitButton('Login'); ?>
div>

php echo CHtml::endForm(); ?>
div>

Kode di atas menghasilkan formulir lebih dinamis. Sebagai contoh, CHtml::activeLabel() menghasilkan label terkait dengan atribut model yang ditetapkan. Jika atribut memiliki kesalahan input, label kelas CSS akan diubah ke error, yang mengubah tampilan label dengan gaya CSS terkait. Hal yang sama, CHtml::activeTextField() menghasilkan field input teks untuk atribut model yang ditetapkan dan mengubah kelas CSS jika ada kesalahan pada input.

Jika kita menggunakan file gaya CSS form.css yang disediakan oleh naskah yiic, formulir yang dihasilkan akan terlihat seperti berikut:

Halaman login

Halaman login

Login dengan halaman kesalahan

Login dengan halaman kesalahan

Mengumpulkan Input Tabular

Mengumpulkan Input Tabular

Adakalanya kita ingin mengumpulkan input pengguna dalam mode batch. Yakni, pengguna dapat memasukan informasi untuk turunan model secara multipel dan mengirimkannya sekaligus. Kami menyebut ini input tabular karena field input sering disajikan dalam tabel HTML.

Untuk bekerja dengan input tabular, pertama kita perlu membuat atau mempopulasikan array turunan model, tergantung pada apakah kita menyisipkan atau memutakhirkan data. Selanjutnya kita dapat mengambil data input pengguna dari variabel $_POST dan menempatkannya ke setiap model. Perbedaan utama dari model input tunggal adalah bahwa kita mengambil data input menggunakan $_POST['ModelClass'][$i] daripada $_POST['ModelClass'].

public function actionBatchUpdate()
{
// ambil item yang akan dipopulasi dalam mode batch
// menganggap setiap item adalah kelas model 'Item'
$items=$this->getItemsToUpdate();
if(isset($_POST['Item']))
{
$valid=true;
foreach($items as $i=>$item)
{
if(isset($_POST['Item'][$i]))
$item->attributes=$_POST['Item'][$i];
$valid=$valid && $item->validate();
}
if($valid) // seluruh item benar
// ...lakukan sesuatu di sini
}
// tampilkan tampilan untuk mengumpulkan input tabular
$this->render('batchUpdate',array('items'=>$items));
}

Setelah aksi siap, kita perlu bekerja pada tampilan batchUpdate untuk menampilkan field input dalam sebuah tabel HTML.





$item): ?>







NamePriceCountDescription






Catatan dalam contoh di atas kita menggunakan "name[$i]" daripada "name" sebagai parameter kedua saat memanggil CHtml::activeTextField.

Jika ada kesalahan validasi, field input terkait akan diterangi secara otomatis, seperti halnya model input tunggal yang kami jelaskan sebelumnya.

Membuat Aksi

Setelah kita memiliki model, kita dapat mulai menulis logika yang diperlukan untuk memanipulasi model. Kita tempatkan logika ini di dalam sebuah aksi kontroler. Untuk contoh formulir login, kode berikut diperlukan:

public function actionLogin()
{
$form=new LoginForm;
if(isset($_POST['LoginForm']))
{
// kumpulkan data input pengguna
$form->attributes=$_POST['LoginForm'];
// validasi input pengguna dan alihkkan ke halaman sebelumnya jika benar
if($form->validate())
$this->redirect(Yii::app()->user->returnUrl);
}
// tampilkan formulir login
$this->render('login',array('user'=>$form));
}

Dalam contoh di atas, pertama kita membuat turunan LoginForm; jika permintaan adalah permintaan POST (berarti formulir login dikirimkan), kita mempopulasi $form dengan data yang dikirimkan $_POST['LoginForm']; kemudian kita memvalidasi input dan jika sukses, mengalihkan browser pengguna ke halaman sebelumnya yang memerlukan otentikasi. Jika validasi gagal, atau jika aksi diakses dari awal, kita menyajikan tampilan login di mana isinya akan dijelaskan dalam subseksi berikut.

Tip: Dalam aksi login, kita menggunakan Yii::app()->user->returnUrl untuk mendapatkan URL halaman sebelumnya yang memerlukan otentikasi. Komponen Yii::app()->user adalah jenis CWebUser (atau anak kelasnya) yang mewakili informasi sesi pengguna (misalnya username, status). Untuk lebih jelasnya, lihat Otentikasi dan Otorisasi.

Mari kita perhatikan pernyataan PHP berikut yang muncul dalam aksi login:

$form->attributes=$_POST['LoginForm'];

Seperti yang kami jelaskan dalam Mengamankan Penempatan Atribut, baris kode ini mempopulasi model dengan data yang dikirimkan pengguna. Properti attributes didefinisikan oleh CModel yang mengharapkan array pasangan nama-nilai dan menempatkan setiap nilai ke atribut model terkait. Maka jika $_POST['LoginForm'] menghasilkan array seperti itu, kode di atas akan sama dengan kode panjang berikut (menganggap setiap atribut ada dalam array):

$form->username=$_POST['LoginForm']['username'];
$form->password=$_POST['LoginForm']['password'];
$form->rememberMe=$_POST['LoginForm']['rememberMe'];

Catatan: Agar $_POST['LoginForm'] menghasilkan array daripada string, kita tetap pada konvensi penamaan field input dalam tampilan. Pada keadaan tertentu, sebuah field input berkaitan dengan atribut a pada kelas model C, kita namai sebagai C[a]. Sebagai contoh, kita ingin menggunakan LoginForm[username] untuk menamai field input yang berkaitan dengan atribut username.

Tugas selanjutnya sekarang adalah membuat tampilan login yang harus berisi formulir HTML dengan field input yang dibutuhkan.

Membuat Model

Sebelum menulis kode HTML yang diperlukan oleh sebuah formulir, kita harus menetapkan jenis data apa yang diharapkan dari pengguna akhir dan aturan apa pada data ini harus diterapkan. Kelas model dapat dipakai guna merekam informasi ini. Model, seperti yang didefinisikan dalam subseksi Model, adalah tempat utama untuk memelihara input pengguna dan memvalidasinya.

Tergantung pada bagaimana kita menggunakan input pengguna, kita bisa membuat dua jenis model. Jika input pengguna dikumpulkan, dipakai dan kemudian diabaikan, kita bisa membuat model formulir; jika input pengguna dikumpulkan dan disimpan ke dalam database, sebaliknya kita dapat menggunakan rekaman aktif. Kedua jenis model berbagi basis kelas CModel yang sama yang mendefinisikan antar muka umum yang diperlukan oleh formulir.

Catatan: Kita menggunakan model formulir terutama dalam contoh pada seksi ini. Akan tetapi, hal yang sama bisa juga diterapkan pada model rekaman aktif.

Mendefinisikan Kelas Model

Di bawah ini kita membuat kelas model LoginForm yang dipakai untuk mengumpulkan input pengguna pada halaman login. Karena informasi login hanya dipakai untuk mengotentikasi pengguna dan tidak perlu menyimpan, kita membuat LoginForm sebagai sebuah model formulir.

class LoginForm extends CFormModel
{
public $username;
public $password;
public $rememberMe=false;
}

Tiga atribut dideklarasikan dalam LoginForm: $username, $password dan $rememberMe. Ini dipakai untuk memelihara nama pengguna dan kata sandi yang dimasukkan, dan opsi apakah pengguna menginginkan untuk mengingat login-nya. Karena $rememberMe memiliki nilai standar false, opsi terkait saat awal ditampilkan dalam formulir login tidak akan dicentang.

Info: Daripada memanggil properi variabel anggota ini, kita menggunakan nama attributes untuk membedakannya dari properti normal. Atribut adalah properti yang terutama dipakai untuk menyimpan data yang berasal dari input pengguna atau database.

Mendeklarasikan Aturan Validasi

Setelah pengguna mengirimkan inputnya dan model sudah dipopulasi, kita perlu memastikan bahwa input benar sebelum menggunakannya. Ini dikerjakan dengan melakukan validasi input terhadap satu set aturan. Kita menetapkan aturan validasi dalam metode rules() yang harus mengembalikan array konfigurasi aturan.

class LoginForm extends CFormModel
{
public $username;
public $password;
public $rememberMe=false;

public function rules()
{
return array(
array('username, password', 'required'),
array('password', 'authenticate'),
);
}

public function authenticate($attribute,$params)
{
if(!$this->hasErrors()) // kita hanya ingin mengotentikasi bila tidak ada kesalahan input
{
$identity=new UserIdentity($this->username,$this->password);
if($identity->authenticate())
{
$duration=$this->rememberMe ? 3600*24*30 : 0; // 30 hari
Yii::app()->user->login($identity,$duration);
}
else
$this->addError('password','Incorrect password.');
}
}
}

Contoh kode di atas menetapkan bahwa username dan password keduanya diperlukan, password harus diotentikasi.

Setiap aturan yang dikembalikan oleh rules() harus dalam format berikut:

array('AttributeList', 'Validator', 'on'=>'ScenarioList', ...opsi tambahan)

di mana AttributeList adalah string nama atribut yang dipisahkan dengan koma yang perlu divalidasi sesuai dengan aturan; Validator menetapan jenis validasi apa yang harus dilakukan; parameter on adalah opsional yang menetapkan daftar skenario di mana aturan harus diterapkan; dan opsi tambahan adalah pasangan nama-nilai yang dipakai untuk menginisialisasi nilai properti validator terkait.

Ada tiga cara untuk menetapkan Validator dalam aturan validasi. Pertama, Validator dapat berupa nama metode dalam kelas model, seperti authenticate dalam contoh di atas. Metode validator harus berupa tanda tangan berikut:

/**
*
@param string nama atribut yang akan divalidasi
*
@param array opsi yang ditetapkan dalam aturan validasi
*/
public function ValidatorName($attribute,$params) { ... }

Kedua, Validator dapat berupa nama kelas validator. Saat aturan diterapkan, turunan kelas validator akan dibuat untuk melakukan validasi sebenarnya. Opsi tambahan dalam aturan dipakai untuk menginisialisasi nilai atribut turunannya. Kelas validator harus diperluas dari CValidator.

Catatan: Saat menetapkan aturan untuk model rekaman aktif, kita dapat menggunakan opsi spesial bernama on. Opsi ini bisa berupa 'insert' atau 'update' agar aturan hanya diterapkan masing-masing saat penyisipan atau pemutakhiran rekaman. Jika tidak disetel, aturan akan diterapkan dalam kedua kasus tersebut saat save() dipanggil.

Ketiga, Validator dapat berupa alias pradefinisi untuk kelas validator. Dalam contoh di atas, nama required adalah alias untuk CRequiredValidator yang memastikan nilai atribut yang divalidasi tidak kosong. Di bawah ini adalah daftar lengkap alias pradefinisi validator aliases:

Di bawah ini daftar beberapa contoh pemakaian validator pradefinisi:

// username diperlukan
array('username', 'required'),
// username harus antara 3 dan 12 karakter
array('username', 'length', 'min'=>3, 'max'=>12),
// saat dalam skenario registrasi, password harus sama dengan password2
array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'),
// saat dalam skenario login, password harus diotentikasi
array('password', 'authenticate', 'on'=>'login'),

Mengamankan Penempatan Atribut

Catatan: penempatan atribut berbasis-skenario sudah tersedia sejak versi 1.0.2.

Setelah turunan model dibuat, seringkali kita perlu mempopulasikan atributnya dengan data yang dikirimkan oleh pengguna-akhir. Ini bisa dikerjakan dengan nyaman menggunakan penempatan masal berikut:

$model=new LoginForm;
$model->scenario='login';
if(isset($_POST['LoginForm']))
$model->attributes=$_POST['LoginForm'];

Catatan: Properti skenario sudah tersedia sejak versi 1.0.4. Penempatan masal akan mengambil nilai properti untuk menguji apakah atribut bisa ditempatkan secara masal. Dalam versi 1.0.2 dan 1.0.3, kita perlu menggunakan cara berikut untuk melakukan penempatan masal pada skenario tertentu:

$model->setAttributes($_POST['LoginForm'], 'login');

Penempatan terakhir adalah penempatan masal yang menempatkan setiap entri dalam $_POST['LoginForm'] ke atribut model terkait dalam skenario login. Ini sama dengan penempatan berikut:

foreach($_POST['LoginForm'] as $name=>$value)
{
if($name is a safe attribute)
$model->$name=$value;
}

Tugas memutuskan apakah entri data aman atau tidak didasarkan pada nilai balik metode bernama safeAttributes dan skenario yang ditetapkan. Secara standar, metode mengembalikan semua variabel anggota public sebagai atribut aman untuk CFormModel, sementara ia mengembalikan semua kolom tabel kecuali kunci primer sebagai atribut aman untuk CActiveRecord. Kita dapat menimpa metode ini guna membatasi atribut aman sesuai dengan skenario. Sebagai contoh, model pengguna dapat berisi beberapa atribut, tapi dalam skenario login kita hanya perlu menggunakan atribut username dan password. Kita dapat menetapkan batas ini seperti berikut:

public function safeAttributes()
{
return array(
parent::safeAttributes(),
'login' => 'username, password',
);
}

Lebih tepatnya, nilai balik metode safeAttributes seharusnya dalam struktur sebagai berikut:

array(
// atribut ini dapat ditempatkan secara masalah dalam setiap skenario
// yang tidak ditetapkan secara eksplisit di bawah ini
'attr1, attr2, ...',
*
// atribut ini dapat ditempatkan secara masal hana dalam skenario 1
'scenario1' => 'attr2, attr3, ...',
*
// atribut ini dapat ditempatkan secara masal hana dalam skenario 2
'scenario2' => 'attr1, attr3, ...',
)

Jika model bukan sensitif-skenario (misalnya, ia hanya dipakai dalam satu skenario, atau semua skenario berbagi set atribut aman yang sama), nilai balik dapat disederhanakan sebagai string tunggal:

'attr1, attr2, ...'

Untuk entri data yang tidak aman, kita perlu menempatkannya ke atribut terkait menggunakan pernyataan penempatan individual, seperti berikut:

$model->permission='admin';
$model->id=1;

Memicu Validasi

Setelah model dipopulasi dengan data yang dikirimkan-pengguna, kita memanggil CModel::validate() untuk memicu proses validasi data. Metode mengembalikan nilai yang menunjukan apakah validasi sukses atau tidak. Untuk model CActiveRecord, validasi juga dapat dipicu secara otomatis saat kita memanggil metode CActiveRecord::save().

Ketika kita memanggil CModel::validate(), kita dapat menetapkan parameter skenario. Hanya aturan validasi yang berlaku pada skenario yang ditetapkan yang akan dijalankan. Aturan validasi pada sebuah skenario jika opsi on pada aturan tidak disetel atau berisi nama skenario yang ditetapkan. Jika kita tidak menetapkan skenario saat memanggil CModel::validate(), hanya aturan yang memiliki opsi on tidak disetel yang akan dijalankan.

Sebagai contoh, kita menjalankan pernyataan berikut untuk melakukan validasi saat meregistrasi seorang pengguna:

$model->scenario='register';
$model->validate();

Catatan: Properti skenario sudah tersedia sejak versi 1.0.4. Metode validasi akan mengambil nilai properti untuk menguji aturan mana yang bisa diperiksa. Dalam versi 1.0.2 dan 1.0.3, kita perlu menggunakan cara berikut untuk melakukan validasi pada skenario tertentu:

$model->validate('register');

Kita dapat mendeklarasikan aturan validasi dalam kelas model formulir seperti brikut,

public function rules()
{
return array(
array('username, password', 'required'),
array('password_repeat', 'required', 'on'=>'register'),
array('password', 'compare', 'on'=>'register'),
);
}

Hasilnya, aturan pertama akan diterapkan dalam semua skenario, sementara dua aturan berikutnya hanya diterapkan dalam skenario register.

Catatan: validasi berbasis-skenario sudah tersedia sejak versi 1.0.1.

Mengambil Kesalahan Validasi

Kita dapat menggunakan CModel::hasErrors() untuk memeriksa apakah ada kesalahan validasi, dan jika ya, kita dapat menggunakan CModel::getErrors() untuk mengambil pesan kesalahan. Kedua metode dapat dipakai untuk semua atribut atau atribut individual.

Label Atribut

Ketika medesain sebuah formulir, seringkali kita perlu menampilkan label untuk setiap field input. Label memberitahu pengguna jenis informasi apa yang harus dimasukkan ke dalam field. Meskipun kita dapat memberi label secara langsung dalam sebuah tampilan, ini akan menawarkan fleksibilitas dan kenyamanan yang lebih jika kita menetapkannya dalam model terkait.

Secara standar, CModel akan mengembalikan nama atribut sebagai labelnya. Ini dapat dikustomisasi dengan menimpa metode attributeLabels(). Seperti yang akan kita lihat dalam subskenario berikutnya, menetapkan label dalam model mengijinkan kita untuk membuat formulir lebih cepat dan bertenaga.

Bekerja dengan Formulir

Pengumpulan data pengguna via formulir HTML adalah tugas utama dalam pengembangan aplikasi Web. Selain mendesain formulir, pengembang perlu mempopulasi formulir dengan data yang sudah ada atau nilai-nilai standar, memvalidasi input pengguna, menampilkan pesan kesalahan yang sesuai untuk input yang tidak benar, dan menyimpan input ke media penyimpan. Yii sudah menyederhanakan alur kerja ini dengan arsitektur MVC.

Langkah-langkah berikut umumnya diperlukan saat berhadapan dengan formulir dalam Yii:

  1. Buat kelas model yang mewakili field data yang dikumpulkan;
  2. Buat aksi kontroler dengan kode yang merespon pengiriman formulir.
  3. Buat formulir dalam file naskah tampilan sesuai dengan aksi kontroler.

Dalam subseksi berikut, kami menjelaskan setiap langkah ini secara lebih rinci.

Alur Kerja Pengembangan

Setelah menjelaskan konsep fundamental Yii, kami memperlihatkan alur kerja umum untuk pengembangan aplikasi web menggunakan Yii. Alur kerja mengasumsikan bahwa kita sudah menyelesaikan analisis persyaratan juga analisis desain aplikasi.

  1. Membuat kerangka struktur direktori. Piranti yiic yang dijelaskan dalam Membuat Aplikasi Pertama Yii dapat dipakai untuk mempercepat langkah ini.

  2. Mengkonfigurasi aplikasi. Ini dilakukan dengan memodifikasi file konfigurasi aplikasi. Langkah ini juga memerlukan penulisan beberapa komponen aplikasi (misalnya komponen pengguna).

  3. Membuat kelas model untuk setiap jenis data untuk diatur. Sekali lagi, yiic bisa dipakai guna membuat kelas rekaman aktif secara otomatis untuk tabel database yang diperlukan.

  4. Membuat kelas kontroler untuk setiap jenis permintaan pengguna. Bagaimana untuk mengklasifikasian permintaan pengguna tergantung pada kebutuhan sebenarnya. Secara umum, jika kelas model perlu diakses oleh pengguna, ia harus memiliki kelas kontroler terkait. Piranti yiic dapat mengotomasi langkah ini juga.

  5. Mengimplementasikan aksi dan tampilan terkait. Di sinilah pekerjaan sebenarnya yang perlu dilakukan.

  6. Mengkonfigurasi aksi yang diperlukan filter dalam kelas.

  7. Membuat tema jika fitur tema diperlukan.

  8. Membuat pesan terjemahan jika internasionalisasi diperlukan.

  9. Memilih data dan tampilan yang dapat di-cache dan menerapkan teknik caching yang sesuai.

  10. Terakhir, penyesuaian dan penyebaran.

Untuk setiap langkah di atas, pengujian kasus mungkin perlu dibuat dan diperlihatkan.

Konvensi

Yii mempunyai konvensi terhadap konfigurasi. Ikuti konvensi dan seseorang bisa membuat aplikasi Yii yang memuaskan tanpa harus menulis dan mengatur konfigurasi yang rumit. Tentunya, Yii masih dapat dikustomisasi dalam hampir setiap aspek dengan konfigurasi bila diperlukan.

Di bawah ini dijelaskan konvensi yang direkomendasikan untuk pemrograman Yii. Demi kenyamanan, kami asumsikan bahwa WebRoot adalah direktori di mana aplikasi Yii diinstalasi.

URL

Secara standar, Yii mengenali URL dengan format berikut:

http://hostname/index.php?r=ControllerID/ActionID

Variabel GET r merujuk pada rute yang bisa dipecah oleh Yii menjadi kontroler dan aksi. Jika ActionID tidak ada, kontroler akan mengambil aksi standar (didefinisikan via CController::defaultAction); dan jika ControllerID juga tidak ada (atau variabel r tidak ada), aplikasi akan menggunakan kontoler standar (didefinsikan via CWebApplication::defaultController).

Dengan bantuan CUrlManager, memungkinkan URL dibuat dan dikenal lebih ramah-SEO-friendly, seperti http://hostname/ControllerID/ActionID.html. Fitur ini dicakup secara rinci dalam URL Management.

Kode

Yii merekomendasikan penamaan variabel, fungsi dan tipe kelas dalam jenis huruf kamel yang membesarkan setiap kata pada nama dan menggabungkannya tanpa spasi. Nama variabel dan spasi namanya semuanya harus dalam huruf kecil, tujuannya untuk membedakannya dari nama kelas (contoh $basePath, runController(), LinkPager). Untuk variabel anggota kelas private, direkomendasikan untuk mengawali namanya dengan karakter garis bawah (contoh $_actionList).

Karena namespace tidak didukung oleh PHP sebelum versi 5.3.0, direkomendasikan bahwa kelas dinamai dalam cara yang unik guna menghindari konflik nama dengan kelas pihak-ketiga. Untuk alasan ini, semua kelas Yii framework diawali dengan huruf "C".

Aturan khusus untuk nama kelas kontroler, ia harus ditambah dengan kata Controller. Kemudian ID kontroler didefinisikan sebagai nama kelas dengan huruf pertamanya dalam huruf kecil dan kata Controller dipotong. Sebagai contoh, kelas PageController akan memiliki ID page. Aturan ini membuat aplikasi lebih aman. Ini juga menjadikan URL yang terkait dengan kontroler sedikit lebih bersih (contoh /index.php?r=page/index daripada /index.php?r=PageController/index).

Konfigurasi

Konfigurasi adalah sebuah array pasangan kunci-nilai. Setiap kunci mewakili nama properti obyek yang dikonfigurasi, dan setiap nilai merupakan nilai awal properti tersebut. Sebagai contoh, array('name'=>'My application', 'basePath'=>'./protected') mengawali properti name dan basePath ke nilai array terkait.

Setiap properti obyek yang bisa ditulis dapat dikonfigurasi. Jika tidak dikonfigurasi, properti akan mengambil nilai standar awal. Ketika mengkonfigurasi properti, tidak ada salahnya untuk membaca dokumentasi terkait agar nilai awal dapat diberikan dengan benar.

File

Konvensi penamaan dan penggunaan file tergantung pada tipenya.

File Kelas harus dinamai setelah kelas publik. Sebagai contoh, kelas CController pada file CController.php. Kelas publik adalah kelas yang dipakai oleh kelas lain. Setiap file kelas harus berisi paling banyak satu kelas. Kelas Private (kelas yang hanya dipakai oleh satu kelas publik) bisa berada dalam file yang sama dengan kelas publik.

File tampilan harus dinamai setelah nama tampilan. Sebagai contoh, tampilan index ada dalam file index.php. File tampilan adalah file naskah PHP yang berisi kode HTML dan PHP terutama untuk keperluan penyajian.

File konfigurasi bisa dinamai secara arbitrari. File konfigurasi adalah naskah PHP yang bertujuan untuk mengembalikan sebuah array asosiasi yang mewakili konfigurasi.

Direktori

Yii menganggap set standar direktori yang dipakai untuk berbagai keperluan. Masing-masing bisa dikustomisasi jika diperlukan.

  • WebRoot/protected: ini adalah basis direktori aplikasi menampung semua naskah PHP sensitif-keamanan dan file data. Yii memiliki alias standar bernama application yang dikaitkan dengan path ini. Direktori ini dan semua yang ada di bawahnya dilindungi dari pengaksesan pengguna Web. Ia bisa dikustomisasi via CWebApplication::basePath.

  • WebRoot/protected/runtime: direktori ini menampung file temporal privat yang dibuat selama menjalankan aplikasi. Direktori ini harus bisa ditulis oleh proses server Web. Ia dapat dikustomisasi melalui CApplication::runtimePath.

  • WebRoot/protected/extensions: direktori ini menampung semua ekstensi pihak ketiga. Ia dapat dikustomisasi melalui CApplication::extensionPath.

  • WebRoot/protected/modules: direktori ini menampung semua modul aplikasi, masing-masing diwakili oleh subdirektori.

  • WebRoot/protected/controllers: direktori ini menampung semua file kelas kontroler. Ia dapat dikustomisasi melalui CWebApplication::controllerPath.

  • WebRoot/protected/views: direktori ini menampung semua file tampilan, termasuk tampilan kontroler, tampilan tata letak dan tampilan sistem. Ia dapat dikustomisasi melalui CWebApplication::viewPath.

  • WebRoot/protected/views/ControllerID: direktori ini menampung file tampilan untuk satu kelas kontroler. Di sini, ControllerID kepenekan dari ID kontroler. Ia dapat dikustomisasi melalui CController::getViewPath.

  • WebRoot/protected/views/layouts: direktori ini menampung semua file tampilan tata letak. Ia dapat dikustomisasi melalui CWebApplication::layoutPath.

  • WebRoot/protected/views/system: direktori ini menampung semua file tampilan sistem. Tampilan sistem adalah template yang dipakai dalam menampilkan eksepsi dan kesalahan. Ia dapat dikustomisasi melalui CWebApplication::systemViewPath.

  • WebRoot/assets: direktori ini menampung file aset yang diterbitkan. File asset adalah file privat yang dapat diterbitkan agar bisa diakses oleh pengguna Web. Direktori ini harus bisa ditulis oleh proses server Web. Ia dapat dikustomisasi melalui CAssetManager::basePath.

  • WebRoot/themes: direktori ini menampung berbagai tema yang dapat diterapkan pada aplikasi. Setiap subdirektori mewakili satu tema yang namanya adalah nama subdirektori. Ia dapat dikustomisasi melalui CThemeManager::basePath.

Modul

Catatan: Dukungan modul sudah tersedia sejak versi 1.0.3.

Modul adalah unit piranti lunak berdiri sendiri yang terdiri dari model, tampilan, kontroler dan komponen pendukung lainnya. Dalam banyak aspek, sebuah modul mirip dengan aplikasi. Perbedaan utamanya adalah bahwa modul tidak bisa disebarkan sendirian dan ia harus berada di dalam sebuah aplikasi. Para pengguna dapat mengakses kontroler dalam sebuah modul layaknya yang dilakukan dengan kontroler aplikasi biasa.

Modul berguna dalam beberapa skenario. Untuk aplikasi berskala-besar, kita dapat membaginya ke dalam beberapa modul, masing-masing dikembangkan dan dipelihara secara terpisah. Beberapa fitur yang umum digunakan, seperti misalnya manajemen pengguna, manajemen komentar, dapat dikembangkan dalam batasan modul agar dapat dipakai kembali dengan mudah dalam proyek mendatang.

Membuat Modul

Modul diatur sebagai direktori di mana namanya bertindak sebagai ID unik. Struktur direktori modul mirip dengan basis direktori aplikasi. Contoh berikut memperlihatkan struktur umum direktori pada modul bernama forum:

forum/
ForumModule.php file kelas modul
components/ berisi komponen yang bisa dipakai ulang
views/ berisi file tampilan untuk widgets
controllers/ berisi file kelas kontroler
DefaultController.php file kelas kontroler standar
extensions/ berisi ekstensi pihak-ketiga
models/ berisi file kelas model
views/ berisi file tampilan kontroler dan tatat letak
layouts/ berisi file tampilan tata letak
default/ berisi file tampilan untuk DefaultController
index.php file tampilan indeks

Modul harus memiliki kelas modul yang diperluas dari CWebModule. Nama kelas ditentukan menggunakan ucfirst($id).'Module', di mana $id merujuk pada ID modul (atau nama direktori modul). Kelas modul bertindak sebagai pusat tempat penyimpanan informasi berbagi diantara kode modul. Sebagai contoh, kita dapat menggunakan CWebModule::params untuk menyimpan parameter modul, dan menggunakan CWebModule::components untuk berbagi komponen aplikasi pada tingkat modul.

Tip: Kita bisa menggunakan piranti yiic untuk membuat kerangka dasar modul baru. Sebagai contoh, untuk membuat modul forum di atas, kita dapat menjalankan perintah berikut dalam jendela baris perintah:

% cd WebRoot/testdrive
% protected/yiic shell
Yii Interactive Tool v1.0
Silahkan ketik 'help' untuk bantuan. Ketik 'exit' untuk keluar.
>> module forum

Menggunakan Modul

Untuk menggunakan modul, pertama tempatkan direktori modul di bawah basis direktori aplikasi modules. Kemudian deklarasikan ID modul dalam properti modul aplikasi. Sebagai contoh, agar bisa menggunakan modul forum di atas, kita dapat menggunakan konfigurasi aplikasi berikut:

return array(
......
'modules'=>array('forum',...),
......
);

Modul juga bisa dikonfigurasi dengan nilai properti awal. Pemakaian ini mirip dengan mengkonfigurasi komponen aplikasi. Sebagai contoh, modul forum dapat memiliki properti bernama postPerPage dakan kelas modulnya yang bisa dikonfigurasi dalam konfigurasi aplikasi sebagai berikut:

return array(
......
'modules'=>array(
'forum'=>array(
'postPerPage'=>20,
),
),
......
);

Turunan modul dapat diakses melalui properti modul pada kontroler yang aktif saat ini. Melalui turunan modul, selanjutnya kita dapat mengakses informasi yang dibagi pada tingkat modul. Sebagai contoh, agar bisa mengakses informasi postPerPage di atas, kita dapat menggunakan ekspresi berikut:

$postPerPage=Yii::app()->controller->module->postPerPage;
// atau yang berikut jika $this merujuk pada turunan kontroler
// $postPerPage=$this->module->postPerPage;

Aksi kontroler dalam sebuah modul dapat diakses menggunakan rute moduleID/controllerID/actionID. Sebagai contoh, menganggap modul forum di atas memiliki kontroler bernama PostController, kita dapat menggunakan rute forum/post/create untuk merujuk pada aksi create dalam kontroler ini. URL terkait untuk rute ini adalah http://www.example.com/index.php?r=forum/post/create.

Tip: Jika kontroler ada dalam sub-direktori controllers, kita masih dapat menggunakan format rute di atas. Sebagai contoh, menganggap PostController di bawah forum/controllers/admin, kita dapat merujuk pada aksi create menggunakan forum/admin/post/create.

Modul Berulang

Modul dapat diulang. Yaitu, sebuah modul bisa berisi modul lainnya. Kita menyebut pemanggil sebagai leluhur modul sementara yang dipanggil disebut anak modul. Anak modul harus ditempatkan di bawah direktori modules pada modul leluhurnya. Untuk mengakses aksi kontroler dalam anak modul, kita harus menggunakan rute parentModuleID/childModuleID/controllerID/actionID.

Alias Path dan Namespace

Yii menggunakan alias secara ekstensif. Alias path dikaitkan dengan direktori atau path file. Ditetapkan dalam sintaks titik, mirip dengan format namespace yang diadopsi secara luas:

RootAlias.path.ke.target

di mana RootAlias adalah alias dari beberapa direktori yang sudah ada. Dengan memanggil YiiBase::setPathOfAlias(), kita dapat menetapkan alias path baru. Demi kenyamanan, Yii sudah mendefinisikan alias root sebagai berikut:

  • system: merujuk pada direktori Yii framework;
  • application: merujuk pada basis direktori aplikasi;
  • webroot: merujuk pada direktori yang berisi file naskah entri. Alias ini sudah tersedia sejak versi 1.0.3.

Sebagai tambahan, jika aplikasi menggunakan modul, alias root juga didefinisikan untuk setiap ID modul dan merujuk pada basis path modul terkait. Fitur ini sudah tersedia sejak versi 1.0.3.

Dengan menggunakan YiiBase::getPathOfAlias(), alias dapat diterjemahkan ke path terkait. Sebagai contoh, system.web.CController akan diterjemahkan sebagai yii/framework/web/CController.

Menggunakan alias, sangat nyaman untuk mengimpor definisi sebuah kelas. Sebagai contoh, jika kita ingin menyertakan definisi kelas CController, kita dapat memanggil seperti berikut:

Yii::import('system.web.CController');

Metode import berbeda dari include dan require dalam hal ia lebih efisien. Definisi kelas yang sedang diimpor sebenarnya tidak disertakan sampai ia dirujuk untuk pertama kali. Mengimpor namespace yang sama berkali-kali juga lebih cepat daripada include_once dan require_once.

Tip: Ketika merujuk pada kelas yang didefinisikan oleh Yii framework, kita tidak perlu mengimpor atau menyertakannya. Semua kelas inti Yii sudah pra-impor.

Kita juga dapat menggunakan sintaks berikut untuk mengimpor seluruh direktori agar file kelas di bawah direktori tersebut secara otomatis disertakan saat diperlukan.

Yii::import('system.web.*');

Selain import, alias juga dipakai di banyak tempat lain untuk merujuk pada kelas. Sebagai contoh, alias dapat dioper ke Yii::createComponent() guna membuat turunan kelas terkait, meskipun file kelas tidak disertakan sebelumnya.

Jangan menyamakan antara alias path dengan namespace. Namespace merujuk pada pengelompokan logis beberapa nama kelas agar dapat dibedakan dari nama kelas lainnya jika namanya sama, sementara alias path dipakai untuk merujuk pada file kelas atau direktori. Alias path tidak konflik dengan namespace.

Tip: Karena PHP sebelum versi 5.3.0 tidak mendukung namespace secara langsung, Anda tidak dapat membuat turunan dari dua kelas yang memiliki nama yang sama dengan definisi yang berbeda. Untuk alasan ini, semua kelas Yii framework diawali dengan huruf 'C' (berarti 'class') agar bisa dibedakan dari kelas yang didefinisikan-pengguna. Direkomendasikan bahwa prefiks 'C' khusus dipakai hanya untuk pemakaian Yii framework saja, dan kelas yang didefinisikan-pengguna diawali dengan huruf lainnya.

Komponen

Aplikasi Yii dibangun setelah komponen berupa obyek ditulis menjadi spesifikasi. Sebuah komponen adalah turunan dari CComponent atau kelas sebelumnya. Pemakaian komponen meliputi pengaksesan propertinya dan memunculkan/menangani event-nya. Kelas basis CComponent menetapkan bagaimana untuk mendefinisikan properti dan event.

Properti Komponen

Properti komponen seperti variabel anggota public sebuah obyek. Kita dapat membaca nilainya atau menempatkan sebuah nilai ke dalamnya. Sebagai contoh,

$width=$component->textWidth;     // ambil properti textWidth
$component->enableCaching=true; // setel properti enableCaching

Untuk mendefinisikan properti komponen, kita cuku mendeklarasian variabel anggota public dalam kelas komponen. Cara yang lebih fleksibel adalah dengan mendefinisikan metode getter (pengambil) dan setter (penyetel) seperti berikut:

public function getTextWidth()
{
return $this->_textWidth;
}

public function setTextWidth($value)
{
$this->_textWidth=$value;
}

Kode di atas mendefinisikan properti yang bisa ditulis dengan nama textWidth (nama sensitif jenis huruf). Ketika membaca properti, getTextWidth() dipanggil dan nilai yang dihasilkannya menjadi nilai properti; Hal yang mirip, saat menulis properti, setTextWidth() dipanggil. Jika metode penyetel tidak didefinisikan, properti akan menjadi hanya-baca dan menulisinya akan memunculkan sebuah eksepsi. Menggunakan metode pengambil dan penyetel untuk mendefinisikan sebuah properti memiliki keuntungan bahwa logika tambahan (seperti melakukan validasi, memunculkan event) dapat dijalankan saat membaca dan menulis properti.

Catatan: Ada perbedaan menyolok antara properti yang didefinisikan via metode pengambil/penyetel dan variabel anggota kelas. Nama pengambil/penyetel tidak sensitif jenis huruf sementara variabel anggota kelas sensitif jenis huruf.

Event Komponen

Event komponen adalah properti khusus yang mengambil metode (disebut pengendali event) sebagai nilainya. Melampirkan (menempatkan) metode ke sebuah event akan menyebabkan metode dipanggil secara otomatis di tempat di mana event dimunculkan. Oleh karena itu, perilaku komponen bisa diubah dengan cara yang tidak bisa dilihat selama pengembangan komponen.

Event komponen didefinisikan dengan mendefinisikan sebuah metode yang namanya dimulai dengan on. Seperti nama properti yang didefinisikan via metode pengambil/penyetel, nama event tidak sensitif jenis huruf. Kode berikut mendefinisikan sebuah event onClicked:

public function onClicked($event)
{
$this->raiseEvent('onClicked', $event);
}

di mana $event adalah turunan CEvent atau anak kelasnya yang menyediakan parameter event.

Kita dapat melampirkan sebuah metode ke event ini seperti berikut:

$component->onClicked=$callback;

di mana $callback merujuk ke PHP callback yang benar. Ia bisa berupa fungsi global atau metode kelas. Jika metode kelas, callback harus dibentuk sebagai array: array($object,'methodName').

Tanda tangan pengenali event harus seperti berikut:

function methodName($event)
{
......
}

di mana $event merupakan parameter yang menjelaskan event (ia berasal dari panggilan raiseEvent()). Parameter $event adalah turunan dari CEvent atau kelas sebelumnya. Pada kondisi minimum, ia berisi informasi mengenai siapa yang memunculkan event.

Jika kita memanggil onClicked() sekarang, event onClicked akan dimunculkan (di dalam onClicked()), dan pengendali event terlampir akan dipanggil secara otomatis.

Sebuah event dapat dilampirkan ke multipel pengendali. Saat event dimunculkan, pengendali akan dipanggil dengan urutan di mana ia dilampirkan ke event. Jika sebuah pengendali memutuskan untuk menghindari pemanggilan pengendali berikutnya, bisa dilakukan dengan menyetel $event->handled menjadi true.

Perilaku Komponen

Mulai dari versi 1.0.2, sebuah komponen sudah ditambahkan guna mendukung mixin dan dapat dilampirkan dengan satu atau beberapa perilaku. Sebuah perilaku adalah obyek yang metodenya bisa 'inherited' (diturunkan) dengan komponen lampirannya dalam arti pengumpulan fungsionalitas daripada spesialisasi (misal, penurunan kelas normal). Komponen dapat dilampirkan ke beberapa perilaku dan selanjutnya melakukan 'multipel penurunan'.

Kelas perilaku harus mengimplementasikan antar muka IBehavior. Umumnya perilaku dapat diperluas dari kelas basis CBehavior. Jika perilaku perlu dilampirkan ke sebuah model, ia juga bisa diperluas dari CModelBehavior atau CActiveRecordBehavior yang mengimplementasikan fitur tambahan tertentu untuk model.

Untuk menggunakan perilaku, ia harus dilampirkan ke sebuah komponen lebih dulu dengan memanggil metode perilaku attach(). Kemudian kita memanggil metode perilaku melalui komponen:

// $name secara unik mengidentifikasi behavior dalam komponen
$behavior->attach($name,$component);
// test() adalah metode $behavior
$component->test();

Perilaku yang dilampirkan dapat diakses seperti layaknya properti komponen. Sebagai contoh, jika perilaku bernama tree dilampirkan ke komponen, kita bisa memperoleh referensi ke obyek perilaku ini menggunakan:

$behavior=$component->tree;
// sama dengan kode berikut:
// $behavior=$component->asa('tree');

Sebuah perilaku dapat dimatikan sementara agar metodenya tidak tersedia pada komponen. Sebagai contoh,

$component->disableBehavior($name);
// pernyataan berikut akan memunculkan eksepsi
$component->test();
$component->enableBehavior($name);
// ia bekerja sekarang
$component->test();

Dimungkinkan bahwa dua perilaku dilampirkan ke komponen yang sama yang memiliki nama metode yang sama. Dalam hal ini, perilaku metode pertama yang akan diprioritaskan.

Ketika dipakai bersama dengan event, perilaku bahkan lebih bertenaga. Sebuah perilaku, bila dilampirkan ke sebuah komponen dapat melampirkan beberapa metodenya ke beberapa event komponen. Dengan melakukan itu, perilaku mendapat kesempatan untuk mengawasi atau mengubah alur eksekusi normal komponen.

Tampilan

Tampilan (view) adalah naskah PHP yang berisi terutama elemen antar muka pengguna. Ia bisa berisi pernyataan PHP, tapi direkomendasikan bahwa pernyataan ini tidak mengubah model data dan harus tetap relatif sederhana. Untuk semangat pemisahan logika dan penyajian, bagian besar logika harus ditempatkan dalam kontroler atau model daripada tampilan.

Tampilan memiliki nama yang dipakai untuk mengidentifikasi file naskah tampilan saat penyiapan. Nama tampilan sama seperti nama file naskah tampilan. Sebagai contoh, tampilan edit merujuk pada file naskah bernama seperti edit.php. Untuk menyiapkan tampilan, pangil CController::render() dengan nama tampilan. Metode akan mencari file tampilan terkait di bawah direktori protected/views/ControllerID.

Di dalam naskah tampilan, kita dapat mengakses turunan kontroler menggunakan $this. Selanjutnya kita bisa menarik setiap properti kontroler dengan mengevaluasi $this->propertyName dalam tampilan.

Kita juga bisa menggunakan pendekatan dorong berikut guna mengoper data ke tampilan:

$this->render('edit', array(
'var1'=>$value1,
'var2'=>$value2,
));

Dalam contoh di atas, metode render() akan mengurai parameter array kedua ke dalam variabel. Hasilnya, dalam naskah tampilan kita dapat mengakses variabel lokal $var1 dan $var2.

Tata Letak

Tata letak adalah tampilan khusus yang dipakai untuk mendekorasi tampilan. Biasanya berisi bagian antar muka pengguna yang umum diantara beberapa tampilan. Sebagai contoh, tata letak mungkin berisi bagian header dan footer serta menyertakan tampilan konten diantarana,

......header di sini......
php echo $content; ?>
......
footer di sini......

di mana $content menyimpan hasil pembuatan tampilan konten.

Tata letak secara implisit diterapkan saat memanggil render(). Secara standar, naskah tampilan protected/views/layouts/main.php dipakai sebagai tata letak. Ini bisa dikustomisasi dengan mengubah baik CWebApplication::layout ataupun CController::layout. Sebaliknya, untuk menyiapkan tampilan tanpa menerapkan tata letak apapun, panggil renderPartial().

Widget

Widget adalah turunan dari CWidget atau anak kelasnya. Komponen yang terutama ditujukan guna keperluan penyajian. Widget biasanya disertakan dalam naskah tampilan untuk menghasilkan beberapa antar muka pengguna yang kompleks dan berdiri sendiri. Sebagai contoh, widget kalender bisa dipakai untuk menyiapkan antar muka kalender pengguna yang kompleks. Widget menghidupkan pemakaian kembali yang lebih baik dalam antar muka pengguna.

Untuk menggunakan widget, lakukan seperti berikut dalam naskah tampilan:

 $this->beginWidget('path.to.WidgetClass'); ?>
...
konten body yang dapat ditangkap oleh widget...
php $this->endWidget(); ?>

atau

 $this->widget('path.to.WidgetClass'); ?>

Contoh kedua dipakai saat widget tidak memerlukan konten body apapun.

Widget dapat dikonfigurasi untuk mengkustomisasi perilakunya. Ini dilakukan dengan menyetel nilai properti awalnya ketika memanggil CBaseController::beginWidget atau CBaseController::widget. Sebagai contoh, ketika menggunakan widget CMaskedTextField, kita ingin menetapkan pelapisan agar dipakai. Kita dapat melakukannya dengan mengoper array nilai awal properti itu sebagai berikut, di mana kunci array adalah nama properti dan nilai array adalah nilai awal pada properti widget terkait:


$this->widget('CMaskedTextField',array(
'mask'=>'99/99/9999'
));
?>

Untuk mendefinisikan widget baru, perluas CWidget dan timpa metode init() dan run():

class MyWidget extends CWidget
{
public function init()
{
// metode ini dipanggil oleh CController::beginWidget()
}

public function run()
{
// metode ini dipanggil oleh CController::endWidget()
}
}

Seperti halnya kontroler, widget juga bisa memiliki tampilan sendiri. Standarnya, file tampilan widget ditempatkan di bawah subdirektori views pada direktori yang berisi file kelas widget. Tampilan ini disiapkan dengan memanggil CWidget::render(), mirip dengan pemanggilan kontroler. Perbedaannya tidak ada tata letak yang akan diterapkan pada tampilan widget.

Tampilan Sistem

Tampilan sistem merujuk pada tampilan yang dipakai oleh Yii untuk menampilkan kesalahan dan pencatatan informasi. Sebagai contoh, ketika permintaan pengguna untuk kontroler atau aksi yang tidak ada, Yii akan memunculkan eksepsi yang menjelaskan kesalahan. Yii menampilkan eksepsi menggunakan tampilan sistem tertentu.

Penamaan tampilan sistem mengikuti beberapa aturan. Nama seperti errorXXX merujuk pada tampilan untuk menampilkan CHttpException dengan kode kesalahan XXX. Sebagai contoh, jika CHttpException dimunculkan dengan kode kesalahan 404, tampilan error404 akan diperlihatkan.

Yii menyediakan satu set tampilan sistem standar yang ditempatkan di bawah framework/views. Ini bisa dikustomisasi dengan membuat file tampilan yang sama dengan nama yang sama di bawah protected/views/system.