mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-06 08:14:21 +01:00
640 lines
24 KiB
Plaintext
640 lines
24 KiB
Plaintext
Rekaman Aktif
|
|
=============
|
|
|
|
Meskipun Yii DAO secara virtual dapat menangani setiap tugas terkait-database,
|
|
kenyataannya kita akan menghabiskan 90% waktu kita dalam penulisan beberapa pernyataan SQL
|
|
yang melakukan operasi umum CRUD (create, read, update dan delete).
|
|
Ini juga akan sulit untuk memelihara kode kita saat ia dicampur dengan
|
|
pernyataan SQL. Untuk memecahkan masalah ini, kita dapat menggunakan Rekaman Aktif.
|
|
|
|
Rekaman Aktif / Active Record (AR) adalah teknik populer Pemetaan Relasional Obyek / Object-Relational Mapping (ORM).
|
|
Setiap kelas AR mewakili tabel database (atau view) yang atributnya diwakili
|
|
oleh properti kelas AR, dan turunan AR mewakili baris pada tabel
|
|
tersebut. Operasi umum CRUD diimplementasikan sebagai metode AR. Hasilnya,
|
|
kita dapat mengakses data dengan cara lebih terorientasi-obyek. Sebagai contoh,
|
|
kita dapat menggunakan kode berikut untuk menyisipkan baris baru ke dalam tabel `Post`:
|
|
|
|
~~~
|
|
[php]
|
|
$post=new Post;
|
|
$post->title='sample post';
|
|
$post->content='post body content';
|
|
$post->save();
|
|
~~~
|
|
|
|
Selanjutnya kami jelaskan bagaimana menyiapkan AR dan menggunakannya untuk melakukan operasi
|
|
CRUD. Kami akan memperlihatkan bagaimana untuk menggunakan AR untuk bekerja dengan relasi database
|
|
dalam seksi berikutnya. Demi kemudahan, kami gunakan tabel database berikut
|
|
sebagai contoh kita dalam seksi ini. Catatan bahwa jika Anda menggunakan database MySQL,
|
|
Anda harus mengganti `AUTOINCREMENT` dengan `AUTO_INCREMENT` dalam SQL berikut.
|
|
|
|
~~~
|
|
[sql]
|
|
CREATE TABLE Post (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
title VARCHAR(128) NOT NULL,
|
|
content TEXT NOT NULL,
|
|
createTime INTEGER NOT NULL
|
|
);
|
|
~~~
|
|
|
|
> Note|Catatan: AR tidak ditujukan untuk memecahkan semua tugas-tugas terkait-database.
|
|
Hal terbaik dipakai untuk memodelkan tabel database dalam konstruksi PHP dan melakukan
|
|
queri yang tidak melibatkan SQL yang kompleks. Yii DAO harus dipakai untuk skenario
|
|
kompleks tersebut.
|
|
|
|
|
|
Membuat Koneksi DB
|
|
--------------------
|
|
|
|
AR bergantung pada koneksi DB untuk melaksanakan operasi terkait-DB. Secara standar,
|
|
ia menganggap bahwa komponen aplikasi `db` adalah turunan
|
|
[CDbConnection] yang dibutuhkan untuk bertindak sebagai koneksi DB. Konfigurasi
|
|
aplikasi berikut memperlihatkan sebuah contoh:
|
|
|
|
~~~
|
|
[php]
|
|
return array(
|
|
'components'=>array(
|
|
'db'=>array(
|
|
'class'=>'system.db.CDbConnection',
|
|
'connectionString'=>'sqlite:path/to/dbfile',
|
|
// hidupkan cache schema untuk meningkatkan performansi
|
|
// 'schemaCachingDuration'=>3600,
|
|
),
|
|
),
|
|
);
|
|
~~~
|
|
|
|
> Tip: Karena Rekaman Aktif bergantung pada metadata mengenai tabel untuk
|
|
menentukan informasi kolom, dibutuhkan waktu guna membaca metadata dan
|
|
menganalisanya. Jika skema database Anda kurang sepertinya perlu diubah,
|
|
Anda harus menghidupkan cache skema dengan mengkonfigurasi properti
|
|
[CDbConnection::schemaCachingDuration] ke nilai lebih besar daripada
|
|
0.
|
|
|
|
Dukungan terhadap AR dibatasi oleh DBMS. Saat ini, hanya DBMS berikut yang
|
|
didukung:
|
|
|
|
- [MySQL 4.1 atau lebih tinggi](http://www.mysql.com)
|
|
- [PostgreSQL 7.3 atau lebih tinggi](http://www.postgres.com)
|
|
- [SQLite 2 dan 3](http://www.sqlite.org)
|
|
- [Microsoft SQL Server 2000 atau lebih tinggi](http://www.microsoft.com/sqlserver/)
|
|
- [Oracle](http://www.oracle.com)
|
|
|
|
> Note|Catatan: Dukungan untuk Microsoft SQL Server sudah tersedia sejak versi 1.0.4;
|
|
> Dan dukungan untuk Oracle sudah tersedia sejak versi 1.0.5.
|
|
|
|
Jika Anda ingin menggunakan komponen aplikasi selain `db`, atau jika Anda
|
|
ingin bekerja dengan multipel database menggunakan AR, Anda harus menimpa
|
|
[CActiveRecord::getDbConnection()]. Kelas [CActiveRecord] adalah basis kelas
|
|
untuk semua kelas AR.
|
|
|
|
> Tip: Ada dua cara untuk bekerja dengan multipel database dalam AR. Jika
|
|
skema database berbeda, Anda dapat membuat basis kelas AR yang berbeda
|
|
dengan implementasi berbeda pada
|
|
[getDbConnection()|CActiveRecord::getDbConnection]. Sebaliknya, secara dinamis
|
|
mengubah variabel static [CActiveRecord::db] merupakan ide yang lebih baik.
|
|
|
|
Mendefinisikan Kelas AR
|
|
-----------------------
|
|
|
|
Untuk mengakses tabel database, pertama kita perlu mendefinisikan kelas AR dengan
|
|
memperluas [CActiveRecord]. Setiap kelas AR mewakili satu tabel database,
|
|
dan turunan AR mewakili sebuah baris dalam tabel tersebut. Contoh berikut
|
|
memperlihatkan kode minimal yang diperlukan untuk kelas AR yang mewakili
|
|
tabel `Post`.
|
|
|
|
~~~
|
|
[php]
|
|
class Post extends CActiveRecord
|
|
{
|
|
public static function model($className=__CLASS__)
|
|
{
|
|
return parent::model($className);
|
|
}
|
|
}
|
|
~~~
|
|
|
|
> Tip: Karena kelas AR sering dirujuk di banyak tempat, kita dapat
|
|
> mengimpor seluruh direktori yang berisi kelas AR, daripada menyertakannya
|
|
> satu demi satu. Sebagai contoh, jika semua file kelas AR kita di bawah
|
|
> `protected/models`, kita dapat mengkonfigurasi aplikasi sebagai berikut:
|
|
> ~~~
|
|
> [php]
|
|
> return array(
|
|
> 'import'=>array(
|
|
> 'application.models.*',
|
|
> ),
|
|
> );
|
|
> ~~~
|
|
|
|
Secara standar, nama kelas AR sama seperti nama tabel database.
|
|
Menimpa metode [tableName()|CActiveRecord::tableName] jika berbeda.
|
|
Metode [model()|CActiveRecord::model] dideklarasikan seperti itu
|
|
untuk setiap kelas AR (akan dijelaskan kemudian).
|
|
|
|
Nilai kolom pada baris tabel dapat diakses sebagai properti
|
|
turunan kelas AR terkait. Sebagai contoh, kode berikut menyetel kolom
|
|
`title` (atribut):
|
|
|
|
~~~
|
|
[php]
|
|
$post=new Post;
|
|
$post->title='a sample post';
|
|
~~~
|
|
|
|
Meskipun kita tidak pernah mendeklarasikan properti `title` secara eksplisit dalam kelas `Post`,
|
|
kita masih dapat mengaksesnya dalam kode di atas. Ini disebabkan `title` adalah
|
|
kolom dalam tabel `Post`, dan CActiveRecord membuatnya bisa diakses seperti layaknya
|
|
properti dengan bantuan metode magic PHP `__get()`. Eksepsi akan ditampilkan
|
|
jika kita mencoba mengakses kolom yang tidak ada dengan cara yang sama.
|
|
|
|
> Info: Untuk pembacaan yang lebih baik, kami sarankan penamaan tabel database dan
|
|
kolom dalam jenis pundak unta. Secara khusus, nama tabel dibentuk dengan
|
|
membesarkan setiap kata pada namanya dan menggabungkannya tanpa spasi; nama
|
|
kolom mirip dengan nama tabel kecuali huruf pertamanya dalam jenis huruf
|
|
kecil. Sebagai contoh, kita menggunakan `Post` untuk menamai tabel penyimpanan tulisan; dan kita
|
|
menggunakan `createTime` untuk menamai kolom kunci primer tabel. Ini menjadikan tabel
|
|
terlihat lebih seperti tipe kelas dan kolom seperti variabel. Catatan, akan tetapi,
|
|
pemakaian punduk unta juga membuat Anda tidak nyaman pada beberapa DBMS, seperti misalnya MySQL,
|
|
karena ia bertindak secara berbeda pada sistem operasi yang berbeda.
|
|
|
|
|
|
Membuat Rekaman
|
|
---------------
|
|
|
|
Untuk menyisipkan baris baru ke dalam tabel database, kita membuat turunan baru kelas
|
|
AR terkait, menyetel propertinya yang terkait dengan kolom tabel,
|
|
dan memanggil metode [save()|CActiveRecord::save] untuk menyelesaikan
|
|
penyisipan.
|
|
|
|
~~~
|
|
[php]
|
|
$post=new Post;
|
|
$post->title='sample post';
|
|
$post->content='content for the sample post';
|
|
$post->createTime=time();
|
|
$post->save();
|
|
~~~
|
|
|
|
Jika kunci primer table adalah auto-incremental, setelah menyisipkan turunan AR
|
|
ia akan berisi kunci primer yang baru dimutakhirkan. Dalam contoh di atas, properti
|
|
`id` akan merujuk pada nilai kunci primer tulisan yang baru saja disisipkan,
|
|
meskipun kita tidak pernah mengubahnya secara eksplisit.
|
|
|
|
Jika kolom didefinisikan dengan beberapa nilai standar statis (misalnya string, angka)
|
|
dalam skema tabel, properti terkait dalam turunan AR akan secara otomatis memiliki
|
|
nilai tersebut setelah turunan dibuat. Satu cara untuk mengubah nilai standar ini
|
|
adalah dengan secara eksplisit mendeklarasikan properti dalam
|
|
kelas AR:
|
|
|
|
~~~
|
|
[php]
|
|
class Post extends CActiveRecord
|
|
{
|
|
public $title='please enter a title';
|
|
......
|
|
}
|
|
|
|
$post=new Post;
|
|
echo $post->title; // ini akan menampilkan: please enter a title
|
|
~~~
|
|
|
|
Mulai dari versi 1.0.2, atribut dapat menempatkan nilai tipe [CDbExpression]
|
|
sebelum rekaman disimpan (baik penyisipan ataupun pemutakhiran) ke database.
|
|
Sebagai contoh, untuk menyimpan timestamp yang dihasilkan oleh fungsi MySQL `NOW()`,
|
|
kita dapat menggunakan kode berikut:
|
|
|
|
~~~
|
|
[php]
|
|
$post=new Post;
|
|
$post->createTime=new CDbExpression('NOW()');
|
|
// $post->createTime='NOW()'; tidak akan bekerja karena
|
|
// 'NOW()' akan dianggap sebagai string
|
|
$post->save();
|
|
~~~
|
|
|
|
> Tip: Karena AR mengijinkan kita untuk melakukan operasi database tanpa menulis
|
|
sejumlah pernyataan SQL, seringkali kita ingin mengetahui pernyataan SQL apa yang dijalankan
|
|
oleh AR. Ini bisa dilakukan dengan menghidupkan [fitur pencatatan](/doc/guide/topics.logging)
|
|
pada Yii. Sebagai contoh, kita dapat menghidupkan [CWebLogRoute] dalam konfigurasi aplikasi,
|
|
dan kita akan melihat pernyataan SQL yang dijalankan untuk ditampilkan di akhir setiap halaman Web.
|
|
Sejak versi 1.0.5, kita dapat menyetel [CDbConnection::enableParamLogging] menjadi true dalam
|
|
konfigurasi aplikasi agar nilai parameter yang diikat ke pernyataan SQL
|
|
juga dicatat.
|
|
|
|
|
|
Membaca Rekaman
|
|
---------------
|
|
|
|
Untuk membaca data dalam tabel database, kita memanggil salah satu metode `find` seperti
|
|
berikut.
|
|
|
|
~~~
|
|
[php]
|
|
// cari baris pertama sesuai dengan kondisi yang ditetapkan
|
|
$post=Post::model()->find($condition,$params);
|
|
// cari baris dengan kunci primer yang ditetapkan
|
|
$post=Post::model()->findByPk($postID,$condition,$params);
|
|
// cari baris dengan nilai atribut yang ditetapkan
|
|
$post=Post::model()->findByAttributes($attributes,$condition,$params);
|
|
// cari baris pertama menggunakan pernyataan SQL yang ditetapkan
|
|
$post=Post::model()->findBySql($sql,$params);
|
|
~~~
|
|
|
|
Dalam contoh di atas, kita memanggil metode `find` dengan `Post::model()`. Ingat
|
|
bahwa metode statis `model()` diperlukan oleh setiap kelas AR. Metode
|
|
menghasilkan turunan AR yang dipakai untuk mengakses metode tingkat kelas
|
|
(mirip dengan metode kelas static) dalam konteks obyek.
|
|
|
|
Jika metode `find` menemukan baris yang sesuai dengan kondisi queri, ia akan
|
|
mengembalikan turunan `Post` yang propertinya berisi nilai kolom terkait
|
|
dari baris table. Kemudian kita dapat membaca nilai yang diambil sepert yang
|
|
kita lakukan pada properti obyek, sebagai contoh, `echo $post->title;`.
|
|
|
|
Metode `find` akan menghasilkan null jika tidak ada yang ditemukan dalam database
|
|
dengan kondisi queri yang diberikan.
|
|
|
|
Ketika memanggil `find`, kita menggunakan `$condition` dan `$params` untuk menetapkan kondisi
|
|
queri. Di sini, `$condition` dapat berupa string yang mewakili klausul `WHERE` dalam
|
|
pernyataan SQL, dan `$params` adalah array parameter yang nilainya harus diikat
|
|
ke tempat di dalam `$condition`. Sebagai contoh,
|
|
|
|
~~~
|
|
[php]
|
|
// cari baris dengan postID=10
|
|
$post=Post::model()->find('postID=:postID', array(':postID'=>10));
|
|
~~~
|
|
|
|
> Note|Catatan: Dalam contoh di atas, kita mungkin perlu melapisi referensi pada kolom `postID`
|
|
untuk DBMS tertentu. Sebagai contoh, jika kita menggunakan PostgreSQL, kita harus menulis
|
|
kondisi sebagai `"postID"=:postID`, karena PostgreSQL standarnya akan memperlakukan nama
|
|
kolom tidak sensitif jenis huruf.
|
|
|
|
Kita juga bisa menggunakan `$condition` untuk menetapkan kondisi queri lebih kompleks
|
|
Daripada sebuah string kita membiarkan `$condition` menjadi turunan [CDbCriteria] yang
|
|
mengijinkan kita untuk menetapkan kondisi selain klausul `WHERE`. Sebagai contoh,
|
|
|
|
~~~
|
|
[php]
|
|
$criteria=new CDbCriteria;
|
|
$criteria->select='title'; // hanya memilih kolom 'title'
|
|
$criteria->condition='postID=:postID';
|
|
$criteria->params=array(':postID'=>10);
|
|
$post=Post::model()->find($criteria); // $params tidak diperlukan
|
|
~~~
|
|
|
|
Catatan, saat menggunakan [CDbCriteria] sebagai kondisi queri, parameter `$params`
|
|
tidak lagi diperlukan karena ia bisa ditetapkan dalam [CDbCriteria], seperti dicontohkan
|
|
di atas.
|
|
|
|
Cara alternatif terhadap [CDbCriteria] adalah dengan mengoper array ke metode `find`.
|
|
Kunci dan nilai array masing-masing berhubungan dengan properti kriteria nama dan nilai.
|
|
Contoh di atas dapat ditulis ulang seperti berikut
|
|
|
|
~~~
|
|
[php]
|
|
$post=Post::model()->find(array(
|
|
'select'=>'title',
|
|
'condition'=>'postID=:postID',
|
|
'params'=>array(':postID'=>10),
|
|
));
|
|
~~~
|
|
|
|
> Info: Saat kondisi queri menemukan beberapa kolom dengan nilai yang
|
|
ditetapkan, kita dapat menggunakan
|
|
[findByAttributes()|CActiveRecord::findByAttributes]. Kita biarkan parameter
|
|
`$attributes` menjadi array nilai yang diindeks oleh nama kolom.
|
|
Dalam beberapa framework, tugas ini bisa dilaksanakan dengan memanggil metode
|
|
seperti `findByNameAndTitle`. Meskipun pendekatan ini terlihat atraktif, sering
|
|
menyebabkan kebingungan, konflik dan masalah seperti sensitifitas-jenis huruf pada
|
|
nama-nama kolom.
|
|
|
|
Ketika multipel baris data sama seperti kondisi queri yang ditetapkan, kita dapat
|
|
membawanya sekaligus menggunakan metode `findAll`, masing-masing memiliki
|
|
pasangan metode `find`, seperti yang sudah kami jelaskan.
|
|
|
|
~~~
|
|
[php]
|
|
// cari seluruh baris yang sesuai dengan kondisi yang ditetapkan
|
|
$posts=Post::model()->findAll($condition,$params);
|
|
// cari seluruh baris dengan kunci primer yang ditetapkan
|
|
$posts=Post::model()->findAllByPk($postIDs,$condition,$params);
|
|
// cari seluruh baris dengan nilai atribut yang ditetapkan
|
|
$posts=Post::model()->findAllByAttributes($attributes,$condition,$params);
|
|
// cari seluruh baris dengan pernyataan SQL yang ditetapkan
|
|
$posts=Post::model()->findAllBySql($sql,$params);
|
|
~~~
|
|
|
|
Jika tidak ada yang sama dengan kondisi queri, `findAll` akan mengembalikan array
|
|
kosong. Ini berbeda dengan `find` yang akan mengembalikan null jika tidak menemukan
|
|
apapun.
|
|
|
|
Selain metode `find` dan `findAll` seperti dijelaskan di atas, metode berikut
|
|
juga disediakan demi kenyamanan:
|
|
|
|
~~~
|
|
[php]
|
|
// ambil sejumlah baris yang sesuai dengan kondisi yang ditetapkan
|
|
$n=Post::model()->count($condition,$params);
|
|
// ambil sejumlah baris menggunakan pernyataan SQL yang ditetapkan
|
|
$n=Post::model()->countBySql($sql,$params);
|
|
// periksa apakah ada satu baris yang sesuai denga kondisi yang ditetapkan
|
|
$exists=Post::model()->exists($condition,$params);
|
|
~~~
|
|
|
|
Memutakhirkan Rekaman
|
|
---------------------
|
|
|
|
Setelah turunan AR dipopulasikan dengan nilai kolom, kita dapat mengubah
|
|
dan menyimpannya kembali ke tabel database.
|
|
|
|
~~~
|
|
[php]
|
|
$post=Post::model()->findByPk(10);
|
|
$post->title='new post title';
|
|
$post->save(); // simpan perubahan ke database
|
|
~~~
|
|
|
|
Seperti yang kita lihat, kita menggunakan metode [save()|CActiveRecord::save] yang sama
|
|
untuk melakukan operasi penyisipan dan pemutakhiran. Jika turunan AR dibuat
|
|
menggunakan operator `new`, pemanggilan [save()|CActiveRecord::save] akan menyisipkan
|
|
baris rekaman baru ke dalam tabel database; jika turunan AR adalah hasil dari beberapa
|
|
pemanggilan metode `find` atau `findAll`, memanggil [save()|CActiveRecord::save] akan
|
|
memutakhirkan baris yang sudah ada dalam tabel. Bahkan, kita dapat menggunakan
|
|
[CActiveRecord::isNewRecord] untuk memberitahu turunan AR baru atau tidak.
|
|
|
|
Dimungkinkan juga untuk memutakhirkan satu atau beberapa baris dalam sebuah tabel database
|
|
tanpa memanggilnya lebih dulu. AR menyediakan metode tingkat-kelas yang nyaman
|
|
untuk tujuan ini:
|
|
|
|
~~~
|
|
[php]
|
|
// mutakhirkan baris yang sama seperti kondisi yang ditetapkan
|
|
Post::model()->updateAll($attributes,$condition,$params);
|
|
// mutakhirkan baris yang sama seperti kondisi dan kunci primer yang ditetapkan
|
|
Post::model()->updateByPk($pk,$attributes,$condition,$params);
|
|
// mutakhirkan kolom counter dalam baris yang sesuai dengan kondisi yang ditetapkan
|
|
Post::model()->updateCounters($counters,$condition,$params);
|
|
~~~
|
|
|
|
Dalam contoh di atas, `$attributes` adalah array nilai kolom yang diindeks oleh
|
|
nama kolom; `$counters` adalah array nilai inkremental yang diindeks oleh nama
|
|
kolom; sedangkan `$condition` dan `$params` seperti yang sudah dijelaskan dalam
|
|
subseksi sebelumnya.
|
|
|
|
Menghapus Rekaman
|
|
-----------------
|
|
|
|
Kita juga bisa menghapus baris data jika turunan AR sudah dipopulasikan
|
|
dengan baris ini.
|
|
|
|
~~~
|
|
[php]
|
|
$post=Post::model()->findByPk(10); // menganggap ada tulisan yang memiliki ID = 10
|
|
$post->delete(); // hapus baris dari tabel database
|
|
~~~
|
|
|
|
Catatan, setelah penghapusan, turunan AR tetap tidak berubah, tapi baris
|
|
terkait dalam tabel database sudah tidak ada.
|
|
|
|
Metode tingkat kelas berikut disediakan untuk menghapus baris tanpa
|
|
haris mengambilnya lebih dulu:
|
|
|
|
~~~
|
|
[php]
|
|
// hapus baris yang sesuai dengan kondisi yang ditetapkan
|
|
Post::model()->deleteAll($condition,$params);
|
|
// hapus baris yang sesuai dengan kondisi dan kunci primer yang ditetapkan
|
|
Post::model()->deleteByPk($pk,$condition,$params);
|
|
~~~
|
|
|
|
Validasi Data
|
|
-------------
|
|
|
|
Ketika menyisipkan atau memutakhirkan baris, seringkali kita harus memeriksa apakah nilai
|
|
kolom sesuai dengan aturan tertentu. Ini penting terutama jika nilai kolom
|
|
disediakan oleh pengguna akhir. Secara umum, kita seharusnya tidak pernah
|
|
mempercayai apapun yang berasal dari sisi klien.
|
|
|
|
AR melakukan validasi data secara otomatis ketika
|
|
[save()|CActiveRecord::save] sedang dipanggil. Validasi didasarkan pada
|
|
aturan yang ditetapkan dalam metode [rules()|CModel::rules] pada kelas AR.
|
|
Untuk lebih jelasnya mengenai bagaimana untuk menetapkan aturan validasi, rujuk
|
|
seksi [Mendeklarasikan Aturan Validasi](/doc/guide/form.model#declaring-validation-rules).
|
|
Di bawah ini adalah alur kerja umum yang diperlukan oleh penyimpanan rekaman:
|
|
|
|
~~~
|
|
[php]
|
|
if($post->save())
|
|
{
|
|
// data benar dan disisipkan/dimutakhirkan dengan sukses
|
|
}
|
|
else
|
|
{
|
|
// data tidak benar. panggil getErrors() untuk mengambil pesan kesalahan
|
|
}
|
|
~~~
|
|
|
|
Ketika data untuk penyisipan atau pemutakhiran dikirimkan oleh pengguna akhir dalam
|
|
bentuk HTML, kita perlu menempatkannya ke properti AR terkait. Kita apat melakukannya
|
|
seperti berikut:
|
|
|
|
~~~
|
|
[php]
|
|
$post->title=$_POST['title'];
|
|
$post->content=$_POST['content'];
|
|
$post->save();
|
|
~~~
|
|
|
|
Jika terdapat banyak kolom, kita akan melihat daftar yang panjang dari penempatan tersebut.
|
|
Ini dapat dipersingkat dengan pemakaian properti
|
|
[attributes|CActiveRecord::attributes] seperti ditampilkan di bawah. Rincian
|
|
dapat ditemukan dalam seksi [Mengamankan Penempatan Atribut](/doc/guide/form.model#securing-attribute-assignments)
|
|
dan seksi [Membuat Aksi](/doc/guide/form.action).
|
|
|
|
~~~
|
|
[php]
|
|
// anggap $_POST['Post'] adalah array nilai kolom yang diindeks oleh nama kolom
|
|
$post->attributes=$_POST['Post'];
|
|
$post->save();
|
|
~~~
|
|
|
|
|
|
Membandingkan Rekaman
|
|
---------------------
|
|
|
|
Seperti baris tabel, turunan AR secara unik diidentifikasi dengan nilai kunci
|
|
primer. Oleh karena itu, untuk membandingkan dua turunan AR, kita perlu membandingkan
|
|
nilai kunci primernya, menganggap keduanya milik kelas AR yang sama. cara
|
|
paling sederhana adalah dengan memanggil [CActiveRecord::equals()].
|
|
|
|
> Info: Tidak seperti implementasi AR dalam framework lain, Yii mendukung
|
|
kunci primer composite dalam turunan AR-nya. Kunci primer terdiri dari dua
|
|
atau lebih kolom. Secara bersamaan, nilai kunci primer disajikan sebagai
|
|
array dalam Yii. Properti [primaryKey|CActiveRecord::primaryKey] memberikan
|
|
nilai kunci primer pada turunan AR.
|
|
|
|
Kustomisasi
|
|
-----------
|
|
|
|
[CActiveRecord] menyediakan beberapa metode penampungan yang dapat ditimpa
|
|
dalam anak kelas untuk mengkustomisasi alur kerjanya.
|
|
|
|
- [beforeValidate|CModel::beforeValidate] dan
|
|
[afterValidate|CModel::afterValidate]: ini dipanggil sebelum dan sesudah
|
|
validasi dilakukan.
|
|
|
|
- [beforeSave|CActiveRecord::beforeSave] dan
|
|
[afterSave|CActiveRecord::afterSave]: ini dipanggil sebelum dan sesudah
|
|
penyimpanan turunan AR.
|
|
|
|
- [beforeDelete|CActiveRecord::beforeDelete] dan
|
|
[afterDelete|CActiveRecord::afterDelete]: ini dipanggil sebelum dan sesudah
|
|
turunan AR dihapus.
|
|
|
|
- [afterConstruct|CActiveRecord::afterConstruct]: ini dipanggil untuk
|
|
setiap turunan AR yang dibuat menggunakan operator `new`.
|
|
|
|
- [beforeFind|CActiveRecord::beforeFind]: ini dipanggil sebelum pencari AR
|
|
dipakai untuk melakukan queri (misal `find()`, `findAll()`). Ini sudah tersedia
|
|
sejak versi 1.0.9.
|
|
|
|
- [afterFind|CActiveRecord::afterFind]: ini dipanggil untuk setiap turunan AR
|
|
yang dibuat sebagai hasil dari queri.
|
|
|
|
|
|
Menggunakan Transaksi dengan AR
|
|
-------------------------------
|
|
|
|
Setiap turunan AR berisi properti bernama
|
|
[dbConnection|CActiveRecord::dbConnection] yang merupakan turunan dari [CDbConnection].
|
|
Kita dapat menggunakan fitur
|
|
[transaksi](/doc/guide/database.dao#using-transactions) yang disediakan oleh Yii
|
|
DAO jika diinginkan saat bekerja dengan AR:
|
|
|
|
~~~
|
|
[php]
|
|
$model=Post::model();
|
|
$transaction=$model->dbConnection->beginTransaction();
|
|
try
|
|
{
|
|
// cari dan simpan adalah dua langkah yang bisa diintervensi oleh permintaan lain
|
|
// oleh karenanya kita menggunakan transaksi untuk memastikan konsistensi dan integritas
|
|
$post=$model->findByPk(10);
|
|
$post->title='new post title';
|
|
$post->save();
|
|
$transaction->commit();
|
|
}
|
|
catch(Exception $e)
|
|
{
|
|
$transaction->rollBack();
|
|
}
|
|
~~~
|
|
|
|
|
|
Lingkup Bernama
|
|
---------------
|
|
|
|
> Note|Catatan: Dukungan lingkup bernama sudah tersedia sejak versi 1.0.5.
|
|
> Ide lingkup bernama berasal dari Ruby on Rails.
|
|
|
|
Sebuah *named scope* atau lingkup bernama mewakili kriteria queri *bernama* yang dapat digabung dengan lingkup bernama lain dan diterapkan ke queri rekaman aktif.
|
|
|
|
Lingkup bernama dideklarasikan terutama dalam metode [CActiveRecord::scopes()] sebagai pasangan nama-kriteria. Kode berikut mendeklarasikan tiga lingkup bernama, `published` dan `recently`, dalam kelas model `Post`
|
|
|
|
~~~
|
|
[php]
|
|
class Post extends CActiveRecord
|
|
{
|
|
......
|
|
public function scopes()
|
|
{
|
|
return array(
|
|
'published'=>array(
|
|
'condition'=>'status=1',
|
|
),
|
|
'recently'=>array(
|
|
'order'=>'createTime DESC',
|
|
'limit'=>5,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
~~~
|
|
|
|
Setiap lingkup bernama dideklarasikan sebagai sebuah array yang dipakai untuk menginisialisasi turunan [CDbCriteria]. Sebagai contoh, lingkup bernama `recently` menetapkan bahwa properti `order` adalah `createTime DESC` dan properti `limit` adalah 5 yang diterjemahkan ke dalam sebuah kriteria queri yang harus menghasilkan paling banyak 5 tulisan terbaru.
|
|
|
|
Lingkup bernama dipakai sebagai pembeda pada pemanggilan metode `find`. Beberapa lingkup bernama dapat dikaitkan bersamaan dan menghasilkan set yang lebih terbatas. Sebagai contoh, untuk mencari tulisan terbaru yang diterbitkan, kita menggunakan kode berikut:
|
|
|
|
~~~
|
|
[php]
|
|
$posts=Post::model()->published()->recently()->findAll();
|
|
~~~
|
|
|
|
Secara umum, lingkup bernama harus berada di sebelah kiri pemanggilan metode `find`. Masing-masing menyediakan kriteria queri, yang merupakan gabungan dengan kriteria lain, termasuk yang dioper ke pemanggilan metode `find`. Hal ini mirip dengan menambahkan sebuah daftar filter ke sebuah queri.
|
|
|
|
Mulai dari versi 1.0.6, lingkup bernama juga dapat dipakai dengan metode `update` dan `delete`. Sebagai contoh, kode bberikut akan menghapus semua tulisan yang akhir-akhir ini diterbitkan:
|
|
|
|
~~~
|
|
[php]
|
|
Post::model()->published()->recently()->delete();
|
|
~~~
|
|
|
|
> Note|Catatan: Lingkup bernama hanya bisa dipakai dengan metode tingkat-kelas. Yakni, metode harus dipanggil menggunakan `ClassName::model()`.
|
|
|
|
|
|
### Parameterisasi Lingkup Bernama
|
|
|
|
Named scopes dapat diparameterkan. Sebagai contoh, kita mungkin ingin mengkustomisasi sejumlah tulisan dengan lingkup bernama `recently`. Untuk melakukannya, daripada mendeklarasikan lingkup bernama dalam metode [CActiveRecord::scopes], kita perlu mendefinisikan sebuah metode baru yang namanya sama seperti nama lingkup tadi:
|
|
|
|
~~~
|
|
[php]
|
|
public function recently($limit=5)
|
|
{
|
|
$this->getDbCriteria()->mergeWith(array(
|
|
'order'=>'createTime DESC',
|
|
'limit'=>$limit,
|
|
));
|
|
return $this;
|
|
}
|
|
~~~
|
|
|
|
Selanjutnya, kita bisa menggunakan pernyataan berikut untuk mengambil 3 tulisan terbaru yang diterbitkan:
|
|
|
|
~~~
|
|
[php]
|
|
$posts=Post::model()->published()->recently(3)->findAll();
|
|
~~~
|
|
|
|
Jika kita tidak melengkapi parameter 3 di atas, secara standar kita akan mengambil 5 tulisan terbaru yang diterbitkan.
|
|
|
|
|
|
### Standar Lingkup Bernama
|
|
|
|
Kelas model dapat memiliki standar lingkup bernama yang akan diterapkan untuk semua queri (termasuk yang relasional) berkenaan dengan model. Sebagai contoh, website yang mendukung multi bahasa mungkin hanya ingin menampilkan konten yang ditetapkan oleh pengguna saat ini. Karena di sana ada banyak queri atas konten situs, kita dapat mendefinisikan standar lingkup bernama guna memecahkan masalah ini. Untuk melakukannya, kita menimpa metode [CActiveRecord::defaultScope] seperti berikut,
|
|
|
|
~~~
|
|
[php]
|
|
class Content extends CActiveRecord
|
|
{
|
|
public function defaultScope()
|
|
{
|
|
return array(
|
|
'condition'=>"language='".Yii::app()->language."'",
|
|
);
|
|
}
|
|
}
|
|
~~~
|
|
|
|
Sekarang, jika metode di bawah ini dipanggil, ia akan secara otomatis menggunakan kriteria queri seperti didefinisikan di atas:
|
|
|
|
~~~
|
|
[php]
|
|
$contents=Content::model()->findAll();
|
|
~~~
|
|
|
|
Catatan bahwa standar lingkup bernama hanya berlaku pada queri `SELECT`. Ia diabaikan untuk queri `INSERT`, `UPDATE` dan `DELETE`.
|
|
|
|
<div class="revision">$Id: database.ar.txt 1391 2009-09-04 19:46:04Z qiang.xue $</div> |