📜 ⬆️ ⬇️

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.


')

Frequently asked Questions





Big changes from alpha version



A complete list of changes can be found in CHANGELOG , and below we describe the most important.

Structure


Yii 2 started using PSR-4
for loading classes. I.e:



Controller classes must now be in the namespace specified in Module::controllerNamespace , unless of course you use Module::controllerMap .

We also returned support for grouping controllers in a subdirectory that was in 1.1.

The convenience of use


Ease of use is one of our team’s highest priorities. That is why we pay a lot of attention to naming and ensuring that the code works well with different IDEs. All this allows you to make everyday development more enjoyable.

We switched to the PSR-1 and PSR-2 code styles and received support from 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 to not 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 its library from scratch for this purpose. In addition to performance, it expands better and supports the markdown version used by GitHub.

Security


Now Yii uses * masked * CSRF tokens to prevent BREACH attacks.

RBAC was rewritten, making it easier. Business rules are now drawn up 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. A full description is available in The Definitive Guide .



Dependency Injection and Service Locator


Many have asked why there is no Dependency Injection (DI) container in Yii. In fact, Yii has always provided similar functionality in the form of a Service Locator, an instance of the Yii application. Now we have allocated the service locator to 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 the Service Locator, we also implemented a yii\di\Container 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 the classes. The old Yii::$objectConfig removed.

Testing


Yii has been integrated with Codeception . This allows you to test the application as a whole by emulating user actions and validating the generated responses. Unlike PHPInit's selenium support, Codeception does not require a browser, it is easier to put it on a CI server and it works much faster.

Yii also adds support for fixtures , 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 has also been implemented, which helps create near-real data sets.

Both application templates, both “basic” and “advanced”, come with tests: modular, functional and acceptance. We hope this will be a good incentive to apply the development through testing.

Validation of models


There are quite a few interesting improvements in model validation.

Validators UniqueValidator and ExistValidator now support 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 performed under conditions that are specified through the when and whenClient . The following is an example of the mandatory field "state" 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 want to check the data is not tied to the 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 forte. The feature set was already quite interesting in the alpha version, and the beta brought improvements and new features. Active Record implementations include elasticsearch , redis and Sphinx search . And in the 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 begun.

Join


We added ActiveQuery::joinWith() to support the creation of SQL queries with JOIN using the already declared AR links. 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 by them.

Data Type Conversion


ActiveRecord now converts data received from the database into the appropriate types. For example, if you have an integer type column in your database, after receiving the corresponding ActiveRecord instance, the type will be of type integer in PHP.

Search


In order to simplify the search task, we added the Query::filterWhere() method, which automatically removes empty values. For example, if you have a search form with a filter for the name and email fields, 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 into the field and add the search condition only in this case. filterWhere() does this checking for you.

 $query = User::find()->filterWhere([ 'name' => Yii::$app->request->get('name'), 'email' => Yii::$app->request->get('email'), ]); 


Batch requests


We added support for batch requests for working with large amounts of data. When using this feature, we get the data in chunks, but not immediately. This saves 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 requests 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 subqueries has been added to the query builder. You can create a subquery as a normal Query object 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 declared in pairs. For example, Customer may contain a orders link, in Order may contain a customer link. In the example below, it can be noted that the customer order is not the same object as the original for
who are looking for orders. Calling customer->orders will lead to a new SQL request as well as calling customer order:

 // 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 inquiries, you can provide feedback for customer and orders relationships. This is done using the inverseOf() method:

 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 API for Relational Query


In Alpha 2.0 in ActiveRecord, we implemented support for both relational (for example, MySQL),
and noSQL (for example, redis, elasticsearch, MongoDB) data stores. In beta, we refactored this code and achieved greater uniformity of interfaces. Namely, ActiveRelation was removed, and ActiveQuery became a single entry point for query execution and link description. We also added the ActiveRecord::findOne() and findAll() methods.
These methods allow you to query on keys or values ​​of columns using a short syntax. Previously, this could be done with the parameters of the ActiveRecord::find() method, which caused confusion due to the method returning different data types.

AJAX support


We decided to use the excellent Pjax library and created the yii\widgets\Pjax . This is a generic widget that allows you to add AJAX to everything that is wrapped in it. For example, you can wrap a GridView into it.
In order to get paginated 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 noticeable 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 the response is now sent at the very end of the application, which allows you to modify the headers and body of the answer as you wish and where you want it.

The request class is now able to parse the body of the request in various formats, such as JSON.

Filters


The whole filtering mechanism has been rethought. Now you can enable filtering of actions at the controller level as well as 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 be applied only to action th in these controllers.

The code has been reorganized and the filters are now in the yii\filters namespace. For example, you can use the filter yii\filters\HttpBasicAtuh to enable HTTP authentication Basic Auth. 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 have 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 installed before the application starts processing the request. This enables the component to register event handlers and participate in the application life cycle.

Work with URL


Since the developers work a lot with URLs, we took out most of the URL-related methods to the Url helper 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 


The URL rules also have improvements. You can use the new yii\web\GroupUrlRule class to group the rules. For each group, you can set a common prefix that will be applied 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 RBAC implementation. Now it is based on the original NIST RBAC model, namely, we threw out the concept of operations and tasks . Instead, they now have permissions , which corresponds to the NIST term.

As mentioned above, the redesign has 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 retrieve messages from an alternate source if the used one 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 look for a translation in fr-CA and, if it is not found there, the search will continue in 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 command to search for messages for translation has learned to write lines in .po and databases.

Extensions and tools


We have implemented an extension of the yii2-apidoc documentation generator, which can be used to create API documentation and main documentation from markdown. The generator is easily customized and expands to your needs. We use it to generate official documentation and an API. You can see the result here: http://www.yiiframework.com/doc-2.0/ .

Debagger has received many minor improvements and a mail debug panel. He also learned how to show the number of queries to the database and the number of sent letters in the toolbar.

In addition to the improvements in the translations mentioned above, a new extension generator has been added to Gii. In addition, you may notice improvements in the preview of the generated code. You can quickly switch between files and update the diff, including from the keyboard. Also, now when copying paste from diff, nothing superfluous gets into the buffer.
Try it!

Thank!



The beta version of Yii 2.0 is a major milestone that has been achieved through great joint efforts. We would not have succeeded without a huge amount of valuable code received from our wonderful community .
Thank you for the fact that this release took place.

Source: https://habr.com/ru/post/219329/


All Articles