[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… 😀

Advertisements

[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… 😀

[Yii Framework] Update Password With CPasswordHelper

I post this item for answer this question here :https://sabitlabscode.wordpress.com/2013/08/12/yii-framework-use-cpasswordhelper-for-authentication/#comment-2141. So how to update password with CPasswordHelper?

We need to take an action to update password, so create it in controller like this :

 public function actionChangepassword()
    {
        $data=$this->loadModel(Yii::app()->user->id);//get current user that active now

        if(isset($_POST['old'],$_POST['baru1'],$_POST['baru2'])) // if user post to change password
        {
            if($_POST['baru1']!==$_POST['baru2']) // check if it have same password for validation?
            {
                $data->addError('username','Your New Password Not Match'); // if not same, show error
            }
            else // if same, next
            {
                if(CPasswordHelper::verifyPassword($_POST['old'], $data->pass)) // check the old password that user input same with old password?
                {
                    $dua=$_POST['baru1'];
                    $data->pass=CPasswordHelper::hashPassword($_POST['baru1']);// encryp that
                    if($data->save()) // save to tabel
                    {
                        $this->redirect(array('/site'));    
                    }
                }
                else //if password not match with old password, show error
                {
                    $data->addError('username','Wrong Password');
                }
            }
        }

        $this->render('cp',array( //call "cp" view
            'data'=>$data,
        ));
    }

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

After that, we need to create new file for view with name “cp.php” (we call “cp.php” in render, so the name must be match) and insert this code :

 <?php
/* @var $this UserController */
/* @var $model User */

$this->breadcrumbs=array(
    'Change Password',
);

?>

<h1>Change Password</h1>

<div>
<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'user-form',
    'enableAjaxValidation'=>true,
)); ?>

    <?php echo $form->errorSummary($data); ?>
    <table>
        <tr>
            <td><?php echo 'Your Current Password :'; ?></td>
            <td>
                <?php echo CHtml::passwordField('old','',array('size'=>50,'maxlength'=>50)); ?>
            </td>
        </tr>
        <tr>
            <td><?php echo 'New Password :'; ?></td>
            <td>
                <?php echo CHtml::passwordField('baru1','',array('size'=>50,'maxlength'=>50)); ?>
            </td>
        </tr>
        <tr>
            <td><?php echo 'Confirmation Your New Password :'; ?></td>
            <td>
                <?php echo CHtml::passwordField('baru2','',array('size'=>50,'maxlength'=>50)); ?>
            </td>
        </tr>
    </table>

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

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

Finish… 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 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… 😀

[PHP Yii Mongodb] Work With Data Relation

Pada rdbms biasanya kita sudah tidak asing dengan istilah tabel relation yang membuat hubungan antara dua tabel atau lebih. Bagaimana dengan mongodb? bukankah mongodb adalah nosql bukan “relational DBMS”? Ya, mongodb juga telah mengakomodasi hal tersebut walaupun tidak persis sama dengan yang dimiliki pada rdbms. Ada 2 cara untuk mengimplementasikannya di dalam mongodb.

1. Membuat field relasi langsung.

Ini sama dengan yang biasa kita lakukan pada rdbms, dimana kita membuat field pengubung (foreign key) pada suatu tabel untuk membuat hubungan antar tabel.

2. Memasukkan data ke dalam document langsung.

Sebenarnya ini bukanlah membuat relation ke dalam tabel, tapi kita memasukkan langsung data-data ke dalam sebuah document. Sebagai contoh dalam mysql kita memiliki tabel “berita” dan “komentar” dimana berita dapat memiliki banyak komentar. Hubungan antara keduanya berita dapat memiliki lebih dari satu komentar, dan komentar hanya memiliki satu buah berita. Pada rdbms kita membuatnya dengan dua buah tabel seperti berikut :

– tabel 1 = > berita : id, judul, isi berita

– tabel 2 => komentar : id, judul komentar, isi komentar, berita_id (foreign key)

pada mongodb, kita dapat memasukkannya langsung ke dalam document berita menjadi seperti berikut :

– document berita : id, judul, isi berita, komentar [id, judul, isi komentar]

Tetapi perlu dipahami kasus-kasus dimana kita lebih baik menggunakan cara 1 atau cara 2.

Ok, sekarang kita coba langsung implementasinya. Pada postingan kali ini akan dibahas penggunaan cara 1, maybe next time akan membahas cara 2.  Kita memiliki 3 buah document :

– siswa : id, nama

– pelajaran : id, nama pelajaran

– nilai : id, siswa_id, pelajaran_id, nilai

Anggaplah kita sudah membuat operasi CRUD untuk document “siswa” dan “pelajaran” (if you dont know how to do it, search it here https://sabitlabscode.wordpress.com/tag/mongodb/). Okeh, sekarang buatlah sebuah model nilai seperti berikut :

 <?php

class NilaiForm extends CFormModel
{
    //define variable in 
    public $pelajaran_id;
    public $siswa_id;
    public $nilai;

    // rule validation
    public function rules()
    {
        return array(
            array('pelajaran_id, siswa_id, nilai', 'required'),
        );
    }

    //attribute label in form
    public function attributeLabels()
    {
        return array(
            'pelajaran_id'=>'Pelajaran',
            'siswa_id'=>'Siswa',
            'nilai'=>'Nilai'
        );
    }

    //run it for save data
    public function savemongo()
    {
        try {
            $connection = new Mongo();
            $database = $connection->selectDB('belajar');
            $collection = $database->selectCollection('nilai');
            $varsiswa = array(
                'pelajaran_id' => new MongoId($this->pelajaran_id),
                'siswa_id' => new MongoId($this->siswa_id),
                'nilai'=>$this->nilai
            );
            $collection->insert($varsiswa,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 editmongo($id)
    {
        try {
            $connection = new Mongo();
            $database = $connection->selectDB('belajar');
            $collection = $database->selectCollection('nilai');
            $varsiswa = array(
                'pelajaran_id' => $this->pelajaran_id,
                'siswa_id' => $this->siswa_id,
                'nilai'=>$this->nilai
            );
            $collection->update(array('_id' => new MongoId($id)),$varsiswa);
            //$collection->insert($varsiswa,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 delete data
    public function deletemongo($id)
    {    
        try {
            $connection = new Mongo();
            $collection = $connection->belajar->nilai;
            $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();
            $database = $connection->selectDB('belajar');
            $collection = $database->selectCollection('nilai');
            $result= $collection->find();

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

    public function findOneById($id)
    {
        try 
        {
            $connection = new Mongo();
            $database = $connection->selectDB('belajar');
            $collection = $database->selectCollection('nilai');
            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());
        }    
    }
}

Setelah itu, buatlah controller untuk request pada aplikasi :

 <?php

class NilaiController extends Controller
{
    // action index to see all data in document nilai
    public function actionIndex()
    {
        $model=new NilaiForm;
        $data=$model->findallmongo();

        // mongodb cant do join, so we need to call model "pelajaran" and "siswa"
        // to show all field that owned by "pelajaran" and "siswa" 
        $m1=new PelajaranForm; 
        $m2=new SiswaForm;
        $this->render('index',array(
            'data'=>$data,
            'm1'=>$m1,
            'm2'=>$m2,
        ));
    }

    // it will show detail data from tabel "nilia"
    public function actionView($id)
    {
        $model=new NilaiForm;
        // call a data from model "nilai"
        $data=$model->findOneById($id);
        $m1=new PelajaranForm;
        $m2=new SiswaForm;

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

    }

    // it use for create new data
    public function actionCreate()
    {
        $model=new NilaiForm;
        if(isset($_POST['NilaiForm']))
        {
            $model->pelajaran_id=$_POST['NilaiForm']['pelajaran_id'];
            $model->siswa_id=$_POST['NilaiForm']['siswa_id'];
            $model->nilai=$_POST['NilaiForm']['nilai'];
            if($model->validate())
            {
                if($model->savemongo())
                {
                    $this->redirect(array('index'));
                }
            }
        }
        $this->render('Nilai',array('model'=>$model));
    }

    // update data
    public function actionUpdate($id)
    {
        $model=new NilaiForm;
        $data=$model->findOneById($id);
        $model->name=$data['name'];

        $model->pelajaran_id=$data['pelajaran_id'];
        $model->siswa_id=$data['siswa_id'];
        $model->nilai=$_POST['NilaiForm']['nilai'];

        if(isset($_POST['NilaiForm']))
        {
            $model->pelajaran_id=$_POST['NilaiForm']['pelajaran_id'];
            $model->siswa_id=$_POST['NilaiForm']['siswa_id'];

            if($model->validate())
            {
                if($model->editmongo($id))
                {
                    $this->redirect(array('index'));
                }
            }
        }
        $this->render('Nilai',array('model'=>$model));    
    }

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

Kemudian aturlah tampilan datanya. Ini adalah tampilan untuk actionIndex,

 <h1>Test Mongo - Nilai</h1>
<?php 
    while ($data->hasNext()):
        $siswa = $data->getNext(); 

$pelajaran=$m1->findOneById($siswa['pelajaran_id']);
$sisw=$m2->findOneById($siswa['siswa_id']);
?>

<b>
<?php echo CHtml::link($pelajaran['name'],array('view','id'=>$siswa['_id'])); ?> | 
<?php echo CHtml::link($sisw['name'],array('view','id'=>$siswa['_id'])); ?>
</b>
[[
<?php echo CHtml::link('Update',array('update','id'=>$siswa['_id'])) ?> |
<?php echo CHtml::link('Delete',array('delete','id'=>$siswa['_id'])) ?>
]]<br/>
<?php endwhile; ?>

Ini tampilan untuk actioncreate dan actionupdate

 <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,'pelajaran_id'); ?>
        <?php echo $form->dropDownList($model,'pelajaran_id',PelajaranForm::dropdown(),array('empty'=>'- Select Pelajaran-')); ?>
        <?php echo $form->error($model,'pelajaran_id'); ?>
    </div>

    <div>
        <?php echo $form->labelEx($model,'siswa_id'); ?>
        <?php echo $form->dropDownList($model,'siswa_id',SiswaForm::dropdown(),array('empty'=>'- Select Pelajaran-')); ?>
        <?php echo $form->error($model,'siswa_id'); ?>
    </div>

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

dan ini adalah tampilan untuk actionView

 <h1>Test Mongo - Nilai</h1>
<?php
$pelajaran=$m1->findOneById($data['pelajaran_id']);
$sisw=$m2->findOneById($data['siswa_id']);
echo $pelajaran['name'];
echo $sisw['name'];
?>

Anda dapat pelajari penjelasan code-code tersebut dari komentar yang ada pada code dan postingan sebelumnya tentang mongodb..

Selesai.. Hope it help..

Happy coding.. 😀

%d bloggers like this: