Yii PHP Framework 1.1.8 is released

Jun 26, 2011

We are very pleased to announce the immediate availability of Yii Framework version 1.1.8. In this release, we included more than 80 new features, enhancements and bug fixes.

For the complete list of changes in this release, please see the change log and important feature additions. And if you plan to upgrade from an older version to 1.1.8, refer to the upgrade instructions.

In the following, we briefly introduce some of the most exciting new features in this release. Thank you for your support!

Custom URL rule classes

In order to handle URLs that are more complicated than CUrlRule can handle (e.g. part of a URL depends on some data stored in a DB table), one can write custom URL rule classes and plug them into CUrlManager. Below we show the URL rule configuration that uses a custom URL rule class:

array(
    // a standard rule mapping '/login' to 'site/login', and so on
    '<action:(login|logout|about)>' => 'site/<action>',
 
    // a custom rule to handle '/Manufacturer/Model'
    array(
        'class' => 'application.components.CarUrlRule',
        'connectionID' => 'db',
    ),
 
    // a standard rule to handle 'post/update' and so on
    '<controller:\w+>/<action:\w+>' => '<controller>/<action>',
),

The custom URL rule class extends from CBaseUrlRule and can be implemented like the following:

class CarUrlRule extends CBaseUrlRule
{
    public $connectionID = 'db';
 
    public function createUrl($manager,$route,$params,$ampersand)
    {
        if ($route==='car/index')
        {
            if (isset($params['manufacturer'], $params['model']))
                return $params['manufacturer'] . '/' . $params['model'];
            else if (isset($params['manufacturer']))
                return $params['manufacturer'];
        }
        return false;  // this rule does not apply
    }
 
    public function parseUrl($manager,$request,$pathInfo,$rawPathInfo)
    {
        if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches))
        {
            // check $matches[1] and $matches[3] to see
            // if they match a manufacturer and a model in the database
            // If so, set $_GET['manufacturer'] and/or $_GET['model']
            // and return 'car/index'
        }
        return false;  // this rule does not apply
    }
}

Improved class autoloader

Yii provides a class autoloader that can include a class on demand. It can now play more nicely with other 3rd-party autoloaders by allowing them to be in front of or after it in the autoloader chain. Previously, the Yii autoloader must be at the end of the autoloader chain so it was triggered for both Yii core classes and external classes:

// By default autoloader is registered before the Yii autoloader
Yii::registerAutoloader($autoloader);

Now you can avoid it by passing true as a second parameter:

// When second parameter $append is true, autoloader is being added after the Yii autoloader
Yii::registerAutoloader($autoloader, true);

By default, Yii class autoloader relies on PHP include path to work. However, some shared hosting services may not allow setting PHP include path. If you encounter this problem, you can now solve it by using the following bootstrap code for your application:

require('path/to/yii.php');
// disable PHP include path
Yii::$enableIncludePath = false;
Yii::createWebApplication($config)->run();

Sending log messages to destinations in "real time"

Some console commands may run for a long period of time, and they often need to keep some log messages in persistent storage to track the progress. The Yii logging mechanism can now support such "real time" logging. To do so, call the following before the long running code:

// automatically send every new message to available log routes
Yii::getLogger()->autoFlush = 1;
// when sending a message to log routes, also notify them to dump the message
// into the corresponding persistent storage (e.g. DB, email)
Yii::getLogger()->autoDump = true;

Saving counters with AR

CActiveRecord has a new convenient method called saveCounters(). It is very similar to the existing CActiveRecord::updateCounters(). The main difference is that saveCounters() only works with the current AR object while updateCounters() applies to the whole DB table. The following is an example showing their differences:

$post = Post::model()->findByPk(1);
// increment the view count of this post by 1
$post->saveCounters(array('views'=>1));
// equivalent implementation
Post::model()->updateCounters(array('views'=>1), 'id=1');

Generating message files

When using the yiic message command to generate message files, do you often have to delete old message files and replace them with the newly generated ones? You now have an option to force the command to overwrite the old files with the newly generated ones. To do so, in the configuration file used by the command, add a new option: "overwrite" => true.

Creating URLs in console applications

We often use CUrlManager to create versatile URLs in Web applications. Sometimes, console applications also have similar needs. For example, a console command may need to build a sitemap that consists of URLs for a front end Web application. This is now made easier as we can call Yii::app()->createUrl() like we do in a Web application.

Clips got parameters and placeholders

Sometimes a code snippet repeats over and over again but doesn't worth moving into a separate view file. In this case you can use clips that are now accepting parameters which will replace placeholders in the clips:

<?php // defining a clip ?>
<?php $this->beginClip('hello')?>
<p>Hello, {username}!</p>
<?php $this->endClip() ?>
 
<?php // using previously defined clip ?>
<?php $this->renderClip('hello',array(
    '{username}'=>'Qiang',
))?>
<?php $this->renderClip('hello',array(
    '{username}'=>'Alex',
))?>
<?php $this->renderClip('hello',array(
    '{username}'=>'Michael',
))?>

Tags

release