[Yii Framework] Membuat CGridView Sort dan Filter dari Model yang Berelasi

Pada Yii Framework, mungkin bukan hal yang sulit untuk membuat sebuah tabel yang menampilkan data dari suatu tabel yang sudah dilengkapi fasilitas “sort” dan “search”. Yah, anda cukup menggunakan fasilitas generate code dari Gii dan itu akan langsung dibuat secara otomatis oleh gii. Bagaimana jika anda ingin membaut sebuah data yang diambil dari lebih dari 1 tabel kemudian menampilkannya dengan fasilitas “sort” dan “search” ??  Untuk kasus ini, kita harus bekerja lebih keras.. kita dapat melakukannya dengan menggunakan cdbcriteria yang sedikit kita manipulasi..  Mari kita bahas…

Misal saya ingin menampilkan data dari tabel “A” dan tabel “B”. Oh iya, perlu anda ketahui tutorial ini menampilkan data untuk tabel yang berelasi. Untuk itu, pastikan pada model tersebut sudah terdapat relasi antara tabel A dan tabel B, sehingga pada model akan ada code seperti berikut :

public function relations()
{
   return array(
       'namaRelasi' => array(self::BELONGS_TO, 'B', 'id_B'),
   );
 }

Setelah itu, definisikan attribute-attribute yang ingin kita ambil dari tabel B pada model A
misal :

public $attribute1,$attribbute2;

Nah, sekarang kita buat sebuah fungsi untuk menampilkan semua data pada tabel A dan tabel B yang sudah disertai fungsi untuk memfilter saat “search” dan mengurutkan saat “sort” :

Buatlah sebuah fungsi seperti berikut :

public function search2()
 {
     $criteria=new CDbCriteria;
     $criteria->select='
       t.id, 
       t.attribute0, 
       namarelasi.attribute1, 
       namarelasi.attribute2';

       $criteria->with=array('namarelasi');
       $criteria->compare('id',$this->id);
       $criteria->compare('attribute0',$this->attribute0,true);
       $criteria->compare('namarelasi.attribute1',$this->attribute1,true);
       $criteria->compare('namarelasi.attribute2',$this->attribute2,true);

       return new CActiveDataProvider(get_class($this), array(
         'criteria'=>$criteria,
         'sort'=>array(
           'attributes'=>array(
              'attribute1'=>array(
                 'asc'=>'namarelasi.attribute1',
                 'desc'=>'namarelasi.attribute1 DESC',
              ),
              'attribute2'=>array(
                 'asc'=>'namarelasi.attribute2',
                 'desc'=>'namarelasi.attribute2 DESC',
              ),
              '*',
          ),
        ),
    ));
 }

Penjelasan : Pada code di atas, pertama-tama kita mendefinisikan nama fungsi. Lalu kita definisikan attribute apa saja yang dapat kita tampilkan. Lalu kita definisikan tabel apa yang kita ambil, tetapi ingat kita mendefinisikan tabel apa yang akan kita ambil bukan dari nama tabel nya.. tetapi dari nama relasinya. Karena itu lah sebelumnya saya sudah mewajibkan untuk mendefinisikan relasi pada pada model yang akan di relasikan..

Setelah mendefinisikan relasi, barulah saya mendefiniskan attribute untuk melakukan filter, lalu definisikan juga attribute-attribute untuk mendefinisikan variabel yang akan di “sort”…

Nah, setelah itu jangan lupa definsikan pada function rules model tersebut seperti berikut :

public function rules()
 {
    return array(
        array('id, attribute0, attribute1, attribute2', 'safe', 'on'=>'search2'),
        );
 }

Rules di atas dimaksudkan agar attribute yang di filter/sort pada CGRidView dapat tertangkap oleh action..

Setelah itu anda dapat menampilkan isi dari tabel anda dengan memanggil fungsi tersebut pada controller anda :

public function actionAdmin()
 {
    $model=new A('search2');
    $model->unsetAttributes(); 
    if(isset($_GET['A']))
       $model->attributes=$_GET['A'];
    $this->render('admin',array(
       'model'=>$model,
     ));
 }

Nah, kemudian pada CGridView jangan lupa arahkan data nya kepada nilai fungsi tsb :

$this->widget('zii.widgets.grid.CGridView', array(
   'id'=>'user-grid',
   'dataProvider'=>$model->search2(),
   'filter'=>$model,
   'columns'=>array(
      'id',
      'attribute0',
      'attribute1',
      'attribute2',
    ),
));

Selesai..
Selamat mencoba..
Semoga membantu.. 🙂

60 Responses to [Yii Framework] Membuat CGridView Sort dan Filter dari Model yang Berelasi

  1. Ardy says:

    Teman2 Yii-ers mohon pencerahannya yach.. kasusnya seperti berikut :
    saya punya 2 tabel
    table pertama adalah Barang
    * kode_barang (PK)
    * status
    * tanggal_masuk

    table kedua adalah Kondisi
    * kode_barang (PK)
    * kondisi_barang (hanya diisi dengan BAGUS dan RUSAK)

    Di tampilan Form ADMIN hanya akan tampil data field2 table pertama saja,
    | kode_barang | status | tanggal_masuk |
    tetapi dengan persyaratan/kondisi
    * kondisi 1 : jika usernya LEVEL 1,data yang tampil adalah semua data barang dengan kondisi_barang (table kedua) BAGUS ataupun RUSAK.
    * kondisi 2 : jika usernya LEVEL 2, data yang tampil adalah data barang dengan kondisi_barang (table kedua) BAGUS
    * kondisi 3 : jika usernya LEVEL 3, data yang tampil adalah data barang dengan kondisi_barang (table kedua) RUSAK

    Mohon teman2 Yii-ers beri masukan utk kasus saya diatas. Terima Kasih.

  2. Ardy says:

    Satu lagi yang kelupaan. Dari kasus tersebut tidak hanya tampil di cGridView saja, tapi tetap ada ‘class’=>’CButtonColumn’, sehingga operasi CRUD (Create Read Update Delete), Search dan Filter bisa dilakukan dari form ADMIN tersebut. Saya sudah mencoba menggunakan CArrayDataProvider, tetapi belum berhasil membuat yang seperti CActiveDataProvider. Mohon bantuan Para Master Yii. Terima Kasih.

  3. @ardy:
    pertama-tama buatlah sebuah query dengan kondisi tersebut, misal:

    if(level==1)

    query = select k.kodebarang, from barang b, kondisi k where b.kodebarang=k.kodebarang;

    else if(level==2)

    query = select k.kodebarang, from barang b, kondisi k where b.kodebarang=k.kodebarang AND k.kondisibarang=”bagus”;

    else if(level==2)

    query = select k.kodebarang, from barang b, kondisi k where b.kodebarang=k.kodebarang AND k.kondisibarang=”rusak”;

    setelah itu tinggal agan masukin ke query..

  4. oh iya, yg di atas pake SQL, kalo mau pake criteria seperti contoh di atas, mending masukin langsung ke controller seperti berikut:

    public function actionAdmin()
    {
    $model=new A(‘search2’);
    $model->unsetAttributes();

    if(level==2)
    $model->kondisibarang=”BAGUS”;
    else if(level==3)
    $model->kondisibarang=”RUSAK”;

    if(isset($_GET[‘A’]))
    $model->attributes=$_GET[‘A’];
    $this->render(‘admin’,array(
    ‘model’=>$model,
    ));
    }

    Msalah membuat tombol update dan delete nya, agan harus definisikan sendiri actionnya seperti berikut:

    2 model 1 form… pada yii framework…

    silahkan dipelajari link tsb gan..

  5. Ardy says:

    Pak.. Oke banget.. Bisa saya mengerti jalurnya nih. Perlahan sudah mulai terbuka otaknya.. Hhahahaahaaa.. Thx u buanyakkkkkk..

  6. boedz says:

    bang sabit saya minta bantuan,,, sya masih newbea bgt yii,, sya mau tanya klo kita bkin suatu kasus,, misal kyk turotial bang sabit yg register,,,,
    nah ko bisa tau harus d edit anu lah ini lah,,nah saya bingung,, gmn sih cara mengetahuinya??,, ketika membuat kasus baru misal post,, nah file apa saja yg harus saya edit,, mhon pnjelasannya,, trimakasih

  7. mksd ny gimana gan? saya belum nangkep mksd pertanyaannya..

  8. boedz says:

    jadi gini gan,,, klo kita mau membuat aplikasi memakai yii itu,,,apa saja yang harus kita edit setelah di generate,,
    misal ada folder view,controller,models,, nah yang saya bingung itu,,, file apa saja yang harus di edit gan,,
    saya blom ngerti konsep MVC,,,
    mnta pencerahan gan

  9. brayen says:

    Permisi mau bertanya pak,
    saya dapat error seperti ini :
    Active record “Score” is trying to select an invalid column “user.nama”. Note, the column must exist in the table or be an expression with alias.

    kira-kira kenapa ya pak ?
    saya sudah mengikuti semua langkah dengan sama persis.

    Terima kasih untuk balasannya.

  10. itu artinya ada nama field/table/relation yang salah maas..
    tapi dari pesan error maas, itu berrarti ada field yang ga ada yang mas definisiin disana..

  11. brayen says:

    Yang terjadi sebagai berikut mas :
    $criteria=new CDbCriteria;
    $criteria->select=’
    t.id_user,
    t.level,
    t.score,
    user.nama
    ‘;
    $criteria->with=array(‘user’);

    ini error, ketika saya ganti jadi begini :
    $criteria=new CDbCriteria;
    $criteria->select=’
    t.id_user,
    t.level,
    t.score
    ‘;
    $criteria->with=array(‘user’, array(‘select’=>’nama AS nama’));

    error hilang, search terhadap table relasi bisa dilakukan, tapi value-nya yang keluar di table kosong.. ada clue mengenai masalah ini mas ?

  12. kosong ga ada data atau gimana mas? relasi yang dibuat udah di pastikan benar atau belum? coba lakukan query join pada database nya langsung data nya ada ga hasilnya?

  13. @boedz : saya bener ga tau kalau ada komentar agan disini. Agan pelajari aja ebook saya dulu gan, pahami konsepnya.. setelah itu kalo ada yang bingung tanya aja langsung..

  14. brayen says:

    Sori, masalahnya sudah ketemu,
    Di bagian view saya tambahkan field value, dan semuanya berjalan normal.. terima kasih mas 😀

    updated view :
    array(
    ‘name’=>’nama’,
    ‘value’=>’$data->user->nama’,
    ),

    • emen says:

      masalah yang sama dengan agan brayen, relasinya sudah benar, tapi pas bagian

      $criteria->select=’
      t.id,
      t.attribute0,
      namarelasi.attribute1,
      namarelasi.attribute2′;

      ketemu error

      Active record “A” is trying to select an invalid column “namarelasi.attribute1”. Note, the column must exist in the table or be an expression with alias.

      mungkin itu salah karena di tabel A g ad kolom “namarelasi.attribute1”, gtw pastinya

      terima kasih agan brayen ma agan sabit 😀

    • arief says:

      masalahnya sama persis gan,itu naro sintaksnya dimana ya?

  15. mas achmad says:

    assalam, mas cara buat form search di yii yang bisa diakses langsung oleh pengunjung gimana mas? sudah sy utak atik kok malah tambah bingung

  16. mas achmad says:

    trus mau hilangkan tombol view,delete,update di CGridview juga gimana caranya mas, maklum masih newbi. trima kasih

  17. coba search aja di blog ini tentang user level access.. agan pelajari dulu gimana cara ngasih hak akses untuk jenis2 user..

  18. emen says:

    misalnya di tabel B ad field tgl_lahir, terus pada CGridView model A ingin ditampilkan umur yang didapat dari perhitungan tgl_lahir model B, itu gimana y gan???

  19. ada gan query untuk ngdapetin umur berdasarkan tgl lahir.. coba di googling aja gan..

  20. adi says:

    mau tnya nih,kondisinya saya punya 2 tabel
    tabel profil dengan atribut nama,alamat
    tabel barang dengan atribut barang beli, barang jual
    nah kasusnya relasi one to many jadi misal nama adi alamat jakarta tapi barang beli:kopi,teh,gula barang jual:ikan,daging (1 profil punya banyak barang)
    saya maunya di halaman admin cuma ada atribut nama, alamat biar ga ada redudansi baru pas di klik view kluar lg hlaman baru isinya atribut barang jual,barang beli punyanya profil yang di view tadi misal td search nama:adi,trus ketemutrus di klik view(gmbar kca pmbsar sblah knan hsil crud gii) bru kluar tabel crud gii lg yg isinya barang beli, barang jual punyanya profil dengan nama adi
    mohon pencerahannya ya

  21. kalo dari kasus itu ga perlu pake yg dari tutor saya gan. Kan di cgridview nya cuma nampilin identitas user aja. Setelah identitas user itu di klik, tinggal di panggil aja semua barang yang dia miliki select barang where id_orang=$idorangnya.

  22. adi says:

    sintaks select barang where id_orang=$idorangnya tulisnya dimana?

  23. adi says:

    punya link tutorial yg mirip sama kasus ini ga gan?
    thanks ya sblumnya

  24. coba cari aja di blog ini ada tutor utk 2 model 1 view.. itu kurang lebih kayak kasus ini..

  25. Bani says:

    Bang, mau tanya dong, saya koding di model, seperti ini:
    ================================================
    public function getLate($tgl=”){
    $sql = “select a.id,a.nip,a.tanggal,a.jam_masuk,a.jam_pulang,a.idshift,a.mesin_id ” .
    “,c.nama,TIME_TO_SEC(TIMEDIFF(a.jam_masuk, b.jam_masuk)) as telat from absensi a LEFT JOIN karyawan c ON a.nip=c.nip ” .
    ” inner join shift b on a.idshift=b.id “;

    if(!empty($tgl))
    $sql = $sql .” WHERE TIME_TO_SEC(TIMEDIFF(a.jam_masuk, b.jam_masuk)) > 0 AND DATE(a.tanggal)=’$tgl'”;
    else
    $sql = $sql .” WHERE TIME_TO_SEC(TIMEDIFF(a.jam_masuk, b.jam_masuk)) > 0 AND DATE(a.tanggal)=DATE(NOW())”;

    $rawData=Yii::app()->db->createCommand($sql)->queryAll();
    $dataProvider=new CArrayDataProvider($rawData, array(
    ‘id’=>’telat’,
    ‘sort’=>array(
    ‘attributes’=>array(
    ‘id’, ‘nip’, ‘tanggal’,’jam_masuk’,’jam_pulang’,’idshift’,’mesin_id’,’nama’,
    ),
    ),
    ‘pagination’=>array(
    ‘pageSize’=>20,
    ),
    ));

    return $dataProvider;

    }

    ===============================================
    Nah, ceritanya saya mau nanti datanya ituh bisa di advance search bang, gimana yah bang?? saya bikin file search baru di view, namanya _search4.php, nah ketika saya klik tombol search, dia g mau flter data di gridviewnya bang..

    Mohon pencerahannya bang..
    Trimss bang..
    ^^

  26. kalo mau bisa dari fungsi itu di search, di fungsi nya di kasih aja parameter getLate($param1, param2, param3) dimana nanti parameter nya tinggal di sisipin di WHERE query nya..

  27. dave says:

    mau tanya mas masalah saya sama kyk brayen,jd yg searchnya bisa tapi value yg keluar di tabel kosong, itu solusinya gmana ya biar tampil?saya kurang paham yg solusi dari brayen di atas,terima kasih mas

  28. coba yg ini :

    $criteria->select=’a
    t.id,
    t.attribute0,
    namarelasi.attribute1,
    namarelasi.attribute2′;

    hapus aja dari code ny mas.

  29. dave says:

    g bisa mas,
    malah error pas nge search
    ada solusi lain g mas untuk kasus yg kaya bryan?

  30. dave says:

    tambahan prtanyaan mas, jd selain yg atribut yg valuenya ga tampil tp bsa di search itu, atribut yg jd pembanding antara tabel a dan tabel b malah tampil valuenya tapi ga bsa di search, tolong solusinya

  31. error nya apa gan?

  32. dave says:

    itu udah tampil valuenya semua tapi yg jd pembanding antar tabel,misal tabel a id_siswa dicocokin sama id_siswa di tabel b, nah yg id_siswa itu di halaman admin.php jd ga bisa di search,klo atribut yg lainnya bisa,knapa ya mas?erornya muncul window baru namanya localhost says: didalemnya pesan erornya byk

  33. dave says:

    sory mas mslah yg di atas udah beres,tp ada msalah baru,jd klo misalnya pas di cocokin id_siswa antara 2 tabel itu klo ada cocok ga msalah,tp klo ga ada misal di tabel a ada id_siswa 101 tapi di tabel b ga ada,pas di halaman admin.php muncul pesan eror ‘Trying to get property of non-object’ itu solusinya gmana ya mas biar msalnya kondisi kyk gtu ga eror tp nampilin atributnya kosong aja/not set

  34. itu di database nya harus dibuat dulu relasi nya mas. kalo udah ada, ntar dia di model juga di definisiin relasinya.. dengan gitu dia otomatis hanya akan nampilin yang cocok aja mas..

  35. dave says:

    misalnya gmana mas buat relasinya di database sama di modelnya?

  36. di kasih primary key dan foreign key gan. Kalo di model, bisa coba liat di function relations. Agan harus pelajari itu dulu gan klo mau lancar buat cgridview relasi.. soalnya disana intinya dia kerja gan..

  37. dave says:

    itu saya pkenya relasi di model belong to karena tabel a ke tabel b relasinya banyak ke satu,klo saya kasih forign key di table a ga eror tp data yang id_siswanya ga ada di id_siswa table b ga tampil di admin.php,klo ga ada foreign key masalahnya jd kyk yg di atas,gmana ya solusinya biar tetep tampil tp atributnya kosong aja gtu,apa masalah di admin.phpnya?

  38. dave says:

    mas ini udah saya coba datanya masuk,cuma masalah tampilanya aja yd di admin.php,saya kan manggil atribut yg di tabel lain pake yang array(‘name’=’nama’, ‘value’=’$data->namarelasi->nama’) nah masalahnya klo value dari nama kosong dia eror,mau saya klo kosong tampilin aja atribut namanya kosong,gmana ya mas? terima kasih mas

  39. juju says:

    mas Sabit Huraira saya mau tanya gimana caranya membuat rule agar data yang ditampilkan cgridview sesuai data user yang login contohnya misalnya kita ingin tampilkan user 1 berasal dari jakarta maka data jakarta aja yang tampil.
    trus tolong buat contohnya ya mas. biar lebih mudah dipelajari.

  40. gery says:

    mas, saya udah coba tutorial di atas, problemnya data yang tampil hanya 3 row. Padahal saya sudah setting pagesizenya 10 di model. mohon bantuannya.

  41. mas bisa bantu saya tentang masalah query relasi tp dengan join, please mas sabit…
    http://stackoverflow.com/questions/19421586/how-to-convert-my-query-to-cdbcriteria-with-and-condition, query agak aneh emg..

    • uda saya jawab mas.

      • dibyo says:

        Mas, sabit enaknya pake csqldataprovider apa CDbCriteria?? karena query saya ini to mas agak aneh. jadi saya tidak ingin membawa where setelah join. pengen bawa “and” saja setelah di join.
        1.Jika menggunakan csqldataprovider, saya bingung filter dan sortnya.
        2.jika menggunakan CDbCriteria, bisa filter bisa sort, tp convert ke CDbCriteria-nya yg agak menyusahkan ternyata.. tp kalo pengalaman mas Sabit. lbh oke pakai yg mana?? mksh mas

  42. untuk query yang kompleks lebih baik gunakan csqldataprov, kalo yang sederhana pake yang biasa. Cdbdriteria mungkin karena agan belum terbiasa aja menggunakannya..

  43. apri says:

    mas sabit maaf tanya, saya br belajar yii untuk membuat aplikasi pencatatan poin(untuk skripsi) gini mas, kalo mau buat query untuk menampilkan data poin yang lebih dari 30 gmana mas?saya jg binggung letak file nya dimana yang mau dibuat apa dikontroler saja?atau di model dan view juga mas?nuhun mas
    mohon bantuannya ya mas,,

  44. Alan says:

    Maaf mas sabit, saya mau tanya, saya punya table
    Karyawan
    -id_karyawan
    -kode_divisi

    gaji
    -id_gaji
    -id_karyawan
    -gaji

    komudian saya pengen tampilan view/gaji/admin (cgridview) di gaji itu sesuai dengan kode_divisi. caranya bagaimana?

  45. ari21putra says:

    gan,mohon koreksinya yaa,, punya saya error “Active record “Anggota” is trying to select an invalid column “kabupaten.kabupaten”. Note, the column must exist in the table or be an expression with alias.”

    code nya disini gan
    http://pastebin.com/AcyK68mf

  46. Mega Kusuma says:

    Mas tannya, ini kan saya punya tabel pembayaran yang isinya ada kolom id_penempatan ngambil dari tabel penempatan. Nah di tabel penempatan ini ada nim.
    Saya nyoba buat nampilin nim biar bisa di search juga di pembayaran/admin. Script diatas sudah saya coba tapi error “Active record “Pembayaran” is trying to select an invalid column “idPenempatan.nim”. Note, the column must exist in the table or be an expression with alias. ” ini kenapa ya mas?

  47. Rizaldi Maulidia says:

    Mantap gan…
    sabitlabcode menjawab semua masalah-masalah saya di Yii Framework..
    Nice gan.. lanjut terus gan buat tutorialnya 😀

  48. kalau mau sorting nama secara abjad gimana ya
    koding nya yg ini..

    public function actionSelectprodi()
    {
    $criteria = new CDbCriteria(array(‘order’=>’row_id asc’));

    $id_kota3 = $_POST[‘Tbsiswa’][‘id_kota’];
    $list = Tbsekolah::model()->findAll(‘kode_kota = :id_kota’, array(‘:id_kota’=>$id_kota3),($criteria));

    $list = CHtml::listData($list,’kode_sekolah’,’nama’=> SORT_ASC);

    echo CHtml::tag(‘option’,array(‘value’=>”),’– Pilih sekolah –‘, true);

    foreach($list as $value=>$asal_sekolah){
    echo CHtml::tag(‘option’,array(‘value’=>$value),CHtml::encode($asal_sekolah), true);
    }
    }

  49. anindya says:

    gan cara untuk tetap nampilin nama barang walaupun stocknya uda 0 gimana ya???

  50. roizoneee says:

    mas kalo error kayak gini apa ya mas?

    ” include(nama.php): failed to open stream: No such file or directory “

Leave a comment