- Scalability and concurrency
- Validator enhancements
- Behaviors
- Databases and ActiveRecord
- Error handling
- Security
- PHP 7.2
- Widgets, forms and clientside
- Events
- APIs, serializers and filters
- Console
- Routing
- i18n
- Helpers
- DI container
- Project templates
- Preparing for 2.1
We are very pleased to announce the release of Yii Framework version 2.0.14. Please refer to the instructions at http://www.yiiframework.com/download/ to install or upgrade to this version.
Version 2.0.14 is a minor release of Yii 2.0 which contains more than a hundred enhancements and bug fixes including security fixes. It is also the last version of Yii 2.0 that contains enhancements. This means that we will focus on including new features into the 2.1.x branch and 2.0.x will only receive bug fixes from now on. We will make an announcement on the time frames for supporting different branches with the release of version 2.1.
There are minor changes that may affect your existing applications, so make sure to check the UPGRADE.md file.
Thanks to all Yii community members who contribute to the framework. We did it together!
You may follow the development progress of Yii 2 by starring or watching Yii 2.0 GitHub Project. There are many active Yii communities so if you need help or want to share your experience, feel free to join them.
Since there is Yii 2.1 in development now, make sure you have a version constraint in your composer.json
, that does not allow it to be installed automatically on update, so when next major version of Yii is released, your project won't break by itself.
A version constraint that does not include 2.1 is for example ~2.0.14
, make sure you do not have >=
or *
in version constraints in composer.json
.
Below we summarize some of the most important features/fixes included in this release. A complete list of changes can be found in the CHANGELOG.
Scalability and concurrency ¶
While not important at early project stages, scalability and concurrency issues are major obstacles for business growth. In this release we have identified and fixed
a concurrency issue when writing values and regenerating IDs in yii\web\DbSession
and three issues that may appear in master-slave setups while using yii\web\DbSession
, yii\validators\UniqueValidator
and yii\validators\ExistValidator
.
Validator enhancements ¶
Additionally to what's mentioned in previous section, there are enhancements in built-in validators.
First, the ExistValidator
is now able to check relations when its new targetRelation
property is set. That basically means the following rules definition is now possible:
public function rules()
{
return [
[['customer_id'], 'exist', 'targetRelation' => 'customer'],
];
}
public function getCustomer()
{
return $this->hasOne(Customer::class, ['id' => 'customer_id']);
}
Another enhancement is about FileValidator
. It got a new property called minFiles
to specify the minimum number of files a
user must upload.
Behaviors ¶
yii\behaviors\BlameableBehavior
got a defaultValue
property that is used in case user ID could not be determined. That is often
the case when Active Record model is used within console application.
New yii\behaviors\AttributeTypecastBehavior
property typecastAfterSave
could be set to true
to make values typecasted after model is saved.
That makes attribute types consistent if they're casted when saved to database.
New yii\behaviors\CacheableWidgetBehavior
was added. It automatically caches widget contents according to duration and dependencies specified
and could be added to a widget like the following:
use yii\behaviors\CacheableWidgetBehavior;
public function behaviors()
{
return [
[
'class' => CacheableWidgetBehavior::className(),
'cacheDuration' => 0,
'cacheDependency' => [
'class' => 'yii\caching\DbDependency',
'sql' => 'SELECT MAX(updated_at) FROM posts',
],
],
];
}
Databases and ActiveRecord ¶
This release adds lots of great things related to databases and ActiveRecord that were worked by Dmitry Naumenko, Sergey Makinen, Robert Korulczyk, Nikolay Oleynikov and other community members.
Custom data types and object conditions ¶
Custom data types support was implemented. Added JSON support for MySQL and PostgreSQL and arrays support for PostgreSQL. In order to do that, Query Builder internals were refactored significantly and now support object format for conditions:
$query->andWhere(new OrCondition([
new InCondition('type', 'in', $types),
['like', 'name', '%good%'],
'disabled=false',
]));
There are two good things about it. First, it's easier to support existing conditions and add new ones for Yii team. Additionally to conditions for JSON
and arrays, it already resulted in a new BetweenColumnsCondition
. There could be more added in Yii 2.1.
Second, it's convenient to add custom conditions now.
Query Builder flexibility ¶
Query Builder flexibility was improved overall. It is now possible to pass yii\db\Query
anywhere, where yii\db\Expression
was supported. For example,
it is now possible to use it like the following:
$subquery = (new Query)
->select([new Expression(1)])
->from('tree')
->where(['parent_id' => 1, 'id' => new Expression('tree.parent_id']));
(new Query())
->from('tree')
->where(['or', 'parent_id = 1', $subquery])
Upserts ¶
Another big thing is upserts for all databases Yii database layer supports. Upsert is an atomic operation that inserts rows into a database table if they do not already exist (matching unique constraints), or update them if they do:
Yii::$app->db->createCommand()->upsert('pages', [
'name' => 'Front page',
'url' => 'http://example.com/', // URL is unique
'visits' => 0,
], [
'visits' => new \yii\db\Expression('visits + 1'),
], $params)->execute();
Will either insert a new page record or increment its visit counter atomically.
Schema builder and migrations ¶
Schema builder now supports tiny integer and JSON so you can use the following in migrations:
$this->createTable('post', [
'id' => $this->primaryKey(),
'text' => $this->text(),
'title' => $this->string()->notNull(),
'attributes' => $this->json(),
'status' => $this->tinyInteger(),
]);
Another enhancement about migrations is the ability to create and drop database views:
$this->createView(
'top_10_posts',
(new \yii\db\Query())
->from('post')
->orderBy(['rating' => SORT_DESC])
->limit(10)
);
$this->dropView('top_10_posts');
New query caching syntax ¶
It was possible before to wrap DB calls with connection's cache
method.
Now there are handy shortcuts:
// at query level
(new Query())->cache(7200)->all();
// at AR level
User::find()->cache(7200)->all();
Active Record relations ¶
Active Record now resets related models after corresponding attribute updates:
$item = Item::findOne(1);
echo $item->category_id; // 1
echo $item->category->name; // weapons
$item->category_id = 2;
echo $item->category->name; // toys
Error handling ¶
Log targets now throw exception in case log can't be exported properly. Previously they were failing silently.
Another case where Yii is now throwing yii\web\HeadersAlreadySentException
exception instead of being silent
if headers were already sent before (thus, it's not possible to send more).
It is now possible to configure Yii error handler via setting $traceLine
property to generate links in the exception code so these could be opened directly in IDE. Configuration is similar to debug toolbar:
'components' => [
// ...
'errorHandler' => [
'errorAction' => 'site/error',
'traceLine' => '<a href="ide://open?url={file}&line={line}">{html}</a>',
],
],
Using yii\web\ErrorAction::$layout
property you can set layout from error action config conveniently:
class SiteController extends Controller
{
// ...
/**
* @inheritdoc
*/
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
'layout' => 'error', // <-- HERE
],
];
}
Security ¶
There are two vulnerabilities discovered and fixed in this release:
- CVE-2018-6009. The
switchIdentity()
function inweb/User.php
did not regenerate the CSRF token upon a change of identity. - CVE-2018-6010. Remote attackers could obtain potentially sensitive information from exception messages printed by the error handler in non-debug mode.
PHP 7.2 ¶
This release brings full PHP 7.2 compatibility. We have adjusted yii\filters\HttpCache
, FileHelper::getExtensionsByMimeType()
and yii\web\Session
to work well with all PHP versions we support.
Widgets, forms and clientside ¶
Markup generated for <script>
tag doesn't have type
attribute anymore. Additionally to better looking, it makes HTML5 markup validator happy.
In form active fields (for both Active Form and Html helper) you can now automatically include placeholder that matches field's attribute:
<?= Html::activeTextInput($post, 'title', ['placeholder' => true]) ?>
Another thing added to ActiveForm is an ability to choose which HTML element receives validation state classes:
<?php $form = ActiveForm::begin([
'validationStateOn' => ActiveForm::VALIDATION_STATE_ON_INPUT,
]) ?>
That possibly allows Yii bootstrap extension to adopt Bootstrap 4.
It's now possible to register JavaScript variables via PHP code:
class SiteController extends Controller
{
public function actionIndex()
{
$this->view->registerJsVar('username', 'SilverFire');
return $this->render('index');
}
}
While it is widely used method of passing data from PHP to JavaScript, before using it consider HTML5 data attributes.
Events ¶
Paul Klimov added wildcard matching to events so it's now possible to subscribe to multiple objects or class events that match the pattern. That is very useful for logging and audit. Brand new section in the guide is full of examples using the feature.
APIs, serializers and filters ¶
When configuring JsonResponseFormatter
you can now specify content type:
'components' => [
'response' => [
// ...
'formatters' => [
\yii\web\Response::FORMAT_JSON => [
'class' => \yii\web\JsonResponseFormatter::className(),
'contentType' => \yii\web\JsonResponseFormatter::CONTENT_TYPE_HAL_JSON,
],
],
],
]
Data filter can now handle lt
,gt
,lte
and gte
on yii\validators\DateValidator
.
yii\base\ArrayableTrait::toArray()
now allows recursive $fields
and $expand
. That means REST APIs queries expand
could be specified now as extra1.extra2
and that would expand extra1
in the original data set and then extra2
in extra1
data set i.e. queries like http://localhost/comments?expand=post.author
are possible.
In case you need to convert model validation errors into JSON you may use \yii\helpers\Json::errorSummary()
now.
Custom authentication headers are now easier to set up thanks to added yii\filters\auth\HttpHeaderAuth
.
Console ¶
How many times you wished there was a built-in method to print model validation errors into console instead of doing foreach
? Now there is one:
if (!$model->validate()) {
echo "Model is not valid:\n";
echo \yii\helpers\Console::errorSummary($model);
return ExitCode::DATAERR;
}
bash and zsh command completion got better. Now it
understands ./yii help
.
When invoking a command options could now be specified as both camelCase and kebab-case i.e. --selfUpdate
and --self-update
. Moreover, in addition to
--<option>=<value>
console optios syntax, it's now possible to use --<option> <value>
syntax.
Routing ¶
Short verb syntax could now be used in URL rule groups:
'components' => [
'urlManager' => [
// ...
'rules' => [
new GroupUrlRule([
'prefix' => 'file',
'rules' => [
'POST document' => 'document/create',
],
]),
],
],
i18n ¶
New yii\i18n\Locale
component was added having getCurrencySymbol()
method that is able to get currency symbol for a given locale.
Helpers ¶
This release brings very interesting enhancements to Yii helpers.
yii\helpers\FileHelper
got two new methods. findDirectories()
returns the directories found under the specified directory and subdirectories.
It is similar to existing findFiles()
but works with directories. unlink()
removes a file or symlink in a cross-platform way which proved to be
tricky.
yii\helpers\StringHelper
got a new matchWildcard()
method that does the same as native fnmatch()
but does it consistently among different OS.
Native one proved to differ from system to system.
yii\helpers\IpHelper
was added. It allows determining IP version by address, comparing address against a mask or range, and expanding IPv6.
Usage is simple and convenient:
if (!IpHelper::inRange($ip, '192.168.1.0/24')) {
// deny access
}
DI container ¶
Container got an ability to reuse definitions as properties:
'container' => [
'definitions' => [
\console\models\TestService::class => [
'class' => \console\models\TestService::class,
'model' => Instance::of(\console\models\TestModel::class)
],
\console\models\TestModel::class => [
'class' => \console\models\TestModel::class,
'property' => 20,
],
],
],
In the code above the model
property of TestService
will be set with an instance of TestModel
class configured in the container.
Project templates ¶
Additionally to minor adjustments basic project template got Docker and vagrant support.
Preparing for 2.1 ¶
Brandon Kelly proposed a very good idea to mark some methods and classes that were already removed in 2.1 as deprecated. That should make transition from 2.0 to 2.1 easier:
- Deprecated
yii\base\BaseObject::className()
in favor of native PHP syntax::class
, which does not trigger autoloading (only works with PHP >=5.5). - Deprecated XCache and Zend data cache support as caching backends.
- Deprecated
yii\BaseYii::powered()
method. - Added
yii\base\InvalidArgumentException
and deprecatedyii\base\InvalidParamException
. - Added
yii\BaseYii::debug()
and deprecatedyii\BaseYii::trace()
.
Code using these methods would work as usual except that IDEs will mark it deprecated.