[Silex Framework] Make REST Web Service (1)

Okey, setelah kurang lebih 5 bulan nggak posting di blog ini, akhirnya dikasih waktu dan kesempatan kembali untuk membuat catatan disini. Kali ini saya akan menjabarkan cara membuat REST Web Service dengan menggunakan Silex Framework, kalo ada yang belum tahu tentang silex framework bisa dilihat di http://silex.sensiolabs.org/. Bisa dilihat pada webnya silex adalah “The PHP micro framework based on Symfony2 Components”, jadi komponen yang digunakan oleh Silex adalah dari Symfony2 yang dari kematangan sudah teruji dalam development aplikasi website. Terus kalo ga ngerti Symfony2 gimana? buat yang ga familiar dengan symfony2 tetap bisa pake kok (saya juga ga familiar dgn Symfony2).

Kenapa pake Silex? kenapa ga pake framework lain macam Yii, Laravel atau Symfony2 sekalian?. Saya ingin membuat sebuah sistem terpisah yang bertugas cuma untuk menangani web service saya. Jika menggunakan framework seperti Yii, Laravel atau symfony2 saya rasa terlalu kompleks dan ditakutkan mempengaruhi performance dari web service yang saya bangun. Pada tutorial selanjutnya mungkin saya akan posting cara mengkonsumsi web service yang kita buat dengan Android atau Xamarin.

Laravel juga punya micro framework yang namanya Lumen, kenapa ga pake itu? Hmm, keputusan pribadi sih. Setelah googling sana-sini, walau banyak perbedaan pendapat antar developer mana yang lebih baik, saya menetapkan dan lebih tertarik explore si Silex.

Pada tutorial ini saya ingin membuat sebuah API Web Service yang dapat mengeluarkan dan mengelola data daftar makanan+harganya. Pertama-tama mari buat sebuah database dan buatlah sebuah tabel berikut :

CREATE TABLE `menu_makanan` (
 `id` INT NOT NULL AUTO_INCREMENT ,
 `nama` VARCHAR(255) NULL ,
 `harga` DECIMAL(12,0) NULL ,
 PRIMARY KEY (`id`) );

Setelah itu inputlah beberapa contoh data, misal seperti gambar berikut :

Capture

Setelah selesai dengan database, sekarang donlot Silex Framework di http://silex.sensiolabs.org/download. Yang di download lebih baik yang “slim”. Ektrak file tersebut dan masukkan ke dalam web server anda (folder letak localhost anda). Rubah nama folder “silex” anda dengan nama project yang anda inginkan (saya memberi nama project dengan “tutor_silex”). Jangan lupa install composer, download di https://getcomposer.org/. Ini dapat digunakan untuk memudahkan anda mengupdate komponen2 pada aplikasi anda secara online melalui command composer.

Buka aplikasi hello world anda pada tautan berikut : http://localhost/tutor_silex/web/index.php/hello. Akan terlihat tampilan browser dengan tulisan “Hello!”.

Sekarang pada project anda silahkan buka file pada “web/index.php”. Berikut penjelasan kode pada file tersebut :

<?php
//kode ini mendefinisikan file pada vendor/autoload.php, 
//file ini adalah sumber induk untuk mengkonsumsi components pada silex/symfony2 component.
require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

//router "hello", mendefinisikan sebuah router yang dapat dipanggil browser
//pada contoh sebelumnya kita telah memanggil tautan yang menampilkan tulisan "Hello!"
//disinilah kode yang mengeksekusi hal tersebut.
$app->get('/hello', function () {
 return 'Hello!';
});

$app->run();

Kita akan menghubungkan aplikasi kita dengan database yang telah kita buat. Untuk mengubungkan aplikasi dengan database kita akan menggunakan doctrine dalam hal ini kita harus melakukan setting pada file “composer.json” yang ada pada aplikasi dan masukkan kode berikut :

{
  "require": {
     "silex/silex": "~1.1",
     "doctrine/dbal":"~2.2",
     "phpunit/phpunit": "4.5.*"
  }
}

Pada code di atas kita mendefinisikan doctrine dan phpunit agar dapat menghubungkan aplikasi dengan database. Doctrine dan phpunit saat ini belum ada pada aplikasi anda, untuk itu kita harus mengupdate komponen anda dengan menggunakan composer. Buka command prompt anda, cd (change direktori) ke direktori project anda. Kemudian update komponen anda dengan mengetikkan perintah “composer update” pada cmd anda. Tunggu hingga proses selesai.

Setelah selesai masukkan kode berikut pada web/index.php anda :

<?php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

//mendefinisikan koneksi ke database
$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
   'db.options' => array(
      'driver' => 'pdo_mysql',
      'host' => 'localhost',
      'dbname' => 'test',
      'user' => 'root',
      'password' => '',
    ),
));

$app->get('/hello', function () {
 return 'Hello!';
});

//route untuk menampilkan daftar semua makanan pada database
$app->get('/daftar', function (Silex\Application $app,Request $request)
{
   $result=array();
   //query database
   $sql = "SELECT * FROM menu_makanan";
   $stmt=$app['db']->query($sql);
   while($row=$stmt->fetch()){
       //format data yang akan ditampilkan
       $result[]=array(
          'id' =>$row['id'],
          'nama' =>$row['nama'],
          'harga' =>$row['harga'],
       );
    }
 
    return $app->json($result);
});

//route untuk menampilkan data makanan dengan id tertentu pada database
$app->get('/daftar/{id}', function (Silex\Application $app,Request $request,$id)
{
   $result=array();
   $sql = "SELECT * FROM menu_makanan WHERE id={$id}";

   $stmt=$app['db']->query($sql);
   while($row=$stmt->fetch()){
       $result[]=array(
           'id' =>$row['id'],
           'nama' =>$row['nama'],
           'harga' =>$row['harga'],
        );
    }
 
    return $app->json($result);
});

$app->run();

Buka browser anda, kemudian buka tautan “http://localhost/tutor_silex/web/index.php/daftar&#8221;, akan tampil data dalam format json seperti berikut :

[{"id":"1","nama":"Pempek Kapal Selam","harga":"10000"},
{"id":"2","nama":"Gado-gado","harga":"10000"},
{"id":"3","nama":"Nasi Uduk","harga":"7000"}]

Kemudian buka tautan “http://localhost/tutor_silex/web/index.php/daftar/2&#8221; (kita memberikan id spesifik dari data yang ingin ditampilkan) akan muncul data dengan format seperti berikut :

[{"id":"2","nama":"Gado-gado","harga":"10000"}]

Anda dapat mengkonsumsi API tersebut. Bisa menggunakan berbagai jenis platfom seperti android, PHP, Iphone, Windows Phone, dll..

Terus kalo mau buat operasi insert/update data sama delete, gimana caranya pake REST Web Service? Hmm, berhubung lagi capek ngetik, maka postingan untuk insert/update dan delete akan saya lanjutkan pada postingan selanjutnya.. terima kasih..

Happy coding 😀

[Yii Framework] Integrate Upload Image With Editor CKEditor

How to integrate upload image that can automatic include it in your editor with CKEditor and Yii Framework?
1. Download ckeditor source here : http://ckeditor.com/

2. Integrate it with Yii Framework, i assume you know how to do it. (read ckeditor documentation)

3. In views, define html tags for ckeditor like this :

 
                echo '<textarea name="name_field" id="name_field"></textarea>';

4. Define ckeditor javascript to make html tags show data like this :

             CKEDITOR.replace('name_field', {
                height: 100,
                width : 350,
                // this code use for activate image upload in your view, and it will execute the url that you want
                // when run it
                filebrowserImageUploadUrl: '<?php echo Yii::app()->createUrl("yourController/yourAction")?>',

                // set toolbar that you want to show
                toolbar : [
                    {'name' : 'document' , 'items' : ['Source']},
                    ['Cut','Copy','Paste','-','Undo','Redo','Image'],
                    {'name' : 'basicstyles','items' : ['Bold','Italic']}
                ]
            } );

after add that code,your tags will display like this :
1

5. Make an action that will execute upload code in your controller :

 
    public function actionUpfile()
    {
        if($_FILES) // check if file upload exist
        {
            $target_path = Yii::app()->basePath.'/../foldername/';  // directory in your server
            $ext_name=explode('.',basename($_FILES['upload']['name']));  // get extension from file upload
            $fname='yourFileName.'.$ext_name[1];  // set your file name, 
            $target_path = $target_path.$fname;  // save path and name file

            if(!file_exists("$target_path"))// if we have set target path
            {
                  $message='';  // message variable, use to show message after upload file
                  $url='';   // url variable, use to set url image in your editor
                  $lower_ext=strtolower($ext_name[1]);  // check extension, validate type file
                  if ($lower_ext!='jpg' && $lower_ext!='jpeg' && $lower_ext!='png' && $lower_ext!='gif')
                  {
                    // if type file not allow
                    $message = "The image must be in either JPG, JPEG, GIF or PNG format."; 
                  }
                else
                {
                    // upload file to server
                    move_uploaded_file($_FILES['upload']['tmp_name'], $target_path);
                    echo 'Success Upload File';
                    // url will save directory. Note it, url is different with target path
                    // url will use in your editor, it will direct access to the path
                    $url='yourwebsite'.'/foldername/'.$fname;
                }
                $funcNum = $_GET['CKEditorFuncNum'] ;
                // after save data, run code to call ckeditor function
                echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$url', '$message');</script>";
              }
              else
              {
                  echo 'Failed Upload File';    
              }
        }
    }

After that, you will see display like this :
2

Yeah, enjoy your application..

Finish.. Hope it help,Happy coding… 😀

[Yii Framework] Update Data Table/ Grid Form With JQrelCopy

Many people ask about “how to update many data in table form?”. I have posted about how to create (not update ) it here https://sabitlabscode.wordpress.com/2012/06/14/yii-framework-ajax-dependent-dropdownlist-in-multi-value-grid-form/ , here https://sabitlabscode.wordpress.com/2012/05/28/yii-framework-insert-banyak-data-dengan-jappendo/ and here https://sabitlabscode.wordpress.com/2011/08/10/yii-framework-membuat-entry-data-tabel-dinamis-dengan-jappendo/. But some

Okeh, first our form will be like this :

t1

And form update will be like this :

t2

Okey, you can see it in update form it will have the previous value that we have been added before. We can delete previous data too with click in “delete” link in form.

I assume you have been knowed to make create form (see my previous post). Now, we will learn how to make an update form. First, download jqrelcopy extension and insert it in your application (In this post i just post with jqrelcopy extension). Next, we need to display previous data when we want to update. So. insert this code on your form in view :

 <div>

<?php 
// define form
$form=$this->beginWidget('CActiveForm', array(
    'id'=>'name-form',
    'enableAjaxValidation'=>false,
)); ?>

<?php 
     // define jqrelcopy
    $this->widget('ext.jqrelcopy.JQRelcopy',array(
        'id' => 'copylink',
        'removeText' => 'Delete', // delete label
        'removeHtmlOptions' => array('style'=>'color:red'),  // style for delete link
        'options' => array(
            'copyClass'=>'newcopy',
            'clearInputs'=>true,
            'excludeSelector'=>'.skipcopy',  // add some class not to copy when we add 
        )
    ));
?>
        <a id="copylink" href="#" rel=".yangdicopy">Add New</a>

        <table>
            <tr>
                <th>Some Text Here</th>
            </tr>

            <?php 
            if(!$model->isNewRecord){
                //if it in update mode, display all value from previous save
                use findAll (or another metode) to show all data before
                foreach (YourModel::model()->findAllByAttributes(array('field1'=>yourParam)) as $key => $value) { 
           ?>
                    <tr>
                        <?php
                           // show all value
                            echo '<td>'.Chtml::textArea('ques3[]',$value->attribute1,array('rows'=>2, 'cols'=>40)).'</td>';
                            // this code use for delete value, it will execution controller and action that set in ajax call
                            echo "<td class='skipcopy'><a href='#' onclick=\"
                                    $.ajax({
                                            url:'".Yii::app()->createUrl('yourController/yourAction')."',
                                            data: {id:$(this).attr('id')}
                                    });
                                    $(this).parent().parent().remove(); return false;
                                \" 
                                style=\"color:red;\" id='produ".$value->idAttribute."' >Delete</a></td>"; 
                                // produ."$value->idAttribute" use to make unique tag in each jqrel table
                        ?>
                    </tr>   
            <?php }} ?>

            <tr>
                <?php
                    // this is standar form will show to add data
                    echo '<td>'.Chtml::textArea('ques3[]','',array('rows'=>2, 'cols'=>40)).'</td>';
                    echo "<td class='skipcopy'><a href='#' onclick=\"
                            $(this).parent().parent().remove(); return false;
                        \" 
                        style=\"color:red;\" id='produ' >Delete</a></td>";
                ?>
            </tr>
        </table>

    <div>
        <?php echo CHtml::submitButton('Save'); ?>
    </div>

<?php $this->endWidget(); ?>
</div><!-- form -->

After that, we will make a code in controller to save update data. Make this in you controller :

 public function actionUpdate()
{
    if(isset($_POST['ques3']))
    {

            $data=YourModel::model()->findAllByAttributes(array('field1'=>yourParam));
            foreach ($_POST['ques3'] as $q3k => $q3v)
            {
                 // if you find index key from $data, so it will be update the data
                 // if no, so make new data
                if(isset($data[$q3k]))
                {
                    $tabdata=YourModel::model()->findByPk($data[$q3k]->idAttribute);  
                }
                else
                {
                    $tabdata=new YourModel;
                }
                $tabdata->field2=$q3v;
                $tabdata->field1=$model->idAttribute;
                $tabdata->save();
            }
    }

    $this->render('update');
}

And for delete existing data, make this code on your controller :

 public function actionDelete()
    {
        if(isset($_GET['id']))
        {
            $idnya=substr($_GET['id'], 5); // remember we need to catch id from "produ" and the id 
             //is the next value after "produ"
            $model=YourModel::model()->findByPk($idnya); search data
            if($model!==null)  // if we can find data, delete it
                $model->delete();
        }
    }

Finsih… Hope it help…

Happy coding… 😀

How To Integrate Yii Framework And Propel

I have been done a project that require use Propel and Yii Framework to connect my application and database. Why i use Propel in Yii Framework and why not active record ? I dont like say it, but it requirement from the project. So before that, i will say about use Propel in Yii Framework :

1. Yii have active record for database, if you use Propel or any ORM you will lost Yii active record. And if you think you can use both of it, i think bad idea.

2. Some extension in Yii use Yii class that use active record. If you use Propel or another ORM, you must modify your extension. For example i use “rights” extension for user management and must modify it.

3. I dont say active record better that propel or propel better thatn active record, but for me in Yii Framework, active record is the best way to manage your database.

4. You must learn again about how to use Propel..  🙂

So this is way to integrate propel and Yii Framework :

1. create your propel

2. insert it in your project, for example insert it in directory “yourapplication/protected/vendor/propel”

3. Edit your root index.php from :

 <?php
$yii=dirname(__FILE__).'/../yii/framework/yii.php';
$config=dirname(__FILE__).'/protected/config/main.php';
defined('YII_DEBUG') or define('YII_DEBUG',true);
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
require_once($yii);
Yii::createWebApplication($config)->run();

to :

 <?php
$yii=dirname(__FILE__).'/framework/yii.php';
$config=dirname(__FILE__).'/protected/config/main.php';

defined('YII_DEBUG') or define('YII_DEBUG',true);
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
require_once($yii);

spl_autoload_unregister(array('YiiBase','autoload'));
require_once ('protected/vendor/propel/runtime/lib/Propel.php'); // this is your propel path

Propel::init("protected/vendor/propel/build/conf/crm-conf.php"); // this is your propel database class path
set_include_path("protected/vendor/propel/build/classes" . PATH_SEPARATOR . get_include_path());

spl_autoload_register(array('Propel', 'autoload'));
spl_autoload_register(array('YiiBase', 'autoload'));

Yii::createWebApplication($config)->run();

After that you can use propel for your application,..

Finish.. hope it help..

[Yii Framework] Use CPasswordHelper For Authentication

Note : available for Yii 1.1.14.

Yii framework telah merilis versi 1.1.14, salah satu fitur tambahan yang ada yaitu class CPasswordHelper terbaru : http://www.yiiframework.com/news/75/yii-1-1-14-is-released/.  Class ini sendiri menyediakan fungsi-fungsi yang dapat digunakan untuk proses autentikasi seperti register dan login. So what the different with md5 or sha? For more information about this class, you can see this wiki : http://www.yiiframework.com/wiki/425/use-crypt-for-password-storage/.

Baiklah, pada postingan ini i will explain how to use this class and compare it with md5 way.

CREATE REGISTER USER

Saya asumsikan kita memiliki tabel seperti berikut untuk tabel user :

 CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `name` varchar(45) NOT NULL,
  `password` varchar(100) NOT NULL,
  `salt_password` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

kita menggunakan password dan salt_password untuk memperkuat enkripsinya ketika kita lakukan dengan md5. Berikut implementasi untuk register user yang kita buat, pada model user kita membuat fungsi untuk generate salt_password dan men-genearate nilai hash password untuk password user.

    public function beforeValidate()
    {
        if($this->isNewRecord)
        {    
            $this->salt_password=$this->generateSalt();
            //before validate, we create random value for salt_password
        }
        return parent::beforeValidate();
    }

    public function beforeSave()
    {
        if($this->isNewRecord)
        {    
            $pword=$this->password;
            $this->password=$this->hashPassword($dua,$this->salt_password); // set password value
            // with value that have been genereate with md5
        }
        return parent::beforeSave();
    }

    // use for validate password when do login
    public function validatePassword($password)
    {
        return $this->hashPassword($password,$this->salt_password)===$this->password;
    }

   // use for generate hash password
    public function hashPassword($password,$salt)
    {
        return md5($salt.$password);
    }

   // use for generate random value
    public function generateSalt()
    {
        return uniqid('',true);
    }

Kemudian untuk fungsi loginnya, kita buat seperti berikut pada component/useridentity :

    private $_id;

    public function authenticate()
    {
        $username = strtolower($this->username);
        $user = FUser::model()->find('LOWER(username)=?', array($username));
        if($user===null)
            $this->errorCode=self::ERROR_USERNAME_INVALID;        
        else if(!$user->validatePassword($this->password))
            $this->errorCode = self::ERROR_PASSWORD_INVALID;
        else
        {
            $this->_id = $user->id;
            $this->username = $user->username;
            $this->errorCode = self::ERROR_NONE;

          }
           return $this->errorCode == self::ERROR_NONE;
    }    

    public function getId()
    {
        return $this->_id;
    }

dan kode di atas, ketika kita melakukan register akan menghasilkan data seperti berikut :

 '1', 'sabit', 'sabit', 'a4057733cf4710736b652963a701746d', '520869a6a1d376.93126928'

Lalu bagaimana dengan implementasi menggunakan cpasswordhelper, yang perlu kita rubah pada bagian model menjadi seperti berikut :

    public function beforeSave()
    {
        if($this->isNewRecord)
        {    
            $pword=$this->password;
            $this->password = CPasswordHelper::hashPassword($pword);
        }
        return parent::beforeSave();
    }

Sementara itu untuk fungsi validatePassword, hashPassword, generateSalt tidak lagi digunkana pada fungsi ini. Kemudian untuk fungsi login kita buat menjadi seperti berikut :

     private $_id;

    public function authenticate()
    {
        $username = strtolower($this->username);
        $user = FUser::model()->find('LOWER(username)=?', array($username));
        if($user===null)
            $this->errorCode=self::ERROR_USERNAME_INVALID;
        else if(!CPasswordHelper::verifyPassword($this->password, $user->password))// here we do change
            $this->errorCode = self::ERROR_PASSWORD_INVALID;
        else
        {
            $this->_id = $user->id;
            $this->username = $user->username;
            $this->errorCode = self::ERROR_NONE;

          }
           return $this->errorCode == self::ERROR_NONE;
    }    

    public function getId()
    {
        return $this->_id;
    }

dan dengan menggunakan cpasswordhelper, kita akan mendapatkan nilai seperti berikut :

 '3', 'andi', 'andi', '$2a$13$ESeZW/8I.lZLWZTomyUKteo0bHmTroH.G91lElgCtXOcrVfmKiPQ.', ''

You can see it we no need with salt_password again..

Finish… Hope it help… happy coding..

[PHP Mongodb] Implement MapReduce

In previous posti https://sabitlabscode.wordpress.com/2013/07/29/mongodb-understanding-mapreduce/ , saya sudah paparkan tentang mapreduce dan bagaimana cara membuatnya di mongodb. So, how to implement it in PHP? Sebenarnya tidak terlalu jauh berbeda dengan memanggil tabel biasa. Jika anda memiliki tabel “member” misal, anda bisa memanggil semua datanya pada PHP dengan :

             
$result = $database->selectCollection('member')->find();

untuk mapreduce anda dapat memanggil nya sama dengan cara di atas, seperti berikut :

             
$result = $database->selectCollection('your_mapreduce_name')->find();

Dan berikut adalah contoh lengkap mulai dari mendefinisikan mapreduce hingga memanggilnya pada PHP. Pertama kita harus mendefinisikan map dan reduce nya seperti berikut (i use same case with previous post) :

     public function getSiswabyjk()
    {
        try {
            $connection = new Mongo();
            //get your database
            $database = $connection->selectDB('your_database_name');
            //define map function
            $map1=new MongoCode("function(){emit(this.sex,1);}");
            //define reduce function
            $reduce1=new MongoCode("function(key,value){".
                "var count=0;".
                "for(var i=0;i<value.length;i++){".
                "count+=value[i]".
                "}".
                "return count;".
                "}");
            //define map reduce function
            $command = array(
                'mapreduce' => 'your_table_name_here', // set table name
                'map' => $map1, // set map
                'reduce' => $reduce1, // set reduce
                'out' => 'mapreduce_name'  //set name of mapreduce, it use for call mapreduce
            );
            //run mapreduce command
            $database->command($command);
            // get result from mapreduce
            $result = iterator_to_array($database->selectCollection('mapreduce_name')->find());
            return $result;
        }
        catch(MongoConnectionException $e) {
            die("Failed to connect to database ".$e->getMessage());
        }
        catch(MongoException $e) {
            die($e->getMessage());
        }                
    }

Finish, you can see the result from this function..
Happy coding..

[PHP Yii Mongodb] Work With Data Relation (2)

Melanjutkan previous post di https://sabitlabscode.wordpress.com/2013/07/14/php-yii-mongodb-work-with-data-relation/, postingan ini akan membahas penggunaan cara ke 2 yaitu dengan cara memasukkan langsung data ke dalam document. Anggaplah saya memiliki document “news” yang data nya terdiri dari :

news : title, news, comments [comment_title, comment_name, comment]

dapat anda lihat bahwa setiap satu “news” dapat memiliki banyak komentar di dalamnya. Bagaimana cara membuatnya? Okeh, pertama-tama kita buat terlebih dahulu modelnya, kita definisikan semua fungsi-fungsi yang kita butuhkan mulai dari savedate, edit, delete, findall, findone, da addcomment. Sehingga model anda akan menjadi seperti berikut :

 <?php
//definition model name
class NewsForm extends CFormModel
{
    //define variable in model 
    public $title;
    public $news;
    public $comment_name;
    public $comment_title;
    public $comment;

    // rule validation
    public function rules()
    {
        return array(
            array('title,news', 'required'),
            //required just when we add comment
            array('comment_name,comment_title,comment','required','on'=>'createcomment'),
        );
    }

    //attribute label in form
    public function attributeLabels()
    {
        return array(
            'title'=>'Title',
            'news'=>'Insert Your News Here',
            'comment_name'=>'Created By',
            'comment_title'=>'Comment Title',
            'comment'=>'Comment',
        );
    }

    //run it for save data
    public function savenews()
    {
        try {
            //get connection to access document
            $connection = new Mongo();
            $collection = $connection->belajar->news;
            $varnews = array(
                'title' => $this->title,
                'news' => $this->news,
            );
            //insert data
            $collection->insert($varnews,array('safe'=>true));
            return true;
        }
        catch(MongoConnectionException $e) {
            die("Failed to connect to database ".$e->getMessage());
        }
        catch(MongoException $e) {
            die('Failed to insert data '.$e->getMessage());
        }
    }

    //run it for update data
    public function editnews($id)
    {
        try {
            $connection = new Mongo();
            $collection = $connection->belajar->news;
            $varnews = array('$set'=>array(
                    'title' => $this->title,
                    'news' => $this->news,
                )
            );        
            //update data    
            $collection->update(array('_id' => new MongoId($id)),$varnews);
            return true;
        }
        catch(MongoConnectionException $e) {
            die("Failed to connect to database ".$e->getMessage());
        }
        catch(MongoException $e) {
            die('Failed to insert data '.$e->getMessage());
        }
    }

    //run it for delete data
    public function deletenews($id)
    {    
        try {
            $connection = new Mongo();
            $collection = $connection->belajar->news;
            //remove data
            $collection->remove(array('_id'=>new MongoId($id)));
        }
        catch(MongoConnectionException $e) {
            die("Failed to connect to database ".$e->getMessage());
        }
        catch(MongoException $e) {
            die('Failed to do operation '.$e->getMessage());
        }
    }

    // this will return all data from document nilai
    public function findallmongo()
    {
        try {
            $connection = new Mongo();
            $collection = $connection->belajar->news;
            //get all data
            $result= $collection->find();

            return $result;
        }
        catch(MongoConnectionException $e) {
            die("Failed to connect to database ".$e->getMessage());
        }
        catch(MongoException $e) {
            die($e->getMessage());
        }    
    }

    // find news by id
    public function findOneById($id)
    {
        try 
        {
            $connection = new Mongo();
            $collection = $connection->belajar->news;
            //get data by $id in parameter
            return $collection->findOne(array('_id'=>new MongoId($id)));
        }
        catch(MongoConnectionException $e) {
            die("Failed to connect to database ".$e->getMessage());
        }
        catch(MongoException $e) {
            die($e->getMessage());
        }    
    }

    //use for add a comment in news
    public function addcomment($id)
    {
        try 
        {
            $connection = new Mongo();
            $collection = $connection->belajar->news;
            //set some value for comment
            $varcomment = array(
                'comment_name' => $this->comment_name,
                'comment_title' => $this->comment_title,
                'comment'=>$this->comment
            );

            // we use $push to add insert value to comments
            // if we not use $push, it replace old data that
            // we have insert
            $collection->update(array('_id' => new MongoId($id)),
                array('$push' =>array('comments' => $varcomment)),
                array('upsert'=>true));
        }
        catch(MongoConnectionException $e) {
            die("Failed to connect to database ".$e->getMessage());
        }
        catch(MongoException $e) {
            die($e->getMessage());
        }
    }
}

Setelah membuat model, kita lanjutkan dengan membuat controller agar user dapat melakukan request pada action-action yang telah kita tentukan. Pada controller ini kita akan menyediakan action-action berikut :

– action index = view all data from news

– actionview = show single data by id, pada actionview juga akan disediakan fitur untuk menambah komentar

– actioncreate = insert new data to document

– actionupdate = update data

– actiondelete = delete data from document

dan berikut adalah code dari controller nya :

 <?php
class NewsController extends Controller
{
    // action index to see all data in document nilai
    public function actionIndex()
    {
        $model=new NewsForm;
        //get all data from model
        $data=$model->findallmongo();

        $this->render('index',array(
            'data'=>$data,
            'model'=>$model,
        ));
    }

    // it will show detail data from tabel "nilia"
    public function actionView($id)
    {
        $model=new NewsForm('createcomment');//it will do validation for "createdcomment"
        // call a data from model "news" by id
        $data=$model->findOneById($id);
        //set field model with $data that 
        //we get from model
        $model->news=$data['news'];
        $model->title=$data['title'];

        //if user do submit(POST) data
        //for write a comment, then do this
        if(isset($_POST['NewsForm']))
        {
            //set value with data that have been submitted
            $model->comment_name=$_POST['NewsForm']['comment_name'];
            $model->comment_title=$_POST['NewsForm']['comment_title'];
            $model->comment=$_POST['NewsForm']['comment'];

            //check validate
            if($model->validate())
            {
                // call function addcomment
                if($model->addcomment($id))
                {
                    $this->redirect(array('view'));
                }
            }
        }

        $this->render('view',array(
            'data'=>$data,
            'model'=>$model,
        ));

    }

    // it use for create new data
    public function actionCreate()
    {
        $model=new NewsForm;
        //when user do submit to this
        if(isset($_POST['NewsForm']))
        {
            $model->news=$_POST['NewsForm']['news'];
            $model->title=$_POST['NewsForm']['title'];
            if($model->validate())
            {
                //save data
                if($model->savenews())
                {
                    $this->redirect(array('index'));
                }
            }
        }
        $this->render('update',array('model'=>$model));
    }

    // update data
    public function actionUpdate($id)
    {
        //define model
        $model=new NewsForm;
        // get data by id
        $data=$model->findOneById($id);
        //set value
        $model->news=$data['news'];
        $model->title=$data['title'];

        //do this when submit
        if(isset($_POST['NewsForm']))
        {
            //set value with submit value
            $model->news=$_POST['NewsForm']['news'];
            $model->title=$_POST['NewsForm']['title'];

            if($model->validate())
            {
                //edit data
                if($model->editnews($id))
                {
                    $this->redirect(array('index'));
                }
            }
        }
        $this->render('update',array('model'=>$model));    
    }

    // delete data
    public function actionDelete($id)
    {
        $model= new NewsForm;
        $model->deletenews($id);
        $this->redirect(array('index'));
    }
}

Di atas adalah code controller kita. Anda dapat melihat pada komentar-komentar code nya untuk melihat penjelasannya.
Setelah membuat controller nya, sekarang saatnya membuat tampilan dari controller itu sendiri. Berikut tampilan yang akan kita buat mulai dari index.php

 <h1>This Is All News That We Have In Mongodb</h1>
<?php echo CHtml::link('Create News',array('create')); ?>
<?php 
    while ($data->hasNext()):
        $news= $data->getNext(); 
?>

<h2>
<?php echo CHtml::link($news['title'],array('view','id'=>$news['_id'])); ?>
</h2>
[[
<?php 
$totalcomment=0;
if(isset($news['comments']))
    $totalcomment=count($news['comments']);
echo 'Total Comment('.$totalcomment.') | ';
?>
<?php echo CHtml::link('Update',array('update','id'=>$news['_id'])) ?> |
<?php echo CHtml::link('Delete',array('delete','id'=>$news['_id'])) ?>
]]<br/>
<?php endwhile; ?>

Kemudian tampilan untuk actionCreate dan actionUpdate yaitu create.php

 <h1>Test Mongo - Pelajaran</h1>
<div>
<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'contact-form',
    'enableClientValidation'=>true,
    'clientOptions'=>array(
        'validateOnSubmit'=>true,
    ),
)); ?>

    <p>Fields with <span>*</span> are required.</p>

    <?php echo $form->errorSummary($model); ?>

    <div>
        <?php echo $form->labelEx($model,'title'); ?>
        <?php echo $form->textField($model,'title'); ?>
        <?php echo $form->error($model,'title'); ?>
    </div>

    <div>
        <?php echo $form->labelEx($model,'news'); ?>
        <?php echo $form->textArea($model,'news'); ?>
        <?php echo $form->error($model,'news'); ?>
    </div>

    <div>
        <?php echo CHtml::submitButton('Submit'); ?>
    </div>
<?php $this->endWidget(); ?>
</div>

dan yang terakhir adalah actionView yang akan menampilkan single data dan dapat menambahkan komentar di dalamnya :

 <h1>View News</h1>

<h2><?php echo $data['title']; ?></h2>
<p><?php echo $data['news'];?></p>
<table>
    <tr>
        <td>Craeted By</td>
        <td>Comment Title</td>
        <td>Comment</td>
<?php
if(isset($data['comments']))
{
    foreach ($data['comments'] as $key => $value) {
        echo '<tr>';
        echo '<td>'.$value['comment_name'].'</td>';
        echo '<td>'.$value['comment_title'].'</td>';
        echo '<td>'.$value['comment'].'</td>';
    }
}
?>
</table>

<h2>Insert Your Comment Here :</h2>
<div>
<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'contact-form',
    'enableClientValidation'=>true,
    'clientOptions'=>array(
        'validateOnSubmit'=>true,
    ),
)); ?>

    <p>Fields with <span>*</span> are required.</p>

    <?php echo $form->errorSummary($model); ?>

    <div>
        <?php echo $form->labelEx($model,'comment_name'); ?>
        <?php echo $form->textField($model,'comment_name'); ?>
        <?php echo $form->error($model,'comment_name'); ?>
    </div>

    <div>
        <?php echo $form->labelEx($model,'comment_title'); ?>
        <?php echo $form->textField($model,'comment_title'); ?>
        <?php echo $form->error($model,'comment_title'); ?>
    </div>

    <div>
        <?php echo $form->labelEx($model,'comment'); ?>
        <?php echo $form->textArea($model,'comment'); ?>
        <?php echo $form->error($model,'comment'); ?>
    </div>

    <div>
        <?php echo CHtml::submitButton('Submit'); ?>
    </div>
<?php $this->endWidget(); ?>
</div>

Okeh, itulah dia sedikit contoh membuat proses CRUD untuk document mongodb yang memiliki embedded document di dalamnya. Yang perlu diperhatikan adalah kapan kita harus menggunakan relasi langsung dan kapan kita menggunakan embed document karena tentu ini akan berpengaruh pada aplikasi yang anda buat..

Finish… Hope it help.. Happy coding… 😀

%d bloggers like this: