xcrudcontroller 7

A base class to quickly build customized CRUD interfaces.


Written in PHP by 1 contributor


Need Support?

we offer maintenance, support and development services for all our open source projects.

Contact Us


A base class to quickly build customized CRUD interfaces.


  • Create, list, view, edit and delete actions. Follow DRY and don't repeat the same CRUD logic in all your controllers.
  • Powerful filter pattern. Use a dedicated filter form in your listing to build convenient search interfaces.
  • Helpers for URL creation. Take the user back to the same listing page after editing/viewing a record.


1 A simple controller

To get started you only have to supply the name of the ActiveRecord class that you want to build a CRUD for:

class UserController extends XCrudController
    public $modelName = 'User';

2 Create view files

You have to supply the list, edit and detail views.

Note: The markup is very reduced. In a real life project you'd of course style these elements apropriately. You could also start from the CRUD templates as generated from Gii. But you have to rearrange and modify them a little.

2.1 List view

The list view contains the filter form and renders the partial view for the actual items via _items.


<?php $model = $this->filterModel; ?>

    <h2>Search users</h2>
    <?php echo CHtml::beginForm(array('list'),'get'); ?>
            <?php echo CHtml::activeTextField($model, 'username'); ?>
            <?php echo CHtml::activeTextField($model, 'email'); ?>
        <?php echo CHtml::submitButton('Search'); ?>
    <?php echo CHtml::endForm(); ?>

<?php $this->renderPartial('_items'); ?>

Note: In real life your filter form is usually offering way more search options. You would better implement this through a dedicated filter form. See below for details.


<?php $this->widget('zii.widgets.grid.CGridView',array(
    'dataProvider' => $this->filterModel->search(),
    'columns' => array(
            'name'  => 'Username',
            'value' => 'CHtml::link($data->username, Yii::app()->controller->createItemUrl($data, "view"))',
            'type'  => 'raw',
            'template'=>'{update} {delete}',
)); ?>

Notice how the links to view and edit an item are built through createItemUrl(). This adds the current list page URL as URL parameter so that it's very easy to link back to this search result page.

2.2 Create/edit form


<?php $model = $this->model; ?>

<h1><?php echo $model->isNewRecord ? 'Add new user' : 'Edit user' ?></h1>

<?php $form=$this->beginWidget('CActiveForm',array(
    'id' => 'user-form',
        <?php echo $form->label($model, 'username'); ?>
        <?php echo $form->textField($model, 'username'); ?>
        <?php echo $form->error($model, 'username'); ?>
        <?php echo $form->label($model, 'email'); ?>
        <?php echo $form->textField($model, 'email'); ?>
        <?php echo $form->error($model, 'email'); ?>
        <?php echo $form->label($model, 'password'); ?>
        <?php echo $form->textField($model, 'password'); ?>
        <?php echo $form->error($model, 'password'); ?>

    <?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save') ?>
    <?php echo CHtml::link('Cancel', $this->returnUrl); ?>

<?php $this->endWidget(); ?>

Note: The form name must be strtolower($this->modelName).'-form' if you want to use AJAX validation with CActiveForm.

2.3 Detail view


<?php $model = $this->model; ?>

    <?php $this->widget('zii.widgets.CDetailView', array(
        'data' => $model,
    )); ?>

<?php echo CHtml::link('Back', $this->returnUrl); ?>



As you've seen above, 4 view files must be provided for the controller:

  • list: Contains the filter form and renders the _items partial
  • _items: Renders the items (e.g. with CListView/CGridView)
  • form: Renders the create/edit form
  • detail: Renders the detail view

The view names can be configured in $listView, $listPartial, $formView and $detailView properties.

The views use a pull mechanism to fetch their data:

  • $this->model: Returns the current model for form and detail view
  • $this->filterModel: Returns the filter model for list and _items view. The data provider for the items is available through the search() method.
  • $this->returnUrl: Contains the URL which takes the user back to the search result page. This is useful on edit and view pages.

After a record was created or updated a flash message with the key $modelName-created or $modelName-updated is set respectively. You can use this to show a success message in the view which you show after saving a record.

Note: You can control, which page you want to show after you created a new record. By default this will be the list page (with filters reset). You can also show the detail view of the new record or stay on the edit page, if you want. Therefore you have to create the "Add" link like this:

CHtml::link('Add user', array('edit', $this->returnVar=>'view'));

Instead of 'view' you can also use 'edit' to redirect to the edit form of the newly created record.


You can configure several scenarios which are set on the $model or $filterModel for specific actions:

  • $createScenario : Set when creating a new record. Default is create.
  • $updateScenario : Set when updating a record. Default is update.
  • $filterScenario : Set on the filter model when assigning search parameters. Default is filter.

Other options

If you don't want to provide all actions, you can disable some of them through $crudActions. By default this is `array('edit', 'list', 'view', 'delete').

The name of the URL parameter for the return URL is set through $returnVar and defaults to returnUrl.

Advanced tricks

Using a filter model

In the simplest case a filter model is an ActiveRecord as created by Gii. But if you want to keep your code cleaner, i'd recommend to use a separate model file for all your filter concerns. This has the advantage that you don't clutter up your ActiveRecords with search related code anymore and can focus on the search logic here:

class UserFilter extends CFormModel
    public $username;
    public $email;

    // You can add many more attributes here, to offer convenient search options
    public $ageMin;
    public $ageMax;

    // All these attributes must be declared as 'safe'
    public function rules()
        return array(
            array('username,email', 'safe'),

    // As usual, build the search criteria from the current attribute values.
    // In real life you may even use a dedicated search engine like Solr -
    // as long as it returns a valid data provider everything will still work.
    // All attribute values are translated into query conditions.
    public function search()
        $criteria = new CDbCriteria;

            $criteria->compare('username', $this->name);

            $criteria->compare('email', $this->city);

            $criteria->addCondition('birthday < SUBDATE(NOW(), INTERVAL '.(int)$this->ageMin.' YEAR)');

            $criteria->addCondition('birthday > SUBDATE(NOW(), INTERVAL '.(int)$this->ageMax.' YEAR)');

        return new CActiveDataProvider('User', array(
            'criteria' => $criteria,

            // Add more options as required, e.g. for sorting

In the controller you have to configure this model in $filterModelName:

class UserController extends XCrudController
    public $modelName = 'User';
    public $filterMlodelName = 'UserFilter';

How to get nicer URLs for your search results

The URL parameters to a search result page look like this:


This does not look very nice. It would be much better to have easier to read search parameters, just like Google or other search engines do it:


It's very easy to achieve this. You have to override the assignFilterModelAttributes() method in your controller like this:

    protected function assignFilterModelAttributes($model)
        $model->attributes = $_GET;

It is safe to do this in this case: We only have the search form parameters in $_GET, plus maybe the pagination and sorting options. But as long as they don't interfere with your search model attributes everything is still fine.

But you also have to change the filter form a little because by default Yii will create form element names like User[username] whereas we want them to be only username now:

    <?php echo CHtml::beginForm(array('list'),'get'); ?>
            <?php echo CHtml::textField('username', $model->username); ?>

43 other PHP projects

phpwkhtmltopdfPHP 716

A slim PHP wrapper around wkhtmltopdf with an easy to use and clean OOP interface

php-pdftkPHP 213

A PDF conversion and form utility based on pdftk

yii2-localeurlsPHP 189

Automatic locale/language management for URLs

YiiRedisPHP 131

A set of wrappers for different data types in redis

yiipasswordPHP 81

Password strategies for Yii

yii2-dockerizedPHP 64

A template for docker based Yii 2 applications

YiiSolrPHP 50

A wrapper for the pecl solr library that provides common Yii constructs, such as models, data providers etc

php-shellcommandPHP 48

A simple object oriented interface to execute shell commands in PHP

Yii-Docs-GeneratorPHP 47

Generates HTML documentation for Yii applications

YiiGitPHP 36

A git wrapper for Yii, allows access to all git commands programatically

YiiElasticSearchPHP 32

Elastic Search client for Yii

YiiCurlPHP 30

A curl library for Yii

YiiStateMachinePHP 28

A state machine behavior for Yii

yii2-streamlogPHP 19

A Yii 2 log target for streams in URL format

oauth2yiiPHP 18

An OAuth2 client / server extension for the Yii framework

packagecompressorPHP 16

A Javascript/CSS compressor based on Yii's package system

restyiiPHP 16

A RESTful extension for Yii.

localeurlsPHP 12

Automatic locale/language management for URLs

php-excel-readerPHP 12

It reads the binary format of XLS files directly and can return values and formats from any cell. This project is the fork of http://code.google.com/p/php-excel-reader/ that, apparently, is no longer maintained.

pdfablePHP 10

A Yii extension to create PDFs with PHPWkHtmlToPdf/wkhtmltopdf

yii-api-vimPHP 8

Yii API manual plugin for VIM

yii2-excel-messagePHP 7

Translate messages via Excel files

yii2-bs3activeformPHP 7

A Bootstrap 3 enhanced ActiveForm for Yii 2

handlebarsphpPHP 6

Transpiles handlebars templates into native PHP templates

Yii-Package-ManagerPHP 6

A package manager for Yii

php-tmpfilePHP 6

A convenience class for temporary files

yii2-apidoc-vimPHP 5

Yii2 apidoc as Vim helpfiles

php-orientdbPHP 5

A fast PHP driver for the OrientDB binary protocol.

translatablePHP 4

Transparent attribute translation for ActiveRecords

YiiUsersPHP 4

User management for Yii

Yii-Resource-ManagerPHP 3

Helpers to allow Yii to interact with resources (files) of different types

flushablePHP 3

Yii dependency that allows to flush records from the cache

bs3activeformPHP 2

A lightweight utility to render Bootstrap 3 forms in Yii

YiiEmailerPHP 2

Emailing functions for Yii

AccessRestrictablePHP 2

A Yii ActiveRecordBehavior that automatically applies conditions for access restriction to every query.

YiiLinkablePHP 1

A simple extension for Yii allowing easy and consistent access to model URLs and appropriate anchor text.

defaultpersisterPHP 1

Yii extension to save and restore model values in user session.

hybridauthmanagerPHP 1

An AuthManager for Yii that stores the hierarchy in a flat PHP file and the assignments in DB

YiiYaaPHP 1

YAA is an additional abstraction layer for Yii that aggregates a number of child models into a clean single model that is easy to cache


Work with PHP files in Active Record way


simple useless twitter client


An alternative Yii2 application template for purists


Yii extension to create URLs that allow to return to a page by storing its GET Parameters on a stack.