Design, CG Graphics & Inspiration

Meet Yii2 Framework

Introduction

The other day, an event has occurred; and I believe, many people were waiting for it, including me. The authors of Yii Framework have set out a preview version.

A day later, a teaching material, it produced a strange impression on me and after the weekend spent on studying Yii2 code, I decided to write my own version. I hope it won’t be worse.

Start

The second version is radically different from the first one. A short list:

– The kernel has been separated from adornments. Many classes have been excluded. Some of them will be moved to separate officially supported extensions. A part of classes have been excluded as not necessary.

– Basic CComponent has been divided into Object and Component. The first one carries out the work of getters and setters, the other one expends the first one, adding events and behaviors.

– Connection of events and behaviors has been modified. Subscribe to an event

$post->on('update', function($event) {
    // send email notification
});

Setting up of the component

$component = \Yii::createObject(array(
  'class' => '\app\components\GoogleMap',
  'apiKey' => 'xyz',
  // Add event
  'on eventName' => array('Event', 'run'),
  // Add behavior
  'as behaviorName' => array(/* Behavior config */),
));

– A new View class has been added, and now we have a real MVC framework.

<?php
use yii\helpers\base\Html;
/**
 * Note that $this is not the controller.
 * To get to the controller you can via $this->context
 * @var yii\base\View $this
 */
$this->title = 'Hello world';
?>
<h1><?php echo Html::encode($this->title); ?></h1>
<p class="lead">Hello world!</p>

*View can be set up for every controller, or a basic one can be used for an application.

– A controller render () does not display anything. It returns data

public function actionIndex()
{
    echo $this->render('index');
}

– Two events available for subscription have appeared in the controller: beforeAction, afterAction

public function init()
{
  $this->on('beforeAction', function($event) {
    // cancel action
    $event->isValid = false;
  });
}

– The controller filters (CFilter) are removed, now everything is done via behaviors.

public function behaviors()
{
  return array(
    'AccessControl' => array(
      'class' => '\yii\web\AccessControl',
      'rules' =>array(/* without changes */),
    ),
  );
}

– A great helper has appeared in the controller – populate method

public function actionLogin()
{
  $model = new LoginForm();
  if ($this->populate($_POST, $model) && $model->login()) {
    Yii::$app->response->redirect(array('site/index'));
  }

  echo $this->render('login', array(
    'model' => $model,
  ));
}

– Several more static helper classes have been added: ArrayHelper, StringHelper, SecurityHelper. Now all the helpers can be overlapped via LSB. Hurrah, – I exclaimed, as many times before I needed to overlap Html.

ActiveForm widget has also been rewritten, and it will probably replace CForm form-builder. Now each form field may be presented as an ActiveField object, which creates ActiveForm.

$form = $this->beginWidget('yii\widgets\ActiveForm', array(
  'options' => array('class' => 'form-horizontal')
));

  echo $form->field($model, 'username')->textInput(); 
  echo $form->field($model, 'password')->passwordInput(); 
  echo $form->field($model, 'rememberMe')->checkbox();

  echo Html::tag('div', Html::submitButton('Login', null, null, array('class' => 'btn btn-primary')), array(
    'class' => 'form-actions'
   ));

$this->endWidget();

* Attention: in Html::tag($tag, $content, $options) — order of the parameters has been changed!

ActiveRecord

“ActiveRecord has been left mostly untouched”

– was written in the previous article. That’s very true – it hasn’t been touched.

We’ve just written quite different ActiveRecord.

— Let’s forget about model ()

CDbCriteria has been removed. But don’t worry, now, it became easier to work with the base. ActiveQuery has appeared (that is a combination of CActiveFinder and CDbCriteria).

// we receive an ActiveQuery instance
$query = Post::find();

// all posts
$posts = $query->all();

// looking for all the posts with a condition
$posts = $query
    ->where(array('status' => Post::DRAFT))
    ->orderBy('time')
    ->all();

// looking for a post 
$post = $query
   ->where(array('id' => 10, 'status' => Post::READ))
   ->one();

// or easier: "where" condition can be transmitted directly to the factory method
$post = Post::find(array('id' => 10, 'status' => Post::READ));

// having transmitted to the factory method not a massive, but a number equivalent to the primary key search 
$post = Post::find(10)
   ->where(array('status' => Post::READ))
   ->one();

// we index the result to a necessary attribute
$posts = $query->indexBy('title')->all();

// the result as an array
$posts = $query->asArray()->all();

– All the general methods are static now: getDb, tableName, find*, saveAll*, primaryKey. Advantage is obvious.

– Connections. Now, the connections are determined by addition of the getters.

class Post extends ActiveRecord
{
    public function getCreator()
    {
        return $this->hasOne('User', array('id' => 'user_id'));
    }
    public function getComments()
    {
        return $this->hasMany('Comment', array('post_id' => 'id'));
    }
    public function getTrustComments($isTrust = true)
    {
        return $this->hasMany('Comment', array('post_id' => 'id'))
            ->where('status = :status', array(
                     ':status' => $isTrust ? self::TRUST : self::UNTRUST,
              ))
            ->orderBy('id');
    }
}

– To simplify the work with connections, they added link () and unlink (), which will set the keys automatically.

– There are named condition groups, but they have a different form. We don’t have CDbCriteria, as well as arrays of conditions any more. Now, these methods (static ones) аdd conditions to Query.

$post = Post::find(1);

$comment = new Comment();
$comment->text = 'Yii Framework is cool!';
$post->link('comments', $comment);

The End

I will draw a line here. The article is big, containing a lot of code, but I hope you’ve got through and read it to the end.

Talk to you later

  • Veaceslav M.,
  • June 11, 2013

SHARE THIS POST

Subscribe for the hottest posts

Subscribe to our email newsletter for useful tips and freebies.

  • Szymon Dudziak

    Looks good. But I have one sugesstion.

    Instead of ‘one’ method for searching n records:

    // having transmitted to the factory method not a massive, but a number equivalent to the primary key search
    $post = Post::find(10)
    ->where(array(‘status’ => Post::READ))
    ->one();

    more naturally could be ‘limit’ (or something similar) :

    $post = Post::find()
    ->where(array(‘status’ => Post::READ))
    ->limit(10);

  • Szymon Dudziak

    Looks good. But I have one sugesstion.

    Instead of ‘one’ method for searching n records:

    // having transmitted to the factory method not a massive, but a number equivalent to the primary key search
    $post = Post::find(10)
    ->where(array(‘status’ => Post::READ))
    ->one();

    more naturally could be ‘limit’ (or something similar) :

    $post = Post::find()
    ->where(array(‘status’ => Post::READ))
    ->limit(10);