[Yii Framework] Mengatasi Masalah Composite Primary Key

Menjawab sebuah pertanyaan di blog ini mengenai masalah pembangunan sebuah aplikasi yang memiliki composite primary key. Ada apa dengan composite key pada Yii? Generate code yang ada pada Yii tidak memungkinkan untuk menggenarate code yang tabel nya memiliki composite key. Lalu bagaimana cara mengatasinya? Ada 2 cara:

1. Anda rubah tabel anda hanya memiliki 1 buah Primary key dg field baru dan menjadikan 2 field composite sebelumnya menjadi Unique.

2. Anda tidak merubah tabel anda, tetapi membuat code CRUD pada Yii secara manual (tentunya anda harus memodifikasi bagian-bagian code anda)

Jika menggunakan opsi pertama, anda dapat menggenerate code nya seperti biasa dengan menggunakan Gii. Lalu bagaimana dengan opsi kedua? ya.. mari kita bahas..

Untuk menggenerate model pada Yii, anda tetap dapat mengenerate code anda. Tetapi untuk controller dan view, kita harus membuatnya manual. Tetapi kita akan mengikuti pola code hasil generate yii pada tabel yang tanpa composite key. Okeh, kita bahas dahulu untuk controller. Buatlah sebuah controller sesuai nama model anda pada folder Controllers pada aplikasi anda. Buat sama persis dengan code controller pada code controller lain hasil generate gii.. Lalu lihat pada fungsi loadModel yang tadinya seperti ini:

public function loadModel($id)
 {
   $model=NamaModel::model()->findByPk((int)$id);
   if($model===null)
     throw new CHttpException(404,'The requested page does not exist.');
   return $model;
 }

rubah menjadi seperti ini:

public function loadModel($id,$id2)
 {
    $model=NamaModel::model()->findByAttributes(array('namaAttribute1'=>$id,'namaAttribute2'=>$id2));
    if($model===null)
        throw new CHttpException(404,'The requested page does not exist.');
    return $model;
 }

Penjelasan : karena kita memiliki composite key yang artinya terdapat 2 buah field atau lebih sebagai identitas unik suatu data, maka kita membuat parameternya juga sesuai dengan field tersebut. Saya asumsikan composite key kita terdiri dari 2 field, untuk itu kita membutuhkan 2 buah parameter pada code tersebut untuk itu kita menggunakan findByAttributes bukan findByPk lagi..

Lalu karena itu, tentu untuk action view, update, dan delete kita harus membuat 2 buah parameter untuk itu. Juga untuk setiap link yang mengarahkan kita ke tabel yang memiliki composite, kita harus sediakan 2 buah parameter disana. Silahkan rubah code actionView anda yang tadinya seperti berikut :

public function actionView($id)
 {
   $this->render('view',array(
     'model'=>$this->loadModel($id),
    ));
 }

menjadi seperti berikut :

public function actionView($id,$id2)
 {
   $this->render('view',array(
     'model'=>$this->loadModel($id,$id2),
    ));
 }

Code actionUpdate yang tadinya seperti ini :

public function actionUpdate($id)
 {
    $model=$this->loadModel($id);
    if(isset($_POST['NamaModel']))
    {
       $model->attributes=$_POST['NamaModel'];
       if($model->save())
          $this->redirect(array('view','id'=>$model->id));
    }
    $this->render('update',array(
       'model'=>$model,
    ));
 }

Menjadi seperti berikut :

public function actionUpdate($id,$id2)
 {
    $model=$this->loadModel($id,$id2);
    if(isset($_POST['NamaModel']))
    {
       $model->attributes=$_POST['NamaModel'];
       if($model->save())
          $this->redirect(array('view','id'=>$model->id,'id2'=>$model->id2));
    }
    $this->render('update',array(
       'model'=>$model,
    ));
 }

Dan actionDelete yang tadinya seperti berikut:

public function actionDelete($id)
 {
    if(Yii::app()->request->isPostRequest)
    {
       $this->loadModel($id)->delete();
       if(!isset($_GET['ajax']))
          $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
    }
    else
       throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
 }

menjadi seperti berikut :

public function actionDelete($id,$id2)
 {
    if(Yii::app()->request->isPostRequest)
    {
       $this->loadModel($id,$id2)->delete();
       if(!isset($_GET['ajax']))
          $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
    }
    else
       throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
 }

Selesai, setelah itu kita tinggal mengedit bagian view kita. Berikut contoh untuk mengarahkan pada halaman update dan view..

echo CHtml::link("Update",array('namaController/update','id1'=>$id1,'id2'=>$id2));
echo CHtml::link("View",array('namaController/view','id1'=>$id1,'id2'=>$id2));

Begitu juga dengan menu-menu yang ada pada tampilan anda.. semuanya harus anda modifikasi sesuai dengan action anda..

Selesai.. Selamat mencoba..

Semoga membantu..🙂

48 Responses to [Yii Framework] Mengatasi Masalah Composite Primary Key

  1. Kok di halaman admin masih ada yang error..saya bingung ni gan..salahnya dimana??

  2. dbormamora says:

    Bit, mau nanya dong.. Kalo hasilnya error 400, your request is invalid tuh apa yg kurang ya?
    codingan gw kek gini :
    model >>
    public function primaryKey()
    {
    return array(‘kode_kabkot’, ‘kode_prov’);
    }

    view >>
    array(‘class’=>’CButtonColumn’,’viewButtonUrl’=>’Yii::app()->controller->createUrl(“view”,$data->primaryKey)’,
    ‘updateButtonUrl’=>’Yii::app()->controller->createUrl(“update”,$data->primaryKey)’,
    ‘deleteButtonUrl’=>’Yii::app()->controller->createUrl(“delete”,$data->primaryKey)’,)

    thanks before

  3. kalo itu action pake actionPrimaryKey coba bor..

  4. itu nama fungsi mu ga ada “action” nya bor..

  5. oh.. ku kirain action.. biasanya kalo error yg gitu berrti ga ada action yang namanya sesuai dengan yang di request bor..

    btw, panggil “primaryKey” nya di view pake “()” bor di belakangnya..

  6. coba ganti :
    ’Yii::app()->controller->createUrl(“view”,$data->primaryKey)

    jadi :

    ’Yii::app()->controller->createUrl(“view”,array($data->primaryKey))

  7. hmmm.. kyak nya emang ga bisa bor definisiin URL kayak gitu..
    make cara biasa aja bor definisiinya berrti..
    ga usah pake fungsi yang PrimaryKey nya..

  8. dbormamora says:

    tapi tetep ngerror Bit,, udah gw comment tuh primaryKey() dan CButtonColumn nya dah gw bikin biasa.. gw bingung salah dmnnya..

  9. kalo kau pake createUrl kayak gitu cara definisiinnya harusnya gini bor :
    Yii::app()->controller->createUrl(“view”,array(‘kode_prov’=>1,’,’kode_kab’=>2))’

    gitu bor..

  10. dbormamora says:

    oouh,, ga dinamis ya.. trus gw musti ganti kyk mana, Bit?

  11. ya ntar dibuat dinamis bor.. kan bisa di tangkep variabel kode_prop dan kode_kab nya dari cgridview..
    coba di cari aja bor cara nangkep nya..

  12. dbormamora says:

    okey, Bit.. thanks

  13. ayahehasna says:

    wah kayaknya case-nya dbormamora sama kayak punyaku
    aku juga lagi ngolah data yang berhubungan dengan data lokasi kdprop, kdkab, kdkec, kddesa. masalah muncul karena data yang tak olah gak ada PK. gak ada no_id-nya, sehingga harus akal-akalan

    bang sabit. itu artinya kalo composite key-nya dari n field, maka perulangannya juga n ya? kalo dicontoh kan cuman 2. ato gmn ya enaknya…

    strukturku kurang lebih kek gini nih tabelnya

    kdprop
    kdkab
    kdkec
    kddesa
    namakk
    alamat
    flag

  14. saran saya kalo udah sebanyak itu lebih baik dibuat PK nya aja gan.. tapi kalo emang nggak ya mau nggak mau di buat n-field yang mbak bilang itu…

  15. Chucky Blood says:

    gan klo di view nya gmn ??

  16. itu udah saya contohin di atas gan..

  17. sari says:

    kak, kalo tabel yang dipake tu ‘tabel view’ hasil denormalisasi dari banyak tabel gimana kak? masalahnya kalo tabel view itu ga ada primary key nya, gimana generate controllernya??
    makasi kak🙂

  18. itu emang ga bisa di generate mbak.. harus di buat sendiri jadi nya mbak..

  19. kiki says:

    Kak, di halaman admin, pas mw klik icon (misalnya icon view), yg muncul “Error 400 Your request is invalid”. Knp yah kak?

  20. itu harus mbak modifikasi lagi mbak button search halaman adminnya.. di set lagi URL nya..

    • kiki says:

      klu button search nya ga masalah kak,, maksudku yg ga bs tuh icon view, update, n delete yg di dalam Cgridview nya..

      mohon pencerahannya kak😀

  21. sory saya salah ketik mbak.. iya maksud nya button view, update, dan delete nya mbak.. itu harus di setting manual url link nya mbak..
    coba liat contoh ini : http://www.yiiframework.com/wiki/106/using-cbuttoncolumn-to-customize-buttons-in-cgridview/

  22. sama aja mbak, emang kenapa mbak?

    • kiki says:

      code nya gini:
      ‘delete’ => array(
      ‘deleteConfirmation’=>”js:’Record with ID ‘+$(this).parent().parent().children(‘:first-child’).text()+’ will be deleted! Continue?'”,
      ),

      tapi masih tetep error 400.

  23. kiki says:

    udah bisa kak, makasih ya😀

  24. acip says:

    mas mau tanya kalo misal saya mau buat pas create kalo kita isi sama primary key yg udah ada kan muncul pesan CDbCommand failed to execute the SQL statement: bla bla, kalo saya mau ganti pesan itu misalnya dengan tulisan ” Maaf data sudah ada”, ga harus bentuk message box, tulisannya di halaman web biasa gitu aja,itu gimana ya mas? terima kasih

  25. itu bisa dibuat validasi sendiri aja gan lewat model nya..
    coba cari aja di blog ini ada tutor untuk buat validasi yang kita custom sendiri..

  26. sangprabo says:

    Kayaknya lebih enak nggak usah pake composite key deh Gan.. Cmiiw

  27. selagi bisa ga pake ga perlu gan.. tapi ini hanya cntoh kalo emang composite di perlukan..

  28. Om sabit :
    kan klo cara itu urlnya jadi..
    /controller/action/id?id2
    nah gimana biar urlnya dipercantik menjadi
    /controller/action/id/id2 ??
    mohon pencerahannya

  29. di dokumentasi yii ada bahasan tentang Url management.. coba baca disana aja gan.. udah lumayan lengkap kok..

  30. udah baca om..
    belum nangkep intinya..
    ntar tak baca lagi deh..
    btw thanx om..

  31. kalo many to many itu tidak ada aturan untuk pake composite gan.. yang jelas kalo many to many harus pake junction tabel.. coba di baca lagi aja gan konsep database many to many.. kalo udah bisa itu lebih enak nanti gan..

  32. kak sabit, yang ini dimasukkin di bagian view yang mana yaaak?? masih bingung aku

    echo CHtml::link(“Update”,array(‘namaController/update’,’id1’=>$id1,’id2’=>$id2));
    echo CHtml::link(“View”,array(‘namaController/view’,’id1’=>$id1,’id2’=>$id2));

  33. Malam Kak sabit disini saya mau tanya yang source code yang ini diletakin dimana ya?

    Nama File dan Foldernya apa? apakah di folder frotected?

    echo CHtml::link(“Update”,array(‘namaController/update’,’id1’=>$id1,’id2’=>$id2));
    echo CHtml::link(“View”,array(‘namaController/view’,’id1’=>$id1,’id2’=>$id2));

    Mohon pencerahannya.

    Terima kasih

  34. Hendi says:

    mohon bantuannya gan mau tanya kalo misal saya mau buat pas create kalo kita isi sama primary key yg udah ada kan muncul pesan CDbCommand failed to execute the SQL statement: bla bla, kalo saya mau ganti pesan itu misalnya dengan tulisan ” Maaf data sudah ada”, ga harus bentuk message box, tulisannya di halaman web biasa gitu aja,itu gimana ya mas? terima kasih

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: