View on GitHub

yii-ycm

YCM - Yii Content Management module

Download this project as a .zip file Download this project as a tar.gz file

Requirements

Installation

    'modules'=>array(
        ...
        'ycm'=>array(
            'username'=>'YOUR USERNAME',
            'password'=>'YOUR PASSWORD',
            'registerModels'=>array(
                //'application.models.Blog', // one model
                'application.models.*', // all models in folder
            ),
            'uploadCreate'=>true, // create upload folder automatically
            'redactorUpload'=>true, // enable Redactor image upload
        ),
        ...
    ),

Screenshots

Screenshot

Examples

Basic

Create table:

CREATE TABLE `sample`
(
  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `field0` TINYINT(4) DEFAULT '0',
  `field1` TINYINT(4) DEFAULT '0',
  `field2` TINYINT(4) DEFAULT '0',
  `field3` TINYINT(4) DEFAULT '0',
  `field4` VARCHAR(128) NOT NULL,
  `field5` VARCHAR(128) NOT NULL,
  `field6` TEXT NOT NULL,
  `field7` TEXT NOT NULL,
  `field8` VARCHAR(64) DEFAULT NULL,
  `field9` VARCHAR(64) DEFAULT NULL,
  `field10` DATE DEFAULT NULL,
  `field11` TIME DEFAULT NULL,
  `field12` DATETIME DEFAULT NULL,
  `field13` VARCHAR(64) DEFAULT NULL,
  `field14` TINYINT(4) DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Create Sample model:

<?php

/**
 * This is the model class for table "sample".
 *
 * The followings are the available columns in table 'sample':
 * @property integer $id
 * @property integer $field0
 * @property integer $field1
 * @property integer $field2
 * @property integer $field3
 * @property string $field4
 * @property string $field5
 * @property string $field6
 * @property string $field7
 * @property string $field8
 * @property string $field9
 * @property string $field10
 * @property string $field11
 * @property string $field12
 * @property string $field13
 * @property integer $field14
 */
class Sample extends CActiveRecord
{
    /**
     * Admin variables (ycm module)
     */
    public $adminNames=array('Samples','sample','samples'); // admin interface, singular, plural
    public $downloadExcel=true; // Download Excel
    public $downloadMsCsv=true; // Download MS CSV
    public $downloadCsv=true; // Download CSV

    /**
     * Behaviors.
     * @return array
     */
    function behaviors() {
        return array(
            'file' => array(
                'class'=>'application.modules.ycm.behaviors.FileBehavior',
            ),
        );
    }

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Sample the static model class
     */
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'sample';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('field4, field5, field6, field7', 'required'),
            array('field0, field1, field2, field3, field14', 'numerical', 'integerOnly'=>true),
            array('field4, field5', 'length', 'max'=>128),
            array('field8, field9, field13', 'length', 'max'=>64),
            array('field8, field9', 'unsafe'),
            array('field8', 'file', 'on'=>'insert', 'allowEmpty'=>true, 'types'=>'jpg,jpeg,gif,png', 'maxSize'=>1024*1024*6),
            array('field8', 'file', 'on'=>'update', 'allowEmpty'=>true, 'types'=>'jpg,jpeg,gif,png', 'maxSize'=>1024*1024*6),
            array('field9', 'file', 'on'=>'insert', 'allowEmpty'=>true, 'types'=>'jpg,jpeg,gif,png,gz,tar,zip,pdf,doc,docx,xls,xlsx,ppt,pptx,pps,ppsx', 'maxSize'=>1024*1024*6),
            array('field9', 'file', 'on'=>'update', 'allowEmpty'=>true, 'types'=>'jpg,jpeg,gif,png,gz,tar,zip,pdf,doc,docx,xls,xlsx,ppt,pptx,pps,ppsx', 'maxSize'=>1024*1024*6),
            array('field10, field11, field12', 'safe'),

            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('id, field0, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10, field11, field12, field13, field14', 'safe', 'on'=>'search'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'id' => 'ID',
            'field0' => 'Field 0',
            'field1' => 'Field 1',
            'field2' => 'Field 2',
            'field3' => 'Field 3',
            'field4' => 'Field 4',
            'field5' => 'Field 5',
            'field6' => 'Field 6',
            'field7' => 'Field 7',
            'field8' => 'Field 8',
            'field9' => 'Field 9',
            'field10' => 'Field 10',
            'field11' => 'Field 11',
            'field12' => 'Field 12',
            'field13' => 'Field 13',
            'field14' => 'Field 14',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria=new CDbCriteria;

        $criteria->compare('id',$this->id);
        $criteria->compare('field0',$this->field0);
        $criteria->compare('field1',$this->field1);
        $criteria->compare('field2',$this->field2);
        $criteria->compare('field3',$this->field3);
        $criteria->compare('field4',$this->field4,true);
        $criteria->compare('field5',$this->field5,true);
        $criteria->compare('field6',$this->field6,true);
        $criteria->compare('field7',$this->field7,true);
        $criteria->compare('field8',$this->field8,true);
        $criteria->compare('field9',$this->field9,true);
        $criteria->compare('field10',$this->field10,true);
        $criteria->compare('field11',$this->field11,true);
        $criteria->compare('field12',$this->field12,true);
        $criteria->compare('field13',$this->field13,true);
        $criteria->compare('field14',$this->field14);

        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
        ));
    }

    /**
     * Config for attribute widgets (ycm module)
     *
     * @return array
     */
    public function attributeWidgets()
    {
        return array(
            array('field0','chosen'),
            array('field1','chosenMultiple'),
            array('field2','dropDown'),
            array('field3','radioButton'),
            array('field4','textField'),
            array('field5','password'),
            array('field6','textArea'),
            array('field7','wysiwyg'),
            array('field8','image'),
            array('field9','file'),
            array('field10','date'),
            array('field11','time'),
            array('field12','datetime'),
            array('field13','disabled'),
            array('field14','boolean'),
        );
    }

    /**
     * Select choices for field0 (ycm module)
     *
     * @return array
     */
    public function field0Choices()
    {
        return array(
            '1'=>'First',
            '2'=>'Second',
            '3'=>'Third',
        );
    }

    /**
     * Select choices for field1 (ycm module)
     *
     * @return array
     */
    public function field1Choices()
    {
        return array(
            '1'=>'First',
            '2'=>'Second',
            '3'=>'Third',
        );
    }

    /**
     * Select choices for field2 (ycm module)
     *
     * @return array
     */
    public function field2Choices()
    {
        return array(
            '1'=>'First',
            '2'=>'Second',
            '3'=>'Third',
        );
    }

    /**
     * Select choices for field3 (ycm module)
     *
     * @return array
     */
    public function field3Choices()
    {
        return array(
            '1'=>'First',
            '2'=>'Second',
            '3'=>'Third',
        );
    }

    /**
     * Config for TbGridView class (ycm module)
     *
     * @return array
     */
    public function adminSearch()
    {
        return array(
            'columns'=>array(
                'field4',
                'id',
                array(
                    'name'=>'field0',
                    'value'=>'$data->field0',
                    'filter'=>Sample::model()->field0Choices(),
                ),
                array(
                    'name'=>'field3',
                    'value'=>'$data->field3',
                    'filter'=>Sample::model()->field3Choices(),
                ),
                array(
                    'name'=>'field14',
                    'value'=>'$data->field14==1 ? CHtml::encode("Yes") : CHtml::encode("No")',
                    'filter'=>array(1=>'Yes',0=>'No'),
                ),
                array(
                    'name' => 'field12',
                    'value' => 'date("d.m.Y H:i:s",strtotime($data->field12))',
                ),
            ),
        );
    }
}

Go to: http://your.domain.com/ycm

One to many relationship (HAS_MANY)

Create tables:

CREATE TABLE `department`
(
  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(128) NOT NULL,
  `description` TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `blog`
(
  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `department_id` INTEGER DEFAULT NULL,
  `title` VARCHAR(128) NOT NULL,
  `content` TEXT NOT NULL,
  CONSTRAINT `FK_department` FOREIGN KEY (`department_id`) REFERENCES `department` (`id`) ON DELETE SET NULL ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Create Department model:

<?php

/**
 * This is the model class for table "department".
 *
 * The followings are the available columns in table 'department':
 * @property integer $id
 * @property string $name
 * @property string $description
 *
 * The followings are the available model relations:
 * @property Blog[] $blogs
 */
class Department extends CActiveRecord
{
    /**
     * Admin variables (ycm module)
     */
    public $adminNames=array('Blog departments','blog department','blog departments'); // admin interface, singular, plural

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Department the static model class
     */
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'department';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('name', 'required'),
            array('name', 'length', 'max'=>128),
            array('description', 'safe'),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('id, name, description', 'safe', 'on'=>'search'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'blogs' => array(self::HAS_MANY, 'Blog', 'department_id'),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'id' => 'ID',
            'name' => 'Name',
            'description' => 'Description',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria=new CDbCriteria;

        $criteria->compare('id',$this->id);
        $criteria->compare('name',$this->name,true);
        $criteria->compare('description',$this->description,true);

        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
        ));
    }

    /**
     * Config for attribute widgets (ycm module)
     *
     * @return array
     */
    public function attributeWidgets()
    {
        return array(
            array('description','wysiwyg'),
        );
    }

    /**
     * Config for TbGridView class (ycm module)
     *
     * @return array
     */
    public function adminSearch()
    {
        return array(
            'columns'=>array(
                'id',
                'name',
            ),
        );
    }
}

Create Blog model:

<?php

/**
 * This is the model class for table "blog".
 *
 * The followings are the available columns in table 'blog':
 * @property integer $id
 * @property integer $department_id
 * @property string $title
 * @property string $content
 *
 * The followings are the available model relations:
 * @property Department $department
 */
class Blog extends CActiveRecord
{
    /**
     * Admin variables (ycm module)
     */
    public $adminNames=array('Blog posts','blog post','blog posts'); // admin interface, singular, plural
    public $downloadExcel=true; // Download Excel
    public $downloadMsCsv=true; // Download MS CSV
    public $downloadCsv=true; // Download CSV

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Blog the static model class
     */
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'blog';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('title, content', 'required'),
            array('department_id', 'numerical', 'integerOnly'=>true),
            array('title', 'length', 'max'=>128),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('id, department_id, title, content', 'safe', 'on'=>'search'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'department' => array(self::BELONGS_TO, 'Department', 'department_id'),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'id' => 'ID',
            'department_id' => 'Department',
            'title' => 'Title',
            'content' => 'Content',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria=new CDbCriteria;

        $criteria->compare('id',$this->id);
        $criteria->compare('department_id',$this->department_id);
        $criteria->compare('title',$this->title,true);
        $criteria->compare('content',$this->content,true);

        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
            'pagination'=>array(
                'pageSize'=>20,
            ),
        ));
    }

    /**
     * Config for attribute widgets (ycm module)
     *
     * @return array
     */
    public function attributeWidgets()
    {
        return array(
            array('department_id','chosen'),
            array('content','wysiwyg'),
        );
    }

    /**
     * Select choices for department_id (ycm module)
     *
     * @return array
     */
    public function department_idChoices()
    {
        return CHtml::listData(Department::model()->findAll(), 'id', 'name');
    }

    /**
     * Config for TbGridView class (ycm module)
     *
     * @return array
     */
    public function adminSearch()
    {
        return array(
            'columns'=>array(
                'id',
                'title',
                array(
                    'name'=>'department_id',
                    'value'=>'($data->department) ? $data->department->name : "No department"',
                    'filter'=>$this->department_idChoices(),
                ),
            ),
        );
    }
}

Go to: http://your.domain.com/ycm

Many to many relationship (MANY_MANY)

Create tables:

CREATE TABLE `post`
(
  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `title` VARCHAR(128) NOT NULL,
  `content` TEXT NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `category`
(
  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(128) NOT NULL,
  `description` TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `post_category`
(
  `post_id` INTEGER NOT NULL,
  `category_id` INTEGER NOT NULL,
  PRIMARY KEY (`post_id`,`category_id`),
  CONSTRAINT `FK_post_category` FOREIGN KEY (`post_id`) REFERENCES `post` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT,
  CONSTRAINT `FK_category_post` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Create Post model:

<?php

/**
 * This is the model class for table "post".
 *
 * The followings are the available columns in table 'post':
 * @property integer $id
 * @property string $title
 * @property string $content
 *
 * The followings are the available model relations:
 * @property Category[] $categories
 * @property PostCategory[] $category
 */
class Post extends CActiveRecord
{
    /**
     * Admin variables (ycm module)
     */
    public $adminNames=array('Posts','post','posts'); // admin interface, singular, plural

    /**
     * Categories id array
     *
     * @var array
     */
    public $assignedCategories;

    /**
     * Populate categories id array after find.
     */
    public function afterFind() {
        if (!$this->isNewRecord) {
            $this->assignedCategories=CHtml::listData($this->category,'category_id','category_id');
        }
    }

    /**
     * Update categories after save.
     */
    public function afterSave() {
        if (!$this->isNewRecord) {
            // delete all categories from Post
            $criteria=new CDbCriteria;
            $criteria->condition='post_id=:post_id';
            $criteria->params=array(':post_id'=>$this->id);
            PostCategory::model()->deleteAll($criteria);
        }
        // add selected categories to Post
        if(!empty($this->assignedCategories)) {
            foreach($this->assignedCategories as $category_id) {
                $postCategory=new PostCategory;
                $postCategory->post_id=$this->id;
                $postCategory->category_id=$category_id;
                $postCategory->save(false);
            }
        }
    }

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Post the static model class
     */
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'post';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('title, content', 'required'),
            array('title', 'length', 'max'=>128),
            array('assignedCategories', 'safe'),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('id, title, content, assignedCategories', 'safe', 'on'=>'search'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'categories'=>array(self::MANY_MANY,'Category','post_category(post_id,category_id)'),
            'category'=>array(self::HAS_MANY,'PostCategory','post_id'),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'id' => 'ID',
            'assignedCategories' => 'Categories',
            'title' => 'Title',
            'content' => 'Content',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria=new CDbCriteria;

        $criteria->compare('id',$this->id);
        $criteria->compare('title',$this->title,true);
        $criteria->compare('content',$this->content,true);

        $criteria->compare('category_id',$this->assignedCategories);
        $criteria->with=array('category');
        $criteria->together=true;

        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
            'pagination'=>array(
                'pageSize'=>20,
            ),
        ));
    }

    /**
     * @return string Category names separated with a comma.
     */
    public function getRelatedCategoryNames()
    {
        $out=CHtml::listData($this->categories,'id','name');
        return implode(', ', $out);
    }

    /**
     * Config for attribute widgets (ycm module)
     *
     * @return array
     */
    public function attributeWidgets()
    {
        return array(
            array('assignedCategories','chosenMultiple'),
            array('content','wysiwyg'),
        );
    }

    /**
     * Select choices for assignedCategories (ycm module)
     *
     * @return array
     */
    public function assignedCategoriesChoices()
    {
        return CHtml::listData(Category::model()->findAll(array('order'=>'name ASC')), 'id', 'name');
    }

    /**
     * Config for TbGridView class (ycm module)
     *
     * @return array
     */
    public function adminSearch()
    {
        return array(
            'columns'=>array(
                'id',
                'title',
                array(
                    'name'=>'assignedCategories',
                    'value'=>'$data->relatedCategoryNames',
                    'filter'=>$this->assignedCategoriesChoices(),
                    'type'=>'html',
                ),
            ),
        );
    }
}

Create Category model:

<?php

/**
 * This is the model class for table "category".
 *
 * The followings are the available columns in table 'category':
 * @property integer $id
 * @property string $name
 * @property string $description
 *
 * The followings are the available model relations:
 * @property Post[] $posts
 * @property Post[] $postCount
 */
class Category extends CActiveRecord
{
    /**
     * Admin variables (ycm module)
     */
    public $adminNames=array('Post categories','post category','post categories'); // admin interface, singular, plural

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Category the static model class
     */
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'category';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('name', 'required'),
            array('name', 'length', 'max'=>128),
            array('description', 'safe'),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('id, name, description', 'safe', 'on'=>'search'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'posts' => array(self::MANY_MANY, 'Post', 'post_category(category_id, post_id)'),
            'postCount' => array(self::STAT, 'Post', 'post_category(category_id, post_id)'),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'id' => 'ID',
            'name' => 'Name',
            'description' => 'Description',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria=new CDbCriteria;

        $criteria->compare('id',$this->id);
        $criteria->compare('name',$this->name,true);
        $criteria->compare('description',$this->description,true);

        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
            'pagination'=>array(
                'pageSize'=>20,
            ),
        ));
    }

    /**
     * Config for attribute widgets (ycm module)
     *
     * @return array
     */
    public function attributeWidgets()
    {
        return array(
            array('description','wysiwyg'),
        );
    }

    /**
     * Config for TbGridView class (ycm module)
     *
     * @return array
     */
    public function adminSearch()
    {
        return array(
            'columns'=>array(
                'id',
                'name',
            ),
        );
    }
}

Create PostCategory model:

<?php

/**
 * This is the model class for table "post_category".
 *
 * The followings are the available columns in table 'post_category':
 * @property integer $post_id
 * @property integer $category_id
 */
class PostCategory extends CActiveRecord
{
    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return PostCategory the static model class
     */
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'post_category';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('post_id, category_id', 'required'),
            array('post_id, category_id', 'numerical', 'integerOnly'=>true),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('post_id, category_id', 'safe', 'on'=>'search'),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'post_id' => 'Post',
            'category_id' => 'Category',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria=new CDbCriteria;

        $criteria->compare('post_id',$this->post_id);
        $criteria->compare('category_id',$this->category_id);

        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
            'pagination'=>array(
                'pageSize'=>20,
            ),
        ));
    }
}

Go to: http://your.domain.com/ycm

License

yii-ycm is free and unencumbered public domain software.