Yii 2.0 review

Let's talk about PHP in general first

PHP is cool!

  • It is a good choice for web development and more.
  • Used more than others (81%!).
  • It's a pleasure to work with if you're using a good framework.

PHP is getting better

  • Performance.
  • Syntax.
  • Password hashing API.
  • Generators.
  • Built-in webserver.
  • And much more...

There are alternative compatible implementations

  • PSR
  • Composer
  • Some stable, supported and backwards compatible frameworks.

And that's great!

Now about sad trends…


PHP code is getting too complex in pursuit of unlimited flexibility.

Many believe that this is the only right way.

All problems in computer science can be solved by another level of indirection… except for the problem of too many layers of indirection

David Wheeler

But what for?

What if one needs to change one DBMS to another? What if one needs to exchange a base component to another one? What if something goes wrong...

So we end up with

  • Misunderstanding, pattern-orientation. Focus on how it's done instead of why it's done.
  • Easier to test, but harder to write code, debug and learn.
  • Layers. Many layers. In your tests you can cheat and hack once. API is used all the time.
  • There's a price for flexibility — complexity. Noone actually needs ultimate flexibility.
  • Can't delegate routine tasks to less qualified developers without spending significant time on educating them.

What should we do then?

Practice-oriented frameworks

  • No unnecessary complexity.
  • Easier to learn.
  • Less magic.
  • Less layers.
  • Less configuration.
  • Simple and usable API.
practice-oriented framework

Framework myths

  • Reinvented the wheel = bad.
  • Has DI container and all the cool patterns = good.
  • Got feature X first = better than others.
  • Decoupled = always better.
  • Lacks feature X = bad.

Really important

  • Easy to learn.
  • Easy to debug and fix errors.
  • Should not be an obstacle for your workflow or using 3rd-party code.
  • Friendly and acitve community.
  • Backwards compatibility and stability.
  • Easy to configure and extend.
  • You should like it ;)

What is Yii 2.0?

  • PHP 5.4.
  • Well balanced.
  • Will be stable and supported.
  • Licensed under BSD.
  • Covers most of web-development tasks.
  • REST API framework.
  • Debugging tools.
  • Code generation.
  • Convenient way to work with data.
  • Good docs and friendly community.
And more projects

One of the fastest PHP-frameworks out there*.

*Except PECL and microframeworks

99.7% HHVM-compatible

Installing basic app template

php composer.phar create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic
cd basic
php -S localhost:80




validation and forms


remembers everything

can search logs

useful errros

useful fatals

All errors are ErrorException

try {
} catch (\yii\base\ErrorException $e) {
    // okay :(

code generator

generating controller




Want more?

advanced app template

  • Works with data.
  • Authorization, authentication, password restore.
  • Divided into frontend/backend/common/console + environments.


Official extensions

  • twig, smarty
  • swiftmailer
  • sphinx, elasticsearch
  • redis, mongodb
  • bootstrap, jui
  • imagine
  • gii, debug
  • codeception, faker
  • authclient
  • apidoc

Extensions are easy to install:

php composer.phar require --prefer-dist yiisoft/yii2-mongodb "*"

that's it. You can use it now.

More than 250 unofficial extensions

Working with databases

Consistent syntax for everything.

$query = new \yii\db\Query;
$query->select('id, name')
  ->orderBy('id DESC')

$command = $query->createCommand();
echo $command->sql;
$rows = $command->queryAll();

$users = User::model()->find()
  ->orderBy('id DESC')

Model and Query are separated

$finder = Post::find()->where(['a' => 10]);
$finder2 = clone $finder;
$finder2->addWhere(['b' => 1]);

$model = $finder->one();
$model2 = $finder2->one();

// shortcuts
$post = Post::findOne(10); // pk = 10
$post = Post::findOne(['a' => 10, 'b' => 1]); // where a = 10 and b = 1

AR relations

has one, has many. Declared as methods.

class User extends \yii\db\ActiveRecord
  public function getPosts()
    return $this->hasMany('Post', ['user_id' => 'id']);

  public function getActivePosts()
    return $this->hasMany('Post', ['user_id' => 'id'])
      ->where(['status' => Post::STATUS_ACTIVE]);

$posts = $user->getPosts()->limit(10)->all();
$postCount = $user->getPosts()->count();

Many to many

class Post extends \yii\db\ActiveRecord
    public function getTags()
        return $this->hasMany(Tag::className(), ['id' => 'tag_id'])
            ->viaTable('post_tag', ['post_id' => 'id']);

AR asArray

$posts = Post::find()->limit(10)->asArray()->all();
foreach($posts as $post) {
  echo $post['title']."\n";

dirty attributes and link

When calling save() only changed attributes are saved.

There are link and unlink to manage relations.

$comment = new Comment();
$comment->text = 'Hello, Yii!';

// INSERT INTO post_comment ...
$post->link('comments', $comment);

// DELETE FROM post_comment ...
$post->unlink('comments', $comment);

Getting data in batches

// 10 records at a time
foreach (Customer::find()->batch(10) as $customers) {
    // $customers — array of 10 or less records
// 10 records at a time, iterating one by one
foreach (Customer::find()->each(10) as $customer) {
    // $customer — Customer object
// eager loading
foreach (Customer::find()->with('orders')->each() as $customer) {


  • AR works with noSQL including relations
  • Eager and lazy data loading

Our priorities

No overcomplication

There's not a single thing like setMyCoolFactoryDependencyInjectionContainer() in Yii

Good balance

Well-thought API, 80% of use cases, sensible defaults, ability to extend.


  • API is documented at the time of creating code.
  • Main docs will be translated and kept up to date (1.1 got its guide translated to 16 languages).
  • Planned books: Mark Safronov, Larry Ullman, community cookbook.


  • We love tools (like apidoc) and IDEs
  • We care about performance
  • We're using Yii ourselves

We're watching trends

REST API framework


  • controller action — API endpoint
  • controller — endpoint group for one resource type
  • model — resource


namespace app\controllers;

use yii\rest\ActiveController;

class UserController extends ActiveController
    public $modelClass = 'app\models\User';

    public function actionSearch($keyword) // !!!
        $result = SearchService::search($keyword);
        return $result;
'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
            'class' => 'yii\rest\UrlRule',
            'controller' => 'user'
  • GET /users: paginated users;
  • HEAD /users: headers ↑;
  • POST /users: new user;
  • GET /users/123: info of user 123;
  • HEAD /users/123: headers ↑;
  • PATCH /users/123 and PUT /users/123: update user 123;
  • DELETE /users/123: delete user 123;
  • OPTIONS /users: which HTTP-verbs could be used for /users;
  • OPTIONS /users/123: which HTTP-verbs could be used for /users/123.

Trying API call

curl -i -H "Accept:application/json" "http://localhost/users"

    HTTP/1.1 200 OK
    Date: Sun, 02 Mar 2014 05:31:43 GMT
    Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
    X-Powered-By: PHP/5.4.20
    X-Pagination-Total-Count: 1000
    X-Pagination-Page-Count: 50
    X-Pagination-Current-Page: 1
    X-Pagination-Per-Page: 20
    Link: <http://localhost/users?page=1>; rel=self,
        <http://localhost/users?page=2>; rel=next,
        <http://localhost/users?page=50>; rel=last
    Transfer-Encoding: chunked
    Content-Type: application/json; charset=UTF-8

            "id": 1,
            "id": 2,


  • Quick prototyping
  • JSON/XML or your own format
  • Versioning
  • Confiugrable serialization. You can choose which fields to expose
  • Collections, fields and pagination, validation

More features

  • REST + fallback
  • Authentication (HTTP basic, URL token, OAuth2), authorization (regular one: access filter and RBAC)
  • HATEOAS (Hypermedia as the Engine of Application State)
  • HTTP-cache
  • Rate limiting: N requests per second per user

Docs: http://www.yiiframework.com/doc-2.0/guide-rest.html

1.1 → 2.0?

Use 2.0 with care

1.1 is stable and supported till at least 2016

How to help us: