Social Icons

Pages

Saturday, November 17, 2012

Reading Record


To read data in a database table, we call one of the find methods as follows.

// find the first row satisfying the specified condition
$post=Post::model()->find($condition,$params);
// find the row with the specified primary key
$post=Post::model()->findByPk($postID,$condition,$params);
// find the row with the specified attribute values
$post=Post::model()->findByAttributes($attributes,$condition,$params);
// find the first row using the specified SQL statement
$post=Post::model()->findBySql($sql,$params);



hen multiple rows of data matching the specified query condition, we can bring them in all together using the following findAll methods, each of which has its counterpart find method, as we already described.

// find all rows satisfying the specified condition
$posts=Post::model()->findAll($condition,$params);
// find all rows with the specified primary keys
$posts=Post::model()->findAllByPk($postIDs,$condition,$params);
// find all rows with the specified attribute values
$posts=Post::model()->findAllByAttributes($attributes,$condition,$params);
// find all rows using the specified SQL statement
$posts=Post::model()->findAllBySql($sql,$params);






More.....

Yii Relations


USER table
- id
- name

POST table
 - id
 - user_id         REFERENCES User.id
 - content

PROFILE table
 - id
 - user_id         REFERENCES User.id
 - profile_info
KEY POINT: A BELONGS_TO relation says that a field in this model points to the primary key in another model; in this case, the current model owns the linking field.

KEY POINT: A HAS_ONE relation says that some other model has a linking field pointing to this model's primary key; in this case, the related model owns the linking field.

Let's put these in context (numbered for reference)

// Post model relations
1.   'user'    => array(self::BELONGS_TO, 'User',    'user_id'),

// Profile model relations
2.   'user'    => array(self::BELONGS_TO, 'User',    'user_id'),

// User model relations
3.   'posts'   => array(self::HAS_MANY,   'Post',    'user_id'),
4.   'profile' => array(self::HAS_ONE,    'Profile', 'user_id'),

Friday, November 16, 2012

Yii internationalization (i18n)


below example, the default language English (en), and we will add some French (fr) components.

1. application configuration (protected/config/main.php), set the sourceLanguage parameter to English(en):

return array(
...
, 'sourceLanguage'=>'en'
...
)


2. In  view, use the Yii::t() function to translate strings:

echo Yii::t('filename','this is fine tutorial for yii internationalization').'<br/>';

echo Yii::t('filename','you have {count} new emails', array('{count}'=>5)).'<br/>';

3. Add a folder "fr" under /protected/messages, and a file called "filename.php". The content of filename.php should be this:


<?php

return array(
'this is fine tutorial for yii internationalization' => 'ce n\'est qu\'un tutoriel très bien pour yu internationalisation'
, 'you have {count} new emails' => 'vous avez {count} nouveaux e-mails'

);

?> 


Then, you can set the language. This is best done in the beginRequest event handler based on user preferences, but here's how to do it manually:

Yii::app()->language='fr';






events in Yii



If you want to use onBeginRequest and onEndRequest you can do it by adding the next lines into your


config file:

return array (
...
'onBeginRequest'=>array('Y', 'getStats'),
'onEndRequest'=>array('Y', 'writeStats'),
...
)


or you can do it inline

Yii::app()->onBeginRequest= array('Y', 'getStats');
Yii::app()->onEndRequest= array('Y', 'writeStats');



where Y is a classname and getStats and writeStats are methods of this class. Now imagine you have a class Y declared like this:


class Y {
public function getStats ($event) {
// Here you put all needed code to start stats collection
}
public function writeStats ($event) {
// Here you put all needed code to save collected stats
}
}



So on every request both methods will run automatically. Of course you can think "why not simply overload onBeginRequest method?" but first of all events allow you to not extend class to run some repeated code and also they allow you to execute different methods of different classes declared in different places. So you can add

Yii::app()->onEndRequest= array('YClass', 'someMethod');

at any other part of your application along with previous event handlers and you will get run both Y->writeStats and YClass->someMethod after request processing. This with behaviors allows you create extension components of almost any complexity without changing source code and without extension of base classes of Yii.

CGridView in Admin Panel


Scenario 
This is CRUD pages for admin menu management. So, Menu model have following things:

menuId : INT
menuName : VARCHAR
sortOrder : INT (Admin may change menu order, based on that front side menu will render)
isActive : BOOL (only values with '1' will be shown in front side)
isDelete : BOOL (only values with '0' will be shown, whenever admin deletes any menu value will be changed to '1')




Fetch listing from model:
Let's start with model file. There is only one change, I want default listing by sortOrder field.

public function search()
{
    .....
    return new CActiveDataProvider($this, array(
    'criteria'=>$criteria,
    'sort'=>array(
        'defaultOrder'=>'sortOrder ASC',
    ),
    ));
}
Add TextField, checkbox, buttons in CGridView: 
Now we will see view file.

We need to add CGridView inside form so that we can save grid data after submission. We will use ajax to operate all things.
We need to use CCheckBoxColumn which will generate checkbox first column as shown in image.
We need some ajax button at bottom of the page using ajaxSubmitButton which will handle all events. Button names are self-explainable. Here i am going to use 4 buttons
To change status to 'Active'
To change status to 'In Active'
To delete multiple row.
To update sort order.

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

<?php 
    $this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'menu-grid',
    'dataProvider'=>$model->search(),
    'filter'=>$model,
    'columns'=>array(
        array(
            'id'=>'autoId',
            'class'=>'CCheckBoxColumn',
            'selectableRows' => '50',   
        ),
        'menuId',
        'menuName',
        array(
            'name'=>'sortOrder',
            'type'=>'raw',
            'value'=>'CHtml::textField("sortOrder[$data->menuId]",$data->sortOrder,array("style"=>"width:50px;"))',
            'htmlOptions'=>array("width"=>"50px"),
        ),
        array(
            'name'=>'isActive',
            'header'=>'Active',
            'filter'=>array('1'=>'Yes','0'=>'No'),
            'value'=>'($data->isActive=="1")?("Yes"):("No")'
        ),
        array(
            'class'=>'CButtonColumn',
        ),
    ),
)); ?>
<script>
function reloadGrid(data) {
    $.fn.yiiGridView.update('menu-grid');
}
</script>
<?php echo CHtml::ajaxSubmitButton('Filter',array('menu/ajaxupdate'), array(),array("style"=>"display:none;")); ?>
<?php echo CHtml::ajaxSubmitButton('Activate',array('menu/ajaxupdate','act'=>'doActive'), array('success'=>'reloadGrid')); ?>
<?php echo CHtml::ajaxSubmitButton('In Activate',array('menu/ajaxupdate','act'=>'doInactive'), array('success'=>'reloadGrid')); ?>
<?php echo CHtml::ajaxSubmitButton('Delete',array('menu/ajaxupdate','act'=>'doDelete'), array('success'=>'reloadGrid')); ?>
<?php echo CHtml::ajaxSubmitButton('Update sort order',array('menu/ajaxupdate','act'=>'doSortOrder'), array('success'=>'reloadGrid')); ?>
<?php $this->endWidget(); ?>




From above code you may wonder why i have taken Filter invisible button, reason is if you don't put it and type something in filter boxed and press enter it will invoke 'Active' button, as it the first submit button in form, you may also try some other options.

Save all grid data into database: 
Looking into controller file.

public function actionAjaxupdate()
{
    $act = $_GET['act'];
    if($act=='doSortOrder')
    {
        $sortOrderAll = $_POST['sortOrder'];
        if(count($sortOrderAll)>0)
        {
            foreach($sortOrderAll as $menuId=>$sortOrder)
            {
                $model=$this->loadModel($menuId);
                $model->sortOrder = $sortOrder;
                $model->save();
            }
        }
    }
    else
    {           
        $autoIdAll = $_POST['autoId'];
        if(count($autoIdAll)>0)
        {
            foreach($autoIdAll as $autoId)
            {
                $model=$this->loadModel($autoId);
                if($act=='doDelete')
                    $model->isDeleted = '1';
                if($act=='doActive')
                    $model->isActive = '1';
                if($act=='doInactive')
                    $model->isActive = '0';                     
                if($model->save())
                    echo 'ok';
                else
                    throw new Exception("Sorry",500);

            }
        }
    }
}

reference 


Thursday, November 15, 2012

Before Save Function in Model


class User extends CActiveRecord
{
    // Format 1
    public function beforeSave()
    {
        if($this->isNewRecord)
        {          
            $this->date=new CDbExpression('NOW()');
            $this->status=0; //option by default
        }else{
             $this->modified = new CDbExpression('NOW()');
        }
        return parent::beforeSave();
    }

    // Format 2
    public function beforeSave()
    {
        if($this->isNewRecord)
        {          
            $this->date=new CDbExpression('NOW()');
            $this->status=0; //option by default
        }
        $this->modified = new CDbExpression('NOW()');
        return parent::beforeSave();
    }
}