
Yii 2.0 beta
We are very pleased to announce the release of the beta version of the PHP framework Yii 2. You can download it from yiiframework.com .
Beta includes hundreds of innovations, changes and fixes from the alpha release .
Next, we will review the most important, but first answer the frequently asked questions.
You can find the full list of changes in CHANGELOG , and below we will describe the most important.
Yii 2 started using PSR-4
to load classes. I.e:
Controller classes must now be located in the namespace specified in
We also returned support for the grouping of controllers in the subdirectory, which was in 1.1.
Ease of use is one of the highest priorities of our team. That is why we pay a lot of attention to naming and to ensure that the code works fine with various IDEs. All this allows you to make everyday development more enjoyable.
We switched to PSR-1 and PSR-2 code styles and got support for many IDEs, automated code checking and
automatic formatting .
One of the most significant changes is that the session does not start until it is really needed. This allows applications not to waste extra resources.
If you use Markdown in your projects, you will notice that the conversion speed to HTML has increased significantly. This became possible after Carsten Brandt (cebe), after reviewing existing solutions, wrote his library from scratch for these purposes. In addition to performance, it extends better and supports the markdown option used by GitHub.
Yii now uses * masked * CSRF tokens to prevent BREACH attacks .
RBAC has been rewritten, making it easier. Business rules are now issued in the form of classes without any
The long-awaited feature that appeared in beta is a built-in framework for creating a REST API. In this review, we will not describe it in detail, but only list the main features. Full description is available in The Definitive Guide .
Many have asked why Yii does not have a Dependency Injection (DI) container. In fact, Yii always provided similar functionality in the form of a Service Locator, an instance of the Yii application. Now we have separated the service locator into a separate component
In addition to Service Locator, we also implemented a DI container
Yii has been integrated with Codeception . This allows you to test the application as a whole by emulating user actions and verifying the correctness of the generated answers. Unlike selenium support in PHPUnit, Codeception does not require a browser, it is easier to put on a CI server and it works much faster.
Yii also added fixture support , which solves the problem of initializing test data - one of the longest and most routine tasks when writing tests. Support for fixtures covers both their creation and application. The faker extension was also implemented , which helps to create close to real data sets.
Both application templates, both “basic” and “advanced”, are delivered with tests: modular, functional and acceptance. We hope this will be a good incentive to apply development through testing.
In model validation, quite a few interesting improvements have occurred.
Validators
Validation can be done under conditions that are specified through the properties
Sometimes you need to check data that is not tied to a model. This can be done using the new class
Everything related to databases is Yii's strong point. The feature set was already quite interesting in the alpha version, and beta brought improvements and new features. Active Record implementations include elasticsearch , redis, and Sphinx search . And in beta, mongodb support appeared .
Yii now supports nested transactions. You can start a transaction without worrying about whether an external transaction has started.
We added
This is especially useful when working with related columns in a GridView. Now, using
ActiveRecord now converts data received from the database into the corresponding types. For example, if you have a
In order to simplify the search task, we have added a method
We have added support for batch requests for working with large amounts of data. When using this feature, we receive data in batches, and not immediately. This can significantly save memory. For example:
You can use batch queries with ActiveRecord:
Support for nested queries has been added to the query builder. You can compose a subquery as a regular object
Links can often be paired. For example,
which orders are searched. A call
To avoid unnecessary SQL query, you can declare feedback for
Now, if we execute the above code again, we get the following:
In alpha 2.0 in ActiveRecord, we implemented support for both relational (e.g. MySQL)
and noSQL (e.g. redis, elasticsearch, MongoDB) data stores. In beta, we refactored this code and achieved more uniformity of interfaces. Namely, it was deleted
These methods allow you to query on keys or column values using short syntax. Previously, this could be done with the method parameters
We decided to use the excellent Pjax library and created a widget
order to get page-by-page navigation and sorting without reloading the page:
In addition to many internal fixes and improvements, the request and response components have undergone many changes. The most notable thing is that working with request now looks like this:
Another fundamental change is that response is now sent at the very end of the application, which allows you to modify the headers and body of the response as you wish and where you wish.
The request class is now able to parse the request body in various formats, such as JSON.
The whole filtering mechanism has been rethought. Now you can enable the filtering of actions at both the controller level and at the application or module levels. This allows you to organize hierarchical filters. For example, you can set a filter for a module and it will be applied to all its actions. In addition, you can install another filter on some module controllers. This filter will only apply to the action in these controllers.
The code has been reorganized and the filters are now in the namespace
We introduced an important initialization step (“bootstrap”) into the application life cycle. Extensions can register bootstrap classes by declaring them in
The bootstrap component will be instantiated before the application starts processing the request. This gives the component the ability to register event handlers and take part in the application life cycle.
Since developers work a lot with URLs, we put most of the URL-related methods to the helper
URL rules also have improvements. You can use the new class
We redid the implementation of RBAC. Now it is based on the original RBAC NIST model, namely we threw out the concept of operations and tasks . Instead, they now have permissions , which corresponds to the term NIST.
As mentioned above, the redesign comprehended and biz rule. Now the rules are described in separate classes.
First, we want to say thanks to all members of the community who participated in the translation of the framework messages. At the moment they are translated into 26 languages. Good number, right?
The message translation component now attempts to take messages from an alternative source if the one used does not contain the desired message. For example, if your application uses
A new option has been added to the Gii code generator that allows you to generate code with messages wrapped in
The team for finding messages for translation learned to write strings in
We have implemented a documentation generator extension
The debugger received many minor improvements and a mail debugging panel. He also learned to show the number of queries to the database and the number of letters sent in the toolbar.
In addition to the improvements regarding translations mentioned above, a new extension generator was added to Gii. In addition, you may notice improvements in the preview of the generated code. You can quickly switch between files and update diff, including from the keyboard. Also now, with copy-paste from diff, nothing superfluous gets to the buffer.
Give it a try!
The beta version of Yii 2.0 is a big milestone that has been achieved with great joint efforts. We would not have succeeded without a huge amount of valuable code received from our wonderful community .
Thank you for the release.
Beta includes hundreds of innovations, changes and fixes from the alpha release .
Next, we will review the most important, but first answer the frequently asked questions.
FAQ
- What does beta mean? Beta means a stable set of features and architecture. From beta to GA (General Availability, stable release), we will mainly deal with bug fixes and documentation. We are not going to change the architecture of the framework or add any new features. It is worth noting that breakdowns of backward compatibility can still happen, but we will try to make them as small as possible, and describe the details made in detail.
- When will the stable release be? So far, we can’t give an exact date. Since the next stage consists mainly in fixing errors and finalizing documentation, we think that it won’t take much time.
- Can I use beta in my projects? You should not use beta in projects with tight deadlines or if you are not familiar with Yii 2.0. If this is not about you and you are not afraid of changes in the framework, you can try. We heard that quite a few projects have already been launched and are working on the `master` branch. Also remember that the minimum PHP version for the framework to work is 5.4.
- Is there any 2.0 documentation? Yes, there is The Definitive Guide and API documentation . The guide is constantly updated. Translation into Russian will be as soon as the original is more or less completed.
- How can I upgrade applications from 1.1 to 2.0? A separate section on
Upgrading from Yii 1.1 has been written on this subject . It is worth noting that since 2.0 is completely rewritten, updating will not be a trivial task. Nevertheless, if you worked with 1.1, it will be much easier for you because there are a lot of similarities between 1.1 and 2.0. - How to upgrade from alpha 2.0? If you update alpha through Composer, you should delete everything except
.gitignore
from the directoryvendor
and run composer again. You only need to do this once and you don’t have to do this with every new release. A complete list of changes, including those breaking backward compatibility, is available in the CHANGELOG file . - How to follow development 2.0? All development and discussion takes place on GitHub:
https://github.com/yiisoft/yii2 . You can subscribe to updates or put an asterisk to receive updates notifications. You can also follow our twitter https://twitter.com/yiiframework .
Big changes with alpha
You can find the full list of changes in CHANGELOG , and below we will describe the most important.
Structure
Yii 2 started using PSR-4
to load classes. I.e:
- The directory structure of the framework has become simpler.
- The extension directory structure has become simpler.
- The framework no longer loads classes named in the PEAR style. Class loading made this easier and faster.
Controller classes must now be located in the namespace specified in
Module::controllerNamespace
, unless of course you are using Module::controllerMap
. We also returned support for the grouping of controllers in the subdirectory, which was in 1.1.
Ease of use
Ease of use is one of the highest priorities of our team. That is why we pay a lot of attention to naming and to ensure that the code works fine with various IDEs. All this allows you to make everyday development more enjoyable.
We switched to PSR-1 and PSR-2 code styles and got support for many IDEs, automated code checking and
automatic formatting .
Performance
One of the most significant changes is that the session does not start until it is really needed. This allows applications not to waste extra resources.
If you use Markdown in your projects, you will notice that the conversion speed to HTML has increased significantly. This became possible after Carsten Brandt (cebe), after reviewing existing solutions, wrote his library from scratch for these purposes. In addition to performance, it extends better and supports the markdown option used by GitHub.
Security
Yii now uses * masked * CSRF tokens to prevent BREACH attacks .
RBAC has been rewritten, making it easier. Business rules are now issued in the form of classes without any
eval
.RESTful API framework
The long-awaited feature that appeared in beta is a built-in framework for creating a REST API. In this review, we will not describe it in detail, but only list the main features. Full description is available in The Definitive Guide .
- Rapid prototyping of frequent operations through ActiveRecord;
- Response format negotiation (JSON and XML are supported by default);
- Customizable serialization of objects. You can select serializable fields.
- Proper formatting of data collections and validation errors;
- Effective routing with full HTTP support;
- Support
OPTIONS
andHEAD
; - Authentication
- Authorization
- HATEOAS support;
- HTTP caching
- Limit the number of requests.
Dependency Injection and Service Locator
Many have asked why Yii does not have a Dependency Injection (DI) container. In fact, Yii always provided similar functionality in the form of a Service Locator, an instance of the Yii application. Now we have separated the service locator into a separate component
yii\di\ServiceLocator
. As before, both the application and the modules are service locators. You can get the service (in 1.1 it was called the application component) using Yii::$app->get('something')
. In addition to Service Locator, we also implemented a DI container
yii\di\Container
. It helps to create less related code. According to preliminary data, our container is one of the fastest DI containers in PHP. You can use Yii::$container->set()
to set the initial values of classes. The old method is Yii::$objectConfig
deleted.Testing
Yii has been integrated with Codeception . This allows you to test the application as a whole by emulating user actions and verifying the correctness of the generated answers. Unlike selenium support in PHPUnit, Codeception does not require a browser, it is easier to put on a CI server and it works much faster.
Yii also added fixture support , which solves the problem of initializing test data - one of the longest and most routine tasks when writing tests. Support for fixtures covers both their creation and application. The faker extension was also implemented , which helps to create close to real data sets.
Both application templates, both “basic” and “advanced”, are delivered with tests: modular, functional and acceptance. We hope this will be a good incentive to apply development through testing.
Model Validation
In model validation, quite a few interesting improvements have occurred.
Validators
UniqueValidator
and ExistValidator
now supports checking multiple columns. Below are some examples for unique
:// a1 должен быть уникальным
['a1', 'unique']
// a1 должен быть уникален, но сравнивать будем с a2
['a1', 'unique', 'targetAttribute' => 'a2']
// a1 и a2 вместе должны быть уникальны и оба поля получат сообщения об ошибке
[['a1', 'a2'], 'unique', 'targetAttribute' => ['a1', 'a2']]
// a1 и a2 вместе должны быть уникальны, но только a1 получит сообщение об ошибке
['a1', 'unique', 'targetAttribute' => ['a1', 'a2']]
// a1 должен быть уникален при сравнении его значения как с a2, так и с a3
['a1', 'unique', 'targetAttribute' => ['a2', 'a1' => 'a3']]
Validation can be done under conditions that are specified through the properties
when
and whenClient
. The following is an example of the mandatory state field only if the selected country is USA:['state', 'required',
'when' => function ($model) {
return $model->country == Country::USA;
},
'whenClient' => "function (attribute, value) {
return $('#country').value == 'USA';
}",
]
Sometimes you need to check data that is not tied to a model. This can be done using the new class
yii\base\DynamicModel
:public function actionSearch($name, $email)
{
$model = DynamicModel::validateData(compact('name', 'email'), [
[['name', 'email'], 'string', 'max' => 128],
['email', 'email'],
]);
if ($model->hasErrors()) {
// неудачная валидация
} else {
// всё хорошо
}
}
Database and Active Record
Everything related to databases is Yii's strong point. The feature set was already quite interesting in the alpha version, and beta brought improvements and new features. Active Record implementations include elasticsearch , redis, and Sphinx search . And in beta, mongodb support appeared .
Nested Transaction Support
Yii now supports nested transactions. You can start a transaction without worrying about whether an external transaction has started.
Join
We added
ActiveQuery::joinWith()
to support the creation of SQL queries with JOIN using the already declared AR relationships. This is especially useful if you want to filter or sort data by fields from related tables. For example:// найдёт все заказы и отсортирует их по id клиента и id заказа. При этом для "customer" будет использована жадная загрузка
$orders = Order::find()->joinWith('customer')->orderBy('customer.id, order.id')->all();
// найдёт все заказы, в которых есть книги. При этом для "books" будет использована жадная загрузка
$orders = Order::find()->innerJoinWith('books')->all();
This is especially useful when working with related columns in a GridView. Now, using
joinWith()
, it is very easy to sort or filter on them.Data type conversion
ActiveRecord now converts data received from the database into the corresponding types. For example, if you have a
type
type column in the database integer
, after receiving the corresponding ActiveRecord instance, the type
type will be integer
in PHP.Search
In order to simplify the search task, we have added a method
Query::filterWhere()
that automatically removes empty values. For example, if you have a search form with a filter by name
and email
, then you can use the above code to build a search query. Without this method, you would have to check if the user entered something in the field and add a search term only in this case. filterWhere()
does such a check for you.$query = User::find()->filterWhere([
'name' => Yii::$app->request->get('name'),
'email' => Yii::$app->request->get('email'),
]);
Batch requests
We have added support for batch requests for working with large amounts of data. When using this feature, we receive data in batches, and not immediately. This can significantly save memory. For example:
use yii\db\Query;
$query = (new Query())
->from('user')
->orderBy('id');
foreach ($query->batch() as $users) {
// $users — массив из 100 или менее строк из таблицы user
}
// или, если хотите получать по одной строке за раз
foreach ($query->each() as $user) {
// $user — одна строка данных из таблицы user
}
You can use batch queries with ActiveRecord:
// выбираем по 10 клиентов за раз
foreach (Customer::find()->batch(10) as $customers) {
// $customers — массив 10 или менее объектов Customer
}
// выбираем по 10 клиентов за раз, перебираем по одному
foreach (Customer::find()->each(10) as $customer) {
// $customer — объект Customer
}
// пакетный запрос с жадной загрузкой
foreach (Customer::find()->with('orders')->each() as $customer) {
}
Subquery Support
Support for nested queries has been added to the query builder. You can compose a subquery as a regular object
Query
and then use it in another Query
:$subQuery = (new Query())->select('id')->from('user')->where('status=1');
$query->select('*')->from(['u' => $subQuery]);
Feedback
Links can often be paired. For example,
Customer
may contain a connection orders
, in Order
may contain a connection customer
. In the example below, you will notice that the customer
order is not the same object as the original for which orders are searched. A call
customer->orders
will result in a new SQL query, just like an customer
order call :// SELECT * FROM customer WHERE id=1
$customer = Customer::findOne(1);
// echoes "not equal"
// SELECT * FROM order WHERE customer_id=1
// SELECT * FROM customer WHERE id=1
if ($customer->orders[0]->customer === $customer) {
echo 'equal';
} else {
echo 'not equal';
}
To avoid unnecessary SQL query, you can declare feedback for
customer
and orders
. This is done using the method inverseOf()
:class Customer extends ActiveRecord
{
// ...
public function getOrders()
{
return $this->hasMany(Order::className(), ['customer_id' => 'id'])->inverseOf('customer');
}
}
Now, if we execute the above code again, we get the following:
// SELECT * FROM customer WHERE id=1
$customer = Customer::findOne(1);
// echoes "equal"
// SELECT * FROM order WHERE customer_id=1
if ($customer->orders[0]->customer === $customer) {
echo 'equal';
} else {
echo 'not equal';
}
Uniform APIs for Relational Query
In alpha 2.0 in ActiveRecord, we implemented support for both relational (e.g. MySQL)
and noSQL (e.g. redis, elasticsearch, MongoDB) data stores. In beta, we refactored this code and achieved more uniformity of interfaces. Namely, it was deleted
ActiveRelation
, and ActiveQuery
became a single entry point for fulfilling queries on relationships and describing relationships. We also added methods ActiveRecord::findOne()
and findAll()
. These methods allow you to query on keys or column values using short syntax. Previously, this could be done with the method parameters
ActiveRecord::find()
, which caused confusion due to the method returning different data types.AJAX Support
We decided to use the excellent Pjax library and created a widget
yii\widgets\Pjax
. This is a common widget that allows you to add AJAX to everything that is wrapped in it. For example, you can wrap it GridView
in order to get page-by-page navigation and sorting without reloading the page:
use yii\widgets\Pjax;
use yii\grid\GridView;
Pjax::begin();
echo GridView::widget([ /*...*/ ]);
Pjax::end();
Request and response
In addition to many internal fixes and improvements, the request and response components have undergone many changes. The most notable thing is that working with request now looks like this:
// получаем GET параметр из request, если его там нет, умолчание равно 1
$page = Yii::$app->request->get('page', 1);
// получаем POST параметр из request, если его там нет, умолчание равно null
$name = Yii::$app->request->post('name');
Another fundamental change is that response is now sent at the very end of the application, which allows you to modify the headers and body of the response as you wish and where you wish.
The request class is now able to parse the request body in various formats, such as JSON.
Filters
The whole filtering mechanism has been rethought. Now you can enable the filtering of actions at both the controller level and at the application or module levels. This allows you to organize hierarchical filters. For example, you can set a filter for a module and it will be applied to all its actions. In addition, you can install another filter on some module controllers. This filter will only apply to the action in these controllers.
The code has been reorganized and the filters are now in the namespace
yii\filters
. For example, you can use a filter yii\filters\HttpBasicAtuh
to enable HTTP Basic Auth authentication. To do this, it is described in the controller or module:public function behaviors()
{
return [
'basicAuth' => [
'class' => \yii\filters\auth\HttpBasicAuth::className(),
'exclude'=> ['error'], // не применяем к action "error"
],
];
}
Component initialization
We introduced an important initialization step (“bootstrap”) into the application life cycle. Extensions can register bootstrap classes by declaring them in
composer.json
. A regular component can also be registered for bootstrap if declared in Application::$bootstrap
. The bootstrap component will be instantiated before the application starts processing the request. This gives the component the ability to register event handlers and take part in the application life cycle.
Work with URL
Since developers work a lot with URLs, we put most of the URL-related methods to the helper
Url
and got a more pleasant API:use yii\helpers\Url;
// текущий активный маршрут
// например: /index.php?r=management/default/users
echo Url::to('');
// тот же контроллер, другой action
// например: /index.php?r=management/default/page&id=contact
echo Url::toRoute(['page', 'id' => 'contact']);
// тот же модуль, другие контроллер и action
// например: /index.php?r=management/post/index
echo Url::toRoute('post/index');
// абсолютный маршрут не зависит от того, какой контроллер делает запрос
// например: /index.php?r=site/index
echo Url::toRoute('/site/index');
// url для регистрозависимого имени `actionHiTech` текущего контроллера
// например: /index.php?r=management/default/hi-tech
echo Url::toRoute('hi-tech');
// url для action в контроллере с регистрозависимым именем, `DateTimeController::actionFastForward`
// например: /index.php?r=date-time/fast-forward&id=105
echo Url::toRoute(['/date-time/fast-forward', 'id' => 105]);
// получаем URL из alias
Yii::setAlias('@google', 'http://google.com/');
echo Url::to('@google/?q=yii');
// получаем канонический URL для текущей страницы
// например: /index.php?r=management/default/users
echo Url::canonical();
// получаем домашний URL
// например: /index.php?r=site/index
echo Url::home();
Url::remember(); // сохраняем URL
Url::previous(); // получаем сохранённый URL
URL rules also have improvements. You can use the new class
yii\web\GroupUrlRule
to group rules. For each group, you can specify a common prefix that will apply to all URLs in the group.new GroupUrlRule([
'prefix' => 'admin',
'rules' => [
'login' => 'user/login',
'logout' => 'user/logout',
'dashboard' => 'default/dashboard',
],
]);
// правило выше эквивалентно следующему:
[
'admin/login' => 'admin/user/login',
'admin/logout' => 'admin/user/logout',
'admin/dashboard' => 'admin/default/dashboard',
]
Role Based Access Control (RBAC)
We redid the implementation of RBAC. Now it is based on the original RBAC NIST model, namely we threw out the concept of operations and tasks . Instead, they now have permissions , which corresponds to the term NIST.
As mentioned above, the redesign comprehended and biz rule. Now the rules are described in separate classes.
Translations
First, we want to say thanks to all members of the community who participated in the translation of the framework messages. At the moment they are translated into 26 languages. Good number, right?
The message translation component now attempts to take messages from an alternative source if the one used does not contain the desired message. For example, if your application uses
fr-CA
as a language, and translations are only for fr
, then Yii will first search for the translation in fr-CA
and, if it is not found there, the search will continue to fr
. A new option has been added to the Gii code generator that allows you to generate code with messages wrapped in
Yii::t()
. The team for finding messages for translation learned to write strings in
.po
and databases.Extensions and Tools
We have implemented a documentation generator extension
yii2-apidoc
that can be used to create API documentation and basic documentation from markdown. The generator is easily customizable and extends to your needs. We use it to generate official documentation and APIs. You can look at the result here: http://www.yiiframework.com/doc-2.0/ . The debugger received many minor improvements and a mail debugging panel. He also learned to show the number of queries to the database and the number of letters sent in the toolbar.
In addition to the improvements regarding translations mentioned above, a new extension generator was added to Gii. In addition, you may notice improvements in the preview of the generated code. You can quickly switch between files and update diff, including from the keyboard. Also now, with copy-paste from diff, nothing superfluous gets to the buffer.
Give it a try!
Thanks!
The beta version of Yii 2.0 is a big milestone that has been achieved with great joint efforts. We would not have succeeded without a huge amount of valuable code received from our wonderful community .
Thank you for the release.