blog

Photo of Graffiti by Bart Christiaanse on Unsplash

Yii 2.0 Public Preview Rundown

by

The Rundown

Yii Framework is getting ever closer to a 2.0 release, with the public preview announced in March now only having 60 open issues (579 closed). There are a lot of changes from Yii 1.1. Let’s take a look at a few of ’em.

Namespaces

Now that PHP 5.3 is required, and being that Yii 2.0 is not trying to be backwards-compatible with Yii 1.1, namespaces are used everywhere. The ‘C’ prefix from framework components has also been dropped as it is no longer needed

use yiihelpersHtml;
echo Html::submitButton('Login', array('class' => 'button'));

Testing

Yii 2.0 integrates with Codeception, described as "PHPUnit on steroids." With Symfony 2, Yii 2, and Zend Framework integration, it looks to have been accepted as an improved testing framework since being released in January 2012. It still integrates with Selenium, and elements can still be matched by name, CSS or XPath.

Requirements Checker

When your app requires a list of PHP extensions or settings, or external libraries to function correctly, it’s often necessary to write some sort of requirements checker. Yii 2 includes one right in the box, ready for your customizations.

$requirements = array(
   array(
      'name' => 'PHP Some Extension',
      'mandatory' => true,
      'condition' => extension_loaded('some_extension'),
      'by' => 'Some application feature',
      'memo' => 'PHP extension "some_extension" required',
   ),
);

Source: framework/yii/requirements/YiiRequirementChecker.php

Events

Yii 2 throws out the "onBeforeNsa"-type event methods in favor of a single on() method.

// attach handler
$component->on($eventName, $handler);
// detach handler
$component->off($eventName, $handler);
// trigger event
$component->trigger('beforeGettingSnowden');

Views

Yii 2 gives some much-needed attention to views by way of implementing an actual View class. In addition, View takes over the roles of the old CClientScript.

Most notably, within a view, $this corresponds to the current view now instead of the controller or widget that is rendering it. $this->context now refers to the controller or widget object.

Yii 2 also works out of the box with Smarty and Twig, if you desire those template engines.

Source: framework/yii/base/View.php

Models

Massive assignment has changed a bit. Instead of doing:

if (isset($_POST['userModel']))
{
   $model->attributes = $_POST['userModel'];
}

… you can just do:

$model->load($_POST);

The key thing here is is that load() will automatically check for an appropriate index within $_POST, defined by the override-able $model->formName().

Source: framework/yii/base/Model.php

Validation

Instead of model rules() specifying which validation rules to use for which attributes on which validation scenario (e.g. "on"=>"createUser"), Yii 2 adds a new method scenarios() to declare which attributes require validation under which scenario (breathe!). This is an optional method; if you have but one validation scenario in your model you need not implement scenarios().

public function scenarios()
{
   return array(
     'createPlayer' => array('email', '!name'),
     'joinGame' => array('gameId'),
   );
}

Marking attributes as safe or unsafe is no longer done as it was in Yii 1; there are no "safe" or "unsafe" validators anymore. Instead, if an attribute is unsafe, you would prefix it with an exclamation point within the scenario.

ActiveRecord

Gone are the relations(), now replaced by getters that return ActiveQuery objects.

class Game extends yiidbActiveRecord
{
   public function getPlayers()
   {
      return $this->hasMany('Player', array('game_id' => 'id'));
   }
}

The relation can thus still be used via $game->players, but now you can customize query conditions on the fly, e.g.:

$winning = $game->getPlayers()->andWhere('winning=1')->all();

In Yii 1, the model() method was used all over the place. This is no more in Yii 2. Instead, you use the much-improved find() method which returns an ActiveQuery instance.

// get all active players
$players = Player::find()
 ->where(array('active'=>1))
 ->orderBy('id')
 ->all();
// get the player whose PK is 1
$firstPlayer = Player::find(1);

And when you want your records as arrays instead of objects, you can just tell ActiveQuery to make it so.

$players = Player::find()->asArray()->all();

Source: framework/yii/db/ActiveRecord.php

Controllers

render() and renderPartial() now no longer send output directly. For me this means one less additional parameter to remember, and more consistency.

Source: framework/yii/base/Controller.php

Onwards!

The more I dig through Yii 2, the more excited I am to use it. I still haven’t converted any Yii 1.x sites to it, but it is certainly worth considering for upcoming Yii Framework projects.

Further reading:
Yii Framework: Upgrading from Yii 1.1.

+ more