Commit 504d9fdb by Tobias Munk

Merge commit '33edfcff' into feature/issue-1160

parents 3fc4d5eb 33edfcff
......@@ -100,7 +100,7 @@ TESTING
-------
Install additional composer packages:
* `php composer.phar require --dev "codeception/codeception: 1.8.*@dev" "codeception/specify: *" "codeception/verify: *" "yiisoft/yii2-faker: *"`
* `php composer.phar require --dev "codeception/codeception: 2.0.*" "codeception/specify: *" "codeception/verify: *" "yiisoft/yii2-faker: *"`
This application boilerplate use database in testing, so you should create three databases that are used in tests:
* `yii2_advanced_unit` - database for unit tests;
......
<?php
use yii\helpers\Html;
/* @var $this \yii\web\View */
/* @var $content string */
/* @var $this \yii\web\View view component instance */
/* @var $message \yii\mail\MessageInterface the message being composed */
/* @var $content string main view render result */
?>
<?php $this->beginPage() ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
......
......@@ -25,7 +25,7 @@
"yiisoft/yii2-gii": "*"
},
"suggest": {
"codeception/codeception": "Codeception, 1.8.*@dev is currently works well with Yii.",
"codeception/codeception": "Codeception, 2.0.* is currently works well with Yii.",
"codeception/specify": "BDD style code blocks for PHPUnit and Codeception",
"codeception/verify": "BDD Assertions for PHPUnit and Codeception",
"yiisoft/yii2-faker": "Fixtures generator for Yii2 based on Faker lib"
......
......@@ -14,7 +14,7 @@ return yii\helpers\ArrayHelper::merge(
'controllerMap' => [
'fixture' => [
'class' => 'yii\faker\FixtureController',
'fixtureDataPath' => '@console/tests/unit/fixtures/data',
'fixtureDataPath' => '@frontend/tests/unit/fixtures/data',
'templatePath' => '@common/tests/templates/fixtures'
],
],
......
......@@ -25,7 +25,7 @@
"yiisoft/yii2-gii": "*"
},
"suggest": {
"codeception/codeception": "Codeception, 1.8.*@dev is currently works well with Yii.",
"codeception/codeception": "Codeception, 2.0.* is currently works well with Yii.",
"codeception/specify": "BDD style code blocks for PHPUnit and Codeception",
"codeception/verify": "BDD Assertions for PHPUnit and Codeception"
},
......
<?php
use yii\helpers\Html;
/* @var $this \yii\web\View */
/* @var $content string */
/* @var $this \yii\web\View view component instance */
/* @var $message \yii\mail\MessageInterface the message being composed */
/* @var $content string main view render result */
?>
<?php $this->beginPage() ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
......
......@@ -6,7 +6,7 @@ After creating the basic application, follow these steps to prepare for the test
1. Install additional composer packages:
```
php composer.phar require --dev "codeception/codeception: 1.8.*@dev" "codeception/specify: *" "codeception/verify: *"
php composer.phar require --dev "codeception/codeception: 2.0.*" "codeception/specify: *" "codeception/verify: *"
```
2. In the file `_bootstrap.php`, modify the definition of the constant `TEST_ENTRY_URL` so
that it points to the correct entry script URL.
......
Service Locator
===============
Service Locator является объектом, который знает, как обеспечить всевозможные службы (или компоненты), которые могут понадобиться в приложении.
В пределах Service Locator'а, каждый компонент имеет только один экземпляр, который уникально определяется с помощью идентификатора (ID).
Уникальный идентификатор (ID) может быть использован для извлечения компонента из Service Locator'а.
В Yii Service Locator является экземпляром класса [[yii\di\ServiceLocator]] или его дочернего класса.
Наиболее часто используемый Service Locator в Yii - это объект *приложения*, который можно получить через
`\Yii::$app`. Обеспечиваемые им службы называют *компонентами приложения*, такие, как компоненты `запрос`, `ответ`, `UrlManager`.
Вы легко можете настроить эти компоненты или даже заменить их собственными реализациями,
благодаря функциональным службам, предоставляемым Service Locator'ом.
Помимо объекта приложения, объект каждого модуля так же является Service Locator'ом.
Для использования Service Locator'а первым шагом является регистрация компонентов.
Компонент может быть зарегистрирован с помощью [[yii\di\ServiceLocator::set()]].
Следующий код демонстрирует различные способы регистрации компонентов:
```php
use yii\di\ServiceLocator;
use yii\caching\FileCache;
$locator = new ServiceLocator;
// Зарегистрирует "cache", используя имя класса, которое может быть использовано для создания компонента.
$locator->set('cache', 'yii\caching\ApcCache');
// Зарегистрирует "db", используя конфигурационный массив, который может быть использован для создания компонента.
$locator->set('db', [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=demo',
'username' => 'root',
'password' => '',
]);
// Зарегистрирует "search", используя анонимную функцию, которая создаёт компонент
$locator->set('search', function () {
return new app\components\SolrService;
});
// Зарегистрирует "pageCache", используя компонент
$locator->set('pageCache', new FileCache);
```
После того, как компонент зарегистрирован, вы можете получить к нему доступ, используя уникальный идентификатор (ID),
одним из двух следующих способов:
```php
$cache = $locator->get('cache');
// или альтернативный
$cache = $locator->cache;
```
Как видно выше, [[yii\di\ServiceLocator]] позволяет обратиться к компоненту, как к свойству,
при помощи идентификатора (ID) компонента.
При обращении к компоненту впервые, [[yii\di\ServiceLocator]] будет использовать информацию о регистрации компонента,
что бы создать новый экземпляр компонента и вернёт его.
В дальнейшем при обращении к компоненту снова, Service Locator вернёт тот же экземпляр.
Что бы проверить, был ли идентификатор (ID) компонента уже зарегистрирован, можно использовать [[yii\di\ServiceLocator::has()]].
Если вы вызовете [[yii\di\ServiceLocator::get()]] с недопустимым идентификатором (ID), тогда будет выброшено исключение.
Поскольку Service Locator`ы зачастую создаются с [конфигурациями](concept-configurations.md),
записываемое свойство с именем [[yii\di\ServiceLocator::setComponents()|components]] предоставляется так,
что Вы можете его настроить и зарегистрировать несколько компонентов одновременно.
Следующий код демонстрирует конфигурационный массив,
который может использоваться для настройки приложения и регистрации компонентов "db", "cache" и "search" :
```php
return [
// ...
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=demo',
'username' => 'root',
'password' => '',
],
'cache' => 'yii\caching\ApcCache',
'search' => function () {
return new app\components\SolrService;
},
],
];
```
数据缓存
============
数据缓存是指将一些 PHP 变量存储到缓存中,使用时再从缓存中取回。
它也是更高级缓存特性的基础,例如 [查询缓存](#query-caching)[内容缓存](caching-content.md).
数据缓存是指将一些 PHP 变量存储到缓存中,使用时再从缓存中取回。它也是更高级缓存特性的基础,例如
[查询缓存](#query-caching)[分页缓存](caching-page.md).
如下代码是一个典型的数据缓存使用模式。其中 `$cache` 代表一个 [缓存组件](#cache-components):
......@@ -51,8 +51,8 @@ if ($data === false) {
然后你就可以通过 `Yii::$app->cache` 访问上面的缓存组件了。
由于所有缓存组件都支持同样的一系列 API ,你并不需要修改使用缓存的那些代码就能直接替换为其他低层缓存组件,
只需在应用程序配置中重新配置一下就可以。例如,你可以将上述配置修改为使用 [[yii\caching\ApcCache|APC cache]]:
由于所有缓存组件都支持同样的一系列 API
,你并不需要修改使用缓存的那些代码就能直接替换为其他低层缓存组件,只需在应用程序配置中重新配置一下就可以。例如,你可以将上述配置修改为使用 [[yii\caching\ApcCache|APC cache]]:
```php
......@@ -72,10 +72,8 @@ Yii 支持一系列缓存存储器,概况如下:
* [[yii\caching\ApcCache]]: 使用 PHP [APC](http://php.net/manual/en/book.apc.php) 扩展。这个选项可以认为是集中式应用程序环境中(例如:单一服务器,没有独立的负载均衡器等)最快的缓存方案。
* [[yii\caching\DbCache]]: 使用一个数据库的表存储缓存数据。要使用这个缓存,你必须创建一个 [[yii\caching\DbCache::cacheTable]] 对应的表。
* [[yii\caching\DummyCache]]: 仅作为一个缓存占位符,不实现任何真正的缓存功能。
这个组件的目的是为了简化那些需要查询缓存有效性的代码。例如,在开发中如果服务器没有实际的缓存支持,你就可以用它配置一个缓存组件。
一个真正的缓存服务启用后,就可以切换为使用相应的缓存组件。两种条件下你都可以使用同样的代码
`Yii::$app->cache->get($key)` 尝试从缓存中取回数据而不用担心 `Yii::$app->cache` 可能是 `null`
* [[yii\caching\DummyCache]]: 仅作为一个缓存占位符,不实现任何真正的缓存功能。 这个组件的目的是为了简化那些需要查询缓存有效性的代码。例如,在开发中如果服务器没有实际的缓存支持,你就可以用它配置一个缓存组件。 一个真正的缓存服务启用后,就可以切换为使用相应的缓存组件。两种条件下你都可以使用同样的代码
`Yii::$app->cache->get($key)` 尝试从缓存中取回数据而不用担心 `Yii::$app->cache` 可能是 `null`
* [[yii\caching\FileCache]]: 使用标准文件存储缓存数据。这个特别适用于缓存大块数据,例如一个网页的内容。
* [[yii\caching\MemCache]]: 使用 PHP [memcache](http://php.net/manual/en/book.memcache.php)
[memcached](http://php.net/manual/en/book.memcached.php) 扩展。这个选项可以认为是分布式应用程序环境中(例如:多台服务器,有负载均衡等)最快的缓存方案。
......
别名(Aliases)
=======
别名(译者注:指路径/URL 别名,简称别名)用作代表文件路径和 URL,主要为了避免在代码中硬编码一些绝对路径和
URL。一个别名必须以 `@` 字符开头,以区别于传统的文件/目录路径或 URL。举栗,别名 `@yii`
指的是 Yii 框架本身的安装目录,而 `@web` 表示的是当前运行应用的根 URL(base URL)。
定义别名 <a name="defining-aliases"></a>
----------------
你可以调用 [[Yii::setAlias()]] 来给指定路径/URL 定义别名。栗子:
```php
// 文件路径的别名
Yii::setAlias('@foo', '/path/to/foo');
// URL 的别名
Yii::setAlias('@bar', 'http://www.example.com');
```
> 注意:别名所指向的文件路径或 URL 不一定是真实存在的文件或资源哦。
用一个别名,你能通过在后面接续斜杠 `/` 以及若干路径片段得到一个新的别名(无需调用
[[Yii::setAlias()]])。我们把通过 [[Yii::setAlias()]] 定义的别名成为根别名
*root aliases*,而用他们衍生出去的别名成为衍生别名 *derived aliases*。比如,`@foo` 就是跟别名,而 `@foo/bar/file.php`
是一个衍生别名。
你还可以用别名定义新别名(根别名与衍生别名均可):
```php
Yii::setAlias('@foobar', '@foo/bar');
```
根别名通常在 [引导(bootstrapping)](runtime-bootstrapping.md) 阶段定义。比如你可以在
[入口脚本](structure-entry-scripts.md) 里调用 [[Yii::setAlias()]]。为了方便起见呢,[应用主体(Application)](structure-applications.md)
提供了一个名为 `aliases` 的可写属性,你可以在应用[配置文件](concept-configurations.md)中设置它,就像这样:
```php
return [
// ...
'aliases' => [
'@foo' => '/path/to/foo',
'@bar' => 'http://www.example.com',
],
];
```
解析别名 <a name="resolving-aliases"></a>
-----------------
你可以调用 [[Yii::getAlias()]] 命令来解析一个根别名到他所对应的文件路径或 URL。同样的页面也可以用于解析衍生别名。比如:
```php
echo Yii::getAlias('@foo'); // 显示:/path/to/foo
echo Yii::getAlias('@bar'); // 显示:http://www.example.com
echo Yii::getAlias('@foo/bar/file.php'); // 显示:/path/to/foo/bar/file.php
```
由衍生别名所代指的路径/URL 是通过替换掉衍生别名中的根别名部分得到的。
> 注意:[[Yii::getAlias()]] 不检查结果路径/URL 所指向的资源是否真实存在。
根别名可能也会包含斜杠 `/` 字符。[[Yii::getAlias()]] 足够聪明,能知道一个别名中的哪个部分是根别名,因此能正确解析文件路径/URL。比如:
```php
Yii::setAlias('@foo', '/path/to/foo');
Yii::setAlias('@foo/bar', '/path2/bar');
Yii::getAlias('@foo/test/file.php'); // 显示:/path/to/foo/test/file.php
Yii::getAlias('@foo/bar/file.php'); // 显示:/path2/bar/file.php
```
`@foo/bar` 未被定义为根别名,最后一行语句会显示为 `/path/to/foo/bar/file.php`
使用别名 <a name="using-aliases"></a>
-------------
别名在 Yii 的很多地方都会被正确识别,而无需调用 [[Yii::getAlias()]]
来把它们转换为路径/URL。比如,[[yii\caching\FileCache::cachePath]] 能同时接受文件路径或是代表文件路径的别名,多亏了 `@` 前缀,它区分开了文件路径与别名。
```php
use yii\caching\FileCache;
$cache = new FileCache([
'cachePath' => '@runtime/cache',
]);
```
请关注下 API 文档了解属性或方法参数是否支持别名。
预定义的别名 <a name="predefined-aliases"></a>
------------------
Yii 预定义了一系列别名来简化频繁引用常用路径和 URL的需求。
在核心框架中已经预定义有以下别名:
- `@yii` - `BaseYii.php` 文件所在的目录(也被称为框架安装目录)
- `@app` - 当前运行的应用 [[yii\base\Application::basePath|根路径(base path)]]
- `@runtime` - 当前运行的应用的 [[yii\base\Application::runtimePath|运行环境(runtime)路径]]
- `@vendor` - [[yii\base\Application::vendorPath|Composer 供应商目录]]
- `@webroot` - 当前运行应用的 Web 入口目录
- `@web` - 当前运行应用的根 URL
`@yii` 别名是在[入口脚本](structure-entry-scripts.md)里包含 `Yii.php` 文件时定义的,其他的别名都是在[配置应用](concept-configurations.md)的时候,于应用的构造器内定义的。
扩展的别名 <a name="extension-aliases"></a>
-----------------
每一个通过 Composer 安装的 [扩展](structure-extensions.md) 都自动添加了一个别名。该别名会以该扩展在 `composer.json`
文件中所声明的根命名空间为名,且他直接代指该包的根目录。比如,如果你安装有 `yiisoft/yii2-jui` 扩展,你会自动得到
`@yii/jui` 别名,它定义于[引导启动](runtime-bootstrapping.md)阶段:
```php
Yii::setAlias('@yii/jui', 'VendorPath/yiisoft/yii2-jui');
```
\ No newline at end of file
类自动加载(Autoloading)
=================
Yii 依靠[类自动加载机制(http://www.php.net/manual/en/language.oop5.autoload.php)来定位和包含所需的类文件。它提供一个高性能且完美支持[PSR-4 标准](https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md)[中文汉化](https://github.com/hfcorriez/fig-standards/blob/zh_CN/%E6%8E%A5%E5%8F%97/PSR-4-autoloader.md))的自动加载器。该自动加载器会在包含 `Yii.php` 文件时安装好。
> 注意:为了简化叙述,本篇文档中我们只会提及类的自动加载。不过,要记得文中的描述同样也适用于接口和Trait(特质)的自动加载哦。
使用 Yii 自动加载器 <a name="using-yii-autoloader"></a>
------------------------
要使用 Yii 的类自动加载器,你需要在创建和命名尼德类的时候遵循两个简单的规则:
* 每个类都必须置于命名空间之下 (比如 `foo\bar\MyClass`)。
* 每个类都必须保存为单独文件,且其完整路径能用以下算法取得:
```php
// $className 是一个开头包含反斜杠的完整类名(译者注:请自行谷歌:fully qualified class name)
$classFile = Yii::getAlias('@' . str_replace('\\', '/', $className) . '.php');
```
举例来说,若某个类名为 `foo\bar\MyClass`,对应类的文件路径[别名](concept-aliases.md)会是
`@foo/bar/MyClass.php`。为了让该别名能被正确解析为文件路径,`@foo``@foo/bar`
中的一个必须是[根别名](concept-aliases.md#defining-aliases)
当我们使用[基本应用模版](start-basic.md)时,你可以把你的类放置在顶级命名空间 `app` 下,这样它们就可以被 Yii
自动加载,而无需定义一个新的别名。这是因为 `@app` 本身是一个[预定义别名](concept-aliases.md#predefined-aliases),且类似于 `app\components\MyClass` 这样的类名,基于我们刚才所提到的算法,可以正确解析出 `AppBasePath/components/MyClass.php` 路径。
[高级应用模版](tutorial-advanced-app.md)里,每一逻辑层级会使用他自己的根别名。比如,在前端层,会使用 `@frontend`
而后端层会使用 `@backend`。因此,你可以把前端的类放在 `frontend` 命名空间,而后端的类放在 `backend`。 这样这些类就可以被 Yii 自动加载了。
类映射表(Class Map) <a name="class-map"></a>
---------
Yii 类自动加载器支持 **类映射表** 功能,该功能会建立一个从类的名字到类文件路径的映射。当自动加载器加载一个文件时,他首先检查映射表里有没有该类。如果有,对应的文件路径就直接加载了,省掉了进一步的检查。它可以让类的自动加载变得炒鸡快!事实上,所有的 Yii 核心类都是这样加载的。
你可以用 `Yii::$classMap` 方法向映射表中添加类,
```php
Yii::$classMap['foo\bar\MyClass'] = 'path/to/MyClass.php';
```
[别名](concept-aliases.md)可以被用于指定类文件的路径。你应该在[引导启动](runtime-bootstrapping.md)的过程中设置类映射表,这样映射表就可以在你使用具体类之前就准备好。
用其他自动加载器 <a name="using-other-autoloaders"></a>
-----------------------
因为 Yii 完全支持 Composer 成为一个依赖包管理器,所以推荐你也同时安装 Composer 的自动加载器,如果你用了一些自带自动加载器的第三方类库,你应该也安装下它们。
在你同时使用其他自动加载器和 Yii 自动加载器的时候,你应该在其他自动加载器安装成功 **之后**,再包含`Yii.php`
文件。这将使 Yii 成为第一个响应任何类自动加载请求的自动加载器。举例来说,以下代码提取自[基本应用模版](start-basic.md)[入口脚本](structure-entry-scripts.md) 。第一行安装了 Composer 的自动加载器,第二行才是 Yii 的自动加载器:
```php
require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
```
你也可以只使用 Composer 的自动加载,而不用 Yii 的自动加载。不过这样做的话,类的加载效率会下降,且你必须遵循 Composer 所设定的规则,从而让你的类满足可以被自动加载的要求。
> 补充:若你不想要使用 Yii 的自动加载器,你必须创建一个你自己版本的 `Yii.php` 文件,并把它包含进你的[入口脚本](structure-entry-scripts.md)里。
自动加载扩展类 <a name="autoloading-extension-classes"></a>
-----------------------------
Yii 自动加载器支持自动加载[扩展](structure-extensions.md)的类。唯一的要求是它需要在 `composer.json`
文件里正确地定义 `autoload` 部分。请参考 [Composer 文档(英文)](https://getcomposer.org/doc/04-schema.md#autoload)[中文汉化](https://github.com/5-say/composer-doc-cn/blob/master/cn-introduction/04-schema.md#autoload)),来了解如何正确描述 `autoload` 的更多细节。
在你不使用 Yii 的自动加载器时,Composer 的自动加载器仍然可以帮你自动加载扩展内的类。
\ No newline at end of file
从 Yii 1.1 升级
===============
因为 2.0 框架是完完全全的重写,所以在 1.1 和 2.0 两个版本之间,存在了很多不同之处。因此,从 1.1 版本升级的过程并不像小版本间的跨越那么简单,在本手册中你将会了解两个版本间主要的不同之处。
2.0 版框架是完全重写的,在 1.1 和 2.0 两个版本之间存在相当多差异。因此从 1.1 版升级并不像小版本间的跨越那么简单,通过本指南你将会了解两个版本间主要的不同之处。
如果你原先没有用过 Yii 1.1, 你可以直接跳过本章,直接从"[入门篇](start-installation.md)"开始读起。
如果你之前没有用过 Yii 1.1,可以跳过本章,直接从"[入门篇](start-installation.md)"开始读起。
请注意,Yii 2.0 引入了很多这篇总结文章并没有涉及到的新功能。我们强烈建议你通读整部权威手册,来了解所有新功能新特色。这样你将有机会发现一些以前你可能要自己开发的功能,而现在他们很可能已经被包含在核心代码中了也说不定。
请注意,Yii 2.0 引入了很多本章并没有涉及到的新功能。强烈建议你通读整部权威指南来了解所有新特性。这样有可能会发现一些以前你要自己开发的功能,而现在已经被包含在核心代码中了。
安装
------------
Yii 2.0 完全拥抱 [Composer](https://getcomposer.org/) 的使用,它其实是实际上的 PHP
包管理器。核心框架以及扩展的安装,都通过 Composer 来处理。想要了解更多如何安装 Yii 2.0
请参阅本指南的 [安装 Yii](start-installation.md) 章节。如果你想创建新的扩展,或者把你已有的 Yii 1.1 的扩展改写成兼容
2.0 的版本,你可以参考 [创建扩展](extend-creating-extensions.md) 章节。
Yii 2.0 完全拥抱 [Composer](https://getcomposer.org/),它是事实上的 PHP 包管理工具。核心框架以及扩展的安装都通过 Composer 来处理。想要了解更多如何安装 Yii 2.0 请参阅本指南的 [安装 Yii](start-installation.md) 章节。如果你想创建新扩展,或者把你已有的 Yii 1.1 的扩展改写成兼容 2.0 的版本,你可以参考 [创建扩展](extend-creating-extensions.md) 章节。
PHP 需求
----------------
Yii 2.0 需求 PHP 5.4 或以上版本,该版本相对于 Yii 1.1 所需求的 PHP 5.2
而言是一个巨大的改进。也因此,在语言层面上有很多的值得注意的不同之处。
下面是在 PHP 层级发生的主要变化的一个小汇总:
Yii 2.0 需要 PHP 5.4 或更高版本,该版本相对于 Yii 1.1 所需求的 PHP 5.2 而言有巨大的改进。因此在语言层面上有很多的值得注意的不同之处。下面是 PHP 层的主要变化汇总:
- [命名空间](http://php.net/manual/zh/language.namespaces.php)
- [匿名函数](http://php.net/manual/zh/functions.anonymous.php)
- 数组短语法 `[...元素...]` 用于取代 `array(...元素...)`
- 短格式的 echo 标签 `<?=` 现被用于视图文件,它自 PHP 5.4 起总会被识别并且合法,而不管 short_open_tag 的设置是什么,可以安全地调用
- 视图文件中的短格式 echo 标签 `<?=`,自 PHP 5.4 起总会被识别并且合法,无论 short_open_tag 的设置是什么,可以安全使用。
- [SPL 类和接口](http://php.net/manual/zh/book.spl.php)
- [延迟静态绑定](http://php.net/manual/zh/language.oop5.late-static-bindings.php)
- [日期和时间](http://php.net/manual/zh/book.datetime.php)
- [Traits(术语翻译未定:特征或特质)](http://php.net/manual/zh/language.oop5.traits.php)
- [intl](http://php.net/manual/zh/book.intl.php) Yii 2.0 使用 `intl` PHP 扩展来支持国际化的相关功能
- [Traits](http://php.net/manual/zh/language.oop5.traits.php)
- [intl](http://php.net/manual/zh/book.intl.php) Yii 2.0 使用 PHP 扩展 `intl` 来支持国际化的相关功能。
命名空间
---------
Yii 2.0 里最明显的改动就数命名空间的使用了。几乎每一个核心类都引入了命名空间,比如
`yii\web\Request`。原本用于类名前缀的字母“C”已经不再使用了。当前的命名规范与目录结构相吻合。比如,
`yii\web\Request` 就表明对应的类文件是 Yii 框架文件夹下的 `web/Request.php` 文件。
Yii 2.0 里最明显的改动就数命名空间的使用了。几乎每一个核心类都引入了命名空间,比如 `yii\web\Request`。1.1 版用于类名前的字母 “C” 已经不再使用。当前的命名规范与目录结构相吻合。例如,`yii\web\Request` 就表明对应的类文件是 Yii 框架文件夹下的 `web/Request.php` 文件。
(有了 Yii 的类自动加载器,你不需要明确包含那个具体文件的情况下,也能照常使用全部核心类。)
(有了 Yii 的类自动加载器,你可以直接使用全部核心类而不需要显式包含具体文件。)
组件(Component)与对象(Object)
--------------------
Yii 2.0 把 1.1里的 `CComponent` 类拆分成了两个类: [[yii\base\Object]] 和 [[yii\base\Component]]。[[yii\base\Object|Object]]
类是一个轻量级的基类,你可以通过 getters 和 setters 来定义 [object 的属性](concept-properties.md)[[yii\base\Component|Component]]
类继承自 [[yii\base\Object|Object]],同时还进一步支持 [事件](concept-events.md)[行为](concept-behaviors.md)
Yii 2.0 把 1.1 里的 `CComponent` 类拆分成了两个类:[[yii\base\Object]] 和 [[yii\base\Component]]。[[yii\base\Object|Object]] 类是一个轻量级的基类,你可以通过 getters 和 setters 来定义 [object 的属性](concept-properties.md)[[yii\base\Component|Component]] 类继承自 [[yii\base\Object|Object]],同时进一步支持 [事件](concept-events.md)[行为](concept-behaviors.md)
如果你的类不需要用到事件或行为的功能,你应该考虑使用 [[yii\base\Object|Object]] 类作为基类。这通常是需要代表基本数据结构的类。
如果你不需要用到事件或行为,应该考虑使用 [[yii\base\Object|Object]] 类作为基类。这通常是表示基本数据结构的类。
配置对象
对象的配置
--------------------
[[yii\base\Object|Object]] 类引入了一种统一的配置对象的方法。所有 [[yii\base\Object|Object]]
的子类都应该用以下方法声明它的构造器(如果需要的话),以正确配置它自身:
[[yii\base\Object|Object]] 类引入了一种统一对象配置的方法。所有 [[yii\base\Object|Object]] 的子类都应该用以下方法声明它的构造方法(如果需要的话),以正确配置它自身:
```php
class MyClass extends \yii\base\Object
......@@ -81,8 +70,7 @@ class MyClass extends \yii\base\Object
}
```
在上面的例子里,构造器的最后一个参数必须输入一个配置数组,包含一系列用于在构造器的结尾初始化相关属性的键值对。你可以重写
[[yii\base\Object::init()|init()]] 方法来执行一些需要在配置生效后进行的初始化工作。
在上面的例子里,构造方法的最后一个参数必须输入一个配置数组,包含一系列用于在方法结尾初始化相关属性的键值对。你可以重写 [[yii\base\Object::init()|init()]] 方法来执行一些需要在配置生效后进行的初始化工作。
你可以通过遵循以下约定俗成的编码习惯,来使用配置数组创建并配置新的对象:
......@@ -94,14 +82,13 @@ $object = Yii::createObject([
], [$param1, $param2]);
```
更多有关配置的细节可以在 [对象配置](concept-configurations.md) 章节找到。
更多有关配置的细节可以在[配置](concept-configurations.md)章节找到。
事件(Event)
------
在 Yii 1 里,我们通常通过定义 `on` 开头的方法 (比如 `onBeforeSave`),来创建事件。而在 Yii 2 中,你可以使用任意的事件名了。同时通过调用
[[yii\base\Component::trigger()|trigger()]] 方法来触发相关事件:
在 Yii 1 中,通常通过定义 `on` 开头的方法(例如 `onBeforeSave`)来创建事件。而在 Yii 2 中,你可以使用任意的事件名了。同时通过调用 [[yii\base\Component::trigger()|trigger()]] 方法来触发相关事件:
```php
$event = new \yii\base\Event;
......@@ -116,21 +103,15 @@ $component->on($eventName, $handler);
// $component->off($eventName, $handler);
```
其实事件功能还有更多改进之处。要了解它们,请查看 [事件(Event)](concept-events.md) 章节。
事件功能还有更多增强之处。要了解它们,请查看[事件](concept-events.md)章节。
路径别名(Path Alias)
------------
Yii 2.0 扩展类路径别名的应用,文件/目录路径和 URLs 都可以使用路径别名啦。Yii 2.0
中路径别名必须以 `@` 符号开头,以区别于普通文件目录路径或 URL。
比如,`@yii` 就是指向 Yii 安装目录别名。路径别名现在被绝大多数的 Yii 核心代码所支持。比如
[[yii\caching\FileCache::cachePath]] 就同时支持输入一个路径别名或一个普通的目录地址。
Yii 2.0 将路径别名的应用扩大至文件/目录路径和 URL。Yii 2.0 中路径别名必须以 `@` 符号开头,以区别于普通文件目录路径或 URL。例如 `@yii` 就是指向 Yii 安装目录的别名。绝大多数 Yii 核心代码都支持别名。例如 [[yii\caching\FileCache::cachePath]] 就同时支持路径别名或普通的目录地址。
路径别名也和类的命名空间密切相关。建议给每一个根命名空间定义一个路径别名,从而无须额外配置,便可启动 Yii
的类自动加载机制。比如,因为有 `@yii` 指向 Yii 安装目录,那类似 `yii\web\Request`
的类就能被 Yii 自动加载。同理,若你用了一个第三方的类库,比如 Zend 框架,你只需定义一个名为 `@Zend`
的路径别名,去指向该框架的安装目录。之后,Yii 就可以自动加载任意 Zend Framework Library 中的类了。
路径别名也和类的命名空间密切相关。建议给每一个根命名空间定义一个路径别名,从而无须额外配置,便可启动 Yii 的类自动加载机制。例如,因为有 `@yii` 指向 Yii 安装目录,那类似 `yii\web\Request` 的类就能被 Yii 自动加载。同理,若你用了一个第三方的类库,如 Zend Framework,你只需定义一个名为 `@Zend` 的路径别名指向该框架的安装目录。之后 Yii 就可以自动加载任意 Zend Framework 中的类了。
更多路径别名信息请参阅[路径别名](concept-aliases.md)章节。
......@@ -138,30 +119,23 @@ Yii 2.0 謇ゥ螻慕アサ霍ッ蠕悪蜷咲噪蠎皮畑梧枚莉カ/逶ョ蠖戊キッ蠕柱 URLs 驛ス蜿ッ莉・菴
视图(View)
-----
Yii 2 的视图最显著的改动是视图内的特殊变量 `$this` 不再指向当前控制器或小部件,而是指向 *视图* 对象。它是一个 2.0
中引入的全新概念。*视图* 对象为 [[yii\web\View]] 的实例,他代表了 MVC 模式中的视图部分。如果你想要在视图中访问一个控制器或者小部件,你可以使用
`$this->context`
Yii 2 中视图最明显的改动是视图内的特殊变量 `$this` 不再指向当前控制器或小部件,而是指向**视图**对象,它是 2.0 中引入的全新概念。**视图**对象为 [[yii\web\View]] 的实例,他代表了 MVC 模式中的视图部分。如果你想要在视图中访问一个控制器或小部件,可以使用 `$this->context`
要在其他视图里渲染一个局部视图,你要用 `$this->render()`,而不是 `$this->renderPartial()``render` 的调用也发成了变化,因为
`render()` 现在只返回渲染结果,而不是直接显示它,所以现在你必须显式地把它 **echo** 出来。像这样:
要在其他视图里渲染一个局部视图,使用 `$this->render()`,而不是 `$this->renderPartial()``render()` 现在只返回渲染结果,而不是直接显示它,所以现在你必须显式地把它 **echo** 出来。像这样:
```php
echo $this->render('_item', ['item' => $item]);
```
除了使用 PHP 作为主要的模板语言,Yii 2.0 也装备了两种时髦模板引擎的官方支持:Smarty 和 Twig。过去的 Prado
模板引擎不再被支持。要使用这些模板引擎,你需要配置 `view` 应用组件,给它设置 [[yii\base\View::$renderers|View::$renderers]]
属性。具体请参阅[模板引擎](tutorial-template-engines.md)章节。
除了使用 PHP 作为主要的模板语言,Yii 2.0 也装备了两种流行模板引擎的官方支持:Smarty 和 Twig。过去的 Prado 模板引擎不再被支持。要使用这些模板引擎,你需要配置 `view` 应用组件,给它设置 [[yii\base\View::$renderers|View::$renderers]] 属性。具体请参阅[模板引擎](tutorial-template-engines.md)章节。
模型(Model)
------
Yii 2.0使用 [[yii\base\Model]] 作为模型基类,类似于1.1的 `CModel``CFormModel`
被完全弃用了,现在要创建表单模型类,可以通过继承 [[yii\base\Model]] 类来实现。
Yii 2.0 使用 [[yii\base\Model]] 作为模型基类,类似于 1.1 的 `CModel``CFormModel` 被完全弃用了,现在要创建表单模型类,可以通过继承 [[yii\base\Model]] 类来实现。
Yii 2.0 引进了名为 [[yii\base\Model::scenarios()|scenarios()]]
的新方法来声明支持的场景,并注明在哪个场景下某属性赋值必须验证,可否被视为安全赋值,等等。如:
Yii 2.0 引进了名为 [[yii\base\Model::scenarios()|scenarios()]] 的新方法来声明支持的场景,并指明在哪个场景下某属性必须经过验证,可否被视为安全值等等。如:
```php
public function scenarios()
......@@ -173,24 +147,20 @@ public function scenarios()
}
```
上面的代码声明了两个场景:`backend``frontend` 。对于 `backend` 场景,`email``role`
属性值都是安全的,且能进行批量赋值;对于 `frontend` 场景,`email` 能批量赋值而 `role` 不能。而 `email``role` 都必须通过规则验证。
上面的代码声明了两个场景:`backend``frontend` 。对于 `backend` 场景,`email``role` 属性值都是安全的,且能进行批量赋值。对于 `frontend` 场景,`email` 能批量赋值而 `role` 不能。 `email``role` 都必须通过规则验证。
[[yii\base\Model::rules()|rules()]] 方法仍用于声明验证规则。注意,由于引进了 [[yii\base\Model::scenarios()|scenarios()]]
,现在已经没有 `unsafe` 验证器了。
[[yii\base\Model::rules()|rules()]] 方法仍用于声明验证规则。注意,由于引入了 [[yii\base\Model::scenarios()|scenarios()]],现在已经没有 `unsafe` 验证器了。
大多数情况下,如果 [[yii\base\Model::rules()|rules()]] 方法内已经完整地指定场景了,那就不必覆写 [[yii\base\Model::scenarios()|scenarios()]]
,也不必声明 `unsafe` 属性值。
大多数情况下,如果 [[yii\base\Model::rules()|rules()]] 方法内已经完整地指定场景了,那就不必覆写 [[yii\base\Model::scenarios()|scenarios()]],也不必声明 `unsafe` 属性值。
要了解更多有关模型的细节,请参考[模型](structure-models.md)章节。
控制器(Controller)
-----------
Yii 2.0 使用 [[yii\web\Controller]] 作为控制器的基类,类似于 1.1 的 `CWebController`。使用 [[yii\base\Action]]
作为操作类的基类。
Yii 2.0 使用 [[yii\web\Controller]] 作为控制器的基类,类似于 1.1 的 `CWebController`。使用 [[yii\base\Action]] 作为操作类的基类。
这些变化最明显的影响是,当你在写控制器操作的代码时,你应该返回(return)要渲染的内容而不是输出(echo)它:
这些变化最明显的影响是,当你在写控制器操作的代码时,应该返回(return)要渲染的内容而不是输出(echo)它:
```php
public function actionView($id)
......@@ -210,10 +180,9 @@ public function actionView($id)
小部件(Widget)
-------
Yii 2.0 使用 [[yii\base\Widget]] 作为小部件基类,类似于1.1的 `CWidget`
Yii 2.0 使用 [[yii\base\Widget]] 作为小部件基类,类似于 1.1 的 `CWidget`
为了让 IDE 更好地支持框架,Yii 2.0 引进了一个调用小部件的新语法。就是引入了 [[yii\base\Widget::begin()|begin()]], [[yii\base\Widget::end()|end()]]
[[yii\base\Widget::widget()|widget()]] 三个静态方法,用法如下:
为了让框架获得更好的 IDE 支持,Yii 2.0 引进了一个调用小部件的新语法。包含 [[yii\base\Widget::begin()|begin()]],[[yii\base\Widget::end()|end()]] 和 [[yii\base\Widget::widget()|widget()]] 三个静态方法,用法如下:
```php
use yii\widgets\Menu;
......@@ -231,18 +200,15 @@ $form = ActiveForm::begin([
ActiveForm::end();
```
更多细节请参阅 [](structure-widgets.md)章节。
更多细节请参阅[小部件](structure-widgets.md)章节。
主题(Theme)
------
2.0 主题的运作方式跟以往完全不同了。它们现在基于一个
**路径映射机制**,该机制会把一个源视图文件的路径映射到一个主题视图文件路径。举例来说,如果路径映射为
`['/web/views' => '/web/themes/basic']`,那么 `/web/views/site/index.php` 视图的主题修饰版就会是
`/web/themes/basic/site/index.php`。也因此让主题现在可以应用在任何视图文件之上,甚至是渲染于控制器或小部件的上下文环境之外的视图文件。
2.0 主题的运作方式跟以往完全不同了。它们现在基于**路径映射机制**,该机制会把一个源视图文件的路径映射到一个主题视图文件路径。举例来说,如果路径映射为 `['/web/views' => '/web/themes/basic']`,那么 `/web/views/site/index.php` 视图经过主题修饰的版本就会是 `/web/themes/basic/site/index.php`。也因此让主题现在可以应用在任何视图文件之上,甚至是渲染控制器上下文环境之外的视图文件或小部件。
同样,`CThemeManager` 组件已经被移除了。取而代之的是,`theme` 成为`view` 应用组件的一个可配置属性。
同样,`CThemeManager` 组件已经被移除了。取而代之的 `theme` 成为`view` 应用组件的一个可配置属性。
更多细节请参考[主题](output-theming.md)章节。
......@@ -250,13 +216,11 @@ ActiveForm::end();
控制台应用(Console Application)
--------------------
控制台应用现在如普通的 Web 应用程序一样,由控制器组成,控制台的控制器继承自 [[yii\console\Controller]]
,类似于1.1的 `CConsoleCommand`
控制台应用现在如普通的 Web 应用程序一样,由控制器组成,控制台的控制器继承自 [[yii\console\Controller]],类似于 1.1 的 `CConsoleCommand`
运行控制台命令使用 `yii <route>`,其中 `<route>` 代表控制器的路由(如 `sitemap/index`)。额外的匿名参数传递到对应的控制器操作,而有名的参数根据
[[yii\console\Controller::options()]] 的声明来解析。
运行控制台命令使用 `yii <route>`,其中 `<route>` 代表控制器的路由(如 `sitemap/index`)。额外的匿名参数传递到对应的控制器操作方法,而有名的参数根据 [[yii\console\Controller::options()]] 的声明来解析。
Yii 2.0 支持基于代码注释自动生成相关命令的帮助(help)信息。
Yii 2.0 支持基于代码注释自动生成相的关命令行帮助(help)信息
更多细节请参阅[控制台命令](tutorial-console.md)章节。
......@@ -264,7 +228,7 @@ Yii 2.0 謾ッ謖∝渕莠惹サ」遐∵ウィ驥願蜉ィ逕滓逶ク蜈ウ蜻ス莉、逧クョ蜉ゥelp我ソ。諱
国际化(I18N)
----
Yii 2.0 移除了原来内置的日期格式器和数字格式器,为了方便 [PECL intl PHP module](http://pecl.php.net/package/intl) (PHP 的国际化扩展)模块的使用。
Yii 2.0 移除了原来内置的日期格式器和数字格式器,为了支持 [PECL intl PHP module](http://pecl.php.net/package/intl)(PHP 的国际化扩展)的使用。
消息翻译现在由 `i18n` 应用组件执行。该组件管理一系列消息源,允许使用基于消息类别的不同消息源。
......@@ -274,9 +238,7 @@ Yii 2.0 遘サ髯、莠次譚・蜀スョ逧律譛滓シ蠑丞勣蜥梧焚蟄玲シ蠑丞勣御クコ莠婿萓ソ
操作过滤器(Action Filters)
--------------
操作的过滤现在通过行为(behavior)来实现。要定义一个新的,自定义的过滤器,请继承 [[yii\base\ActionFilter]]
类。要使用一个过滤器,需要把过滤器类作为一个 `behavior` 绑定到控制器上。比如,要使用 [[yii\filters\AccessControl]]
过滤器,你需要在控制器内添加如下代码:
操作的过滤现在通过行为(behavior)来实现。要定义一个新的,自定义的过滤器,请继承 [[yii\base\ActionFilter]] 类。要使用一个过滤器,需要把过滤器类作为一个 `behavior` 绑定到控制器上。例如,要使用 [[yii\filters\AccessControl]] 过滤器,你需要在控制器内添加如下代码:
```php
public function behaviors()
......@@ -298,11 +260,9 @@ public function behaviors()
前端资源(Assets)
------
Yii 2.0 引入了一个新的概念,称为 *资源包*(Asset Bundle),以代替 1.1 的脚本包概念。
Yii 2.0 引入了一个新的概念,称为**资源包**(Asset Bundle),以代替 1.1 的脚本包概念。
一个资源包是一个目录下的资源文件集合(如 JavaScript 文件、CSS 文件、图片文件等)。每一个资源包被表示为一个类,该类继承自
[[yii\web\AssetBundle]]。用 [[yii\web\AssetBundle::register()]] 方法注册一个资源包后,就使它的资源可被 Web
访问,注册了资源包的页面会自动包含和引用资源包内指定的 JS 和 CSS 文件。
一个资源包是一个目录下的资源文件集合(如 JavaScript 文件、CSS 文件、图片文件等)。每一个资源包被表示为一个类,该类继承自 [[yii\web\AssetBundle]]。用 [[yii\web\AssetBundle::register()]] 方法注册一个资源包后,就使它的资源可被 Web 访问了,注册了资源包的页面会自动包含和引用资源包内指定的 JS 和 CSS 文件。
更多细节请参阅 [前端资源管理(Asset)](structure-assets.md) 章节。
......@@ -318,15 +278,12 @@ Yii 2.0 蠕亥、壼クク逕ィ逧撕諤∝勧謇狗アサ悟桁諡ャ
* [[yii\helpers\FileHelper]]
* [[yii\helpers\Json]]
请参考 [手一览](helper-overview.md) 章节来了解更多。
请参考[手一览](helper-overview.md) 章节来了解更多。
表单
-----
Yii 2.0 引进了 *表单栏(field)* 的概念,用来创建一个基于 [[yii\widgets\ActiveForm]]
的表单。一个表单栏是一个由标签、输入框、错误消息(可能还有提示文字)组成的容器,被表示为 [[yii\widgets\ActiveField|ActiveField]] 对象。
使用表单栏建立表单的过程比以前更整洁利落:
Yii 2.0 引进了**表单栏(field)**的概念,用来创建一个基于 [[yii\widgets\ActiveForm]]的表单。一个表单栏是一个由标签、输入框、错误消息(可能还有提示文字)组成的容器,被表示为 [[yii\widgets\ActiveField|ActiveField]] 对象。使用表单栏建立表单的过程比以前更整洁利落:
```php
<?php $form = yii\widgets\ActiveForm::begin(); ?>
......@@ -338,17 +295,13 @@ Yii 2.0 蠑戊ソ帑コ *陦ィ蜊墓擾シield* 逧ヲょソオ檎畑譚・蛻帛サコ荳荳ェ蝓コ莠 [[
<?php yii\widgets\ActiveForm::end(); ?>
```
请参考 [创建表单](input-forms.md) 章节来了解更多细节。
请参考[创建表单](input-forms.md)章节来了解更多细节。
查询生成器(Query Builder)
-------------
Yii 1.1中,查询语句的构建分散在多个类中,包括`CDbCommand``CDbCriteria` 以及
`CDbCommandBuilder`。Yii 2.0 以 [[yii\db\Query|Query]] 对象的形式表示一个数据库查询,这个对象可以在
[[yii\db\QueryBuilder|QueryBuilder]] 的帮助下于幕后生成 SQL 语句。
例如:
Yii 1.1 中,查询语句的生成分散在多个类中,包括 `CDbCommand``CDbCriteria` 以及 `CDbCommandBuilder`。Yii 2.0 以 [[yii\db\Query|Query]] 对象的形式表示一个数据库查询,这个对象使用 [[yii\db\QueryBuilder|QueryBuilder]] 在幕后生成 SQL 语句。例如:
```php
$query = new \yii\db\Query();
......@@ -361,20 +314,17 @@ $sql = $command->sql;
$rows = $command->queryAll();
```
绝的是,这些查询生成方法还TM可以和[活动记录](db-active-record.md)配合使用
重要的是,这些查询生成方法还可以和[活动记录](db-active-record.md)配合使用。
请参考[查询生成器(Query Builder)](db-query-builder.md) 节了解更多内容。
请参考[查询生成器(Query Builder)](db-query-builder.md)章节了解更多内容。
活动记录(Active Record)
-------------
Yii 2.0 的[活动记录](db-active-record.md)改动了很多。两个最显而易见的改动分别涉及查询语句的构建(query
building)和关联查询的处理(relational query handling)。
Yii 2.0 的[活动记录](db-active-record.md)改动了很多。两个最显而易见的改动分别涉及查询语句的生成(query building)和关联查询的处理(relational query handling)。
在 1.1 中的 `CDbCriteria` 类在 Yii 2 中被 [[yii\db\ActiveQuery]] (活动查询)所替代。这个类是继承自
[[yii\db\Query]],因此也继承了所有查询生成方法。当需要开始拼装一个查询了,你可以调用 [[yii\db\ActiveRecord::find()]]
方法来开头:
1.1 中的 `CDbCriteria` 类在 Yii 2 中被 [[yii\db\ActiveQuery]] 所替代。这个类是继承自 [[yii\db\Query]],因此也继承了所有查询生成方法。开始拼装一个查询可以调用 [[yii\db\ActiveRecord::find()]] 方法进行:
```php
// 检索所有 *活动的* 客户和订单,并以 ID 排序:
......@@ -384,9 +334,7 @@ $customers = Customer::find()
->all();
```
要声明一个关联关系,只需简单地定义一个 getter 方法来返回一个 [[yii\db\ActiveQuery|ActiveQuery]]
对象。getter 方法定义的属性名(译者注:即 getOrders() 中的 orders)表示关联关系名。如,以下代码声明了一个名为 `orders`
的关系(1.1 中必须在 `relations()` 方法内声明关系):
要声明一个关联关系,只需简单地定义一个 getter 方法来返回一个 [[yii\db\ActiveQuery|ActiveQuery]] 对象。getter 方法定义的属性名(译者注:即 getOrders() 中的 orders)表示关联关系名。如,以下代码声明了一个名为 `orders` 的关系(1.1 中必须在 `relations()` 方法内声明关系):
```php
class Customer extends \yii\db\ActiveRecord
......@@ -397,24 +345,22 @@ class Customer extends \yii\db\ActiveRecord
}
}
```
现在你就可以通过调用 `$customer->orders`
来从关联表中访问所有用户的订单了。你还可以用以下代码进行一场,使用定制的查询条件执行的“即时演算”关联查询:
现在你就可以通过调用 `$customer->orders` 来访问关联表中某用户的订单了。你还可以用以下代码进行一场指定条件的实时关联查询:
```php
$orders = $customer->getOrders()->andWhere('status=1')->all();
```
当贪婪加载一段关联关系时,Yii 2.0 和 1.1 的运作机理并不相同。具体来说,在 1.1 中,为同时选出主表和关联记录,会生成一个 JOIN
查询。在 Yii 2.0 中会使用两个没有 JOIN 的 SQL 语句:第一条语句取回主表记录,第二条取回用主表记录的主键信息筛选后的关联记录。
当贪婪加载一段关联关系时,Yii 2.0 和 1.1 的运作机理并不相同。具体来说,在 1.1 中使用一条 JOIN 语句同时查询主表和关联表记录。在 Yii 2.0 中会使用两个没有 JOIN 的 SQL 语句:第一条语句取回主表记录,第二条通过主表记录经主键筛选后查询关联表记录。
构建会返回大量记录的查询时,可以添加 [[yii\db\ActiveQuery::asArray()|asArray()]] 方法链的方法,这样会以数组的形式返回查询结果,而不必返回
[[yii\db\ActiveRecord|ActiveRecord]] 对象,这能明显降低因大量记录读取所消耗的 CPU 时间和内存。如:
生成返回大量记录的查询时,可以链式书写 [[yii\db\ActiveQuery::asArray()|asArray()]] 方法,这样会以数组的形式返回查询结果,而不必返回
[[yii\db\ActiveRecord|ActiveRecord]] 对象,这能显著降低因大量记录读取所消耗的 CPU 时间和内存。如:
```php
$customers = Customer::find()->asArray()->all();
```
另一个改变是你不能再通过公共数据定义特性(Attribute)的默认值了。如果你需要这么做的话,你可以在你的记录类的 `init` 方法中设置它们。
另一个改变是你不能再通过公共数据定属性(Attribute)的默认值了。如果你需要这么做的话,可以在你的记录类的 `init` 方法中设置它们。
```php
public function init()
......@@ -424,27 +370,23 @@ public function init()
}
```
曾几何时,在 1.1 中重写一个活动记录类的构造器(Constructor)会导致一些问题。它们在 2.0
中不会再出现了。需要注意的是,如果你需要在构造器中添加一些参数,你恐怕必须重写 [[yii\db\ActiveRecord::instantiate()]] 方法。
曾几何时,在 1.1 中重写一个活动记录类的构造方法(Constructor)会导致一些问题。它们不会在 2.0 中出现了。需要注意的是,如果你需要在构造方法中添加一些参数,恐怕必须重写 [[yii\db\ActiveRecord::instantiate()]] 方法。
活动记录方面还有很多其他的变化与改进,请参考 [活动记录](db-active-record.md) 章节以了解更多细节。
活动记录方面还有很多其他的变化与改进,请参考[活动记录](db-active-record.md)章节以了解更多细节。
用户及身份验证接口(IdentityInterface)
-------------------------------------
1.1 中的 `CWebUser` 类现在被 [[yii\web\User]] 所取代,随之 `CUserIdentity` 类也不在了。与之相对的,为达到相同目的,你可以实现
[[yii\web\IdentityInterface]] 接口,它使用起来更直观。在高级应用模版里提供了一个这么样的一个例子。
1.1 中的 `CWebUser` 类现在被 [[yii\web\User]] 所取代,随之 `CUserIdentity` 类也不在了。与之相对的,为达到相同目的,你可以实现 [[yii\web\IdentityInterface]] 接口,它使用起来更直观。在高级应用模版里提供了一个这样的一个例子。
要了解更多细节请参考 [认证(Authentication)](security-authentication.md)[授权(Authorization)](security-authorization.md) 以及
[高级应用模版](tutorial-advanced-app.md) 这三个章节。
要了解更多细节请参考[认证(Authentication)](security-authentication.md)[授权(Authorization)](security-authorization.md)以及[高级应用模版](tutorial-advanced-app.md) 这三个章节。
URL 管理
--------
Yii 2.0 的 URL 管理跟 1.1 中很像。一个主要的改进是现在的 URL 管理支持 **可选参数** 了。比如,如果你在 2.0 中定义了一个下面这样的规则,那么它可以同时匹配
`post/popular``post/1/popular` 两种 URL。而在 1.1 中为达成相同效果,必须要使用两条规则。
Yii 2.0 的 URL 管理跟 1.1 中很像。一个主要的改进是现在的 URL 管理支持**可选参数**了。比如,如果你在 2.0 中定义了一个下面这样的规则,那么它可以同时匹配 `post/popular``post/1/popular` 两种 URL。而在 1.1 中为达成相同效果,必须要使用两条规则。
```php
[
......@@ -454,9 +396,9 @@ Yii 2.0 逧 URL 邂。逅キ 1.1 荳ュ蠕亥ワ縲ゆク荳ェ荳サ隕∫噪謾ケ霑帶弍邇ー蝨ィ逧 URL
]
```
请参考 [URL 解析和生成](runtime-url-handling.md) 章节,以了解更多细节。.
请参考[URL 解析和生成](runtime-url-handling.md) 章节,以了解更多细节。.
同时使用 Yii 1.1 和 2.x
----------------------
如果你遗留有一些 Yii 1.1 的代码,需要跟 Yii 2.0 一起使用,你可以参考 [1.1 和 2.0 共用](extend-using-v1-v2.md) 章节。
如果你有一些遗留的 Yii 1.1 代码,需要跟 Yii 2.0 一起使用,可以参考 [1.1 和 2.0 共用](extend-using-v1-v2.md)章节。
Yii 是什么
===========
Yii 是一个高性能的、基于组件的 PHP 框架,用于快速开发现代 Web 应用程序。名字 Yii (读作 `Yee``[ji:]`) 在汉语中的意
思是“简单、发展变化”。也可以看作是 **Yes It Is**! 的缩写。
Yii 是一个高性能,基于组件的 PHP 框架,用于快速开发现代 Web 应用程序。名字 Yii (读作
`易`)在中文里有“极致简单与不断变化”两重含义,也可看作 **Yes It Is**!的缩写
Yii 最适合做什么?
---------------------
Yii 是一个通用的 Web 编程框架,意味着它可以用于开发任意类型的 PHP Web 应用程序。由于它基于组件的架构和精致的缓存支持,它
特别适用于开发大型的应用程序,例门户,论坛,内容管理系统(CMS),电子商务项目,RESTful Web 服务等等。
Yii 是一个通用的 Web 编程框架,即可以用于开发各种基于 PHP 的
Web 应用。因为基于组件的框架结构和设计精巧的缓存支持,Yii 特别适合开发大型应用,如门户网站、论坛、内容管理系统(CMS)、电子商务项目和 RESTful Web 服务等。
Yii 和其他框架相比呢?
-------------------------------------------
- 和其他 PHP 框架类似,Yii 实现了 MVC(Model-View-Controller)设计模式并基于该模式组织代码。
- Yii 遵循一个哲学——代码要写的简单而又优雅。它永远不会为了要遵循某个设计模式而过度设计代码。
- Yii 是一个一站式框架,提供了大量经过验证的、入手可用的特性,例如:对关系型和NoSQL数据库都提供了查询构建器
(query builders)和 ActiveRecord;RESTful API 开发支持;多层缓存支持;还有更多。
- Yii 非常易于扩展。你可以自定义或替换几乎任何一处核心代码。你也会受益于它一致性的扩展架构,开发可再分发的扩展。
- 高性能始终是 Yii 的一个主要目标。
- Yii 的代码简洁优雅,这是 Yii 的编程哲学。它永远不会为了要迎合某个设计模式而对代码进行过度的设计。
- Yii 是一个全栈框架,提供了大量久经考验,开箱即用的特性,例如:对关系型和 NoSQL 数据库都提供了查询生成器(QueryBuilders)和 ActiveRecord;RESTful API 的开发支持;多层缓存支持;等等。
- Yii 非常易于扩展。你可以自定义或替换几乎任何一处核心代码。你还会受益于它坚实可靠的扩展架构,使用、再开发或再发布扩展。
- 高性能始终是 Yii 的首要目标之一。
Yii 不是一场独角戏,它有一个[强大的开发者团队][]提供支持,也有一个庞大的专家社区,持续不断地对Yii的开发作出贡献。
Yii 开发者团队始终对 Web 开发最新潮流和其他框架及项目中的优秀实践和特性保持密切的关注,其他地方出现的最相关优秀实践及
特性会被不定期的整合进核心框架中,并提供简单优雅的接口。
Yii 不是一场独角戏,它有一个[强大的开发者团队](http://www.yiiframework.com/about/)提供支持,也有一个庞大的专家社区,持续不断地对 Yii 的开发作出贡献。Yii 开发者团队始终对 Web 开发最新潮流和其他框架及项目中的最佳实践和特性保持密切的关注,那些有意义的最佳实践及特性会被不定期的整合进核心框架中,并提供简单优雅的接口。
[强大的开发者团队]: http://www.yiiframework.com/about/
Yii 版本
------------
Yii 当前有两个主要版本:1.1 和 2.0。 1.1 版是一个旧版本,现在处于维护状态。2.0是一个彻底重写的 Yii,采用了最新的技术和协
议,包括 Composer,PSR,命名空间,trait 等等。 2.0 版本代表了最新一代的框架,是未来几年中的主力开发版本。本指南主要基于
Yii 当前有两个主要版本:1.1 和 2.0。 1.1 版是上代的老版本,现在处于维护状态。2.0 版是一个完全重写的版本,采用了最新的技术和协议,包括依赖包管理器(Composer)、PHP 代码规范(PSR)、命名空间、Traits(特质)等等。 2.0 版代表了最新一代框架,是未来几年中我们的主要开发版本。本指南主要基于
2.0 版本编写。
系统要求和前置条件
系统要求和先决条件
------------------------------
Yii 2.0 需要 PHP 5.4.0 或以上版本支持。你可以通过运行任何 Yii 发行包中附带的系统要求检查器查看每个具体特性所需的 PHP 配
置。
使用 Yii 需要对面向对象编程(OOP)有基本的了解,因为 Yii 是一个纯面向对象的框架。
Yii 2.0 还是用了 PHP 的最新特性,例如 [命名空间](http://www.php.net/manual/en/language.namespaces.php)
[trait](http://www.php.net/manual/en/language.oop5.traits.php)
理解这些概念有助于你更快地掌握 Yii 2.0。
使用 Yii 需要对面向对象编程(OOP)有基本了解,因为 Yii 是一个纯面向对象的框架。Yii 2.0 还使用了 PHP 的最新特性,例如 [命名空间](http://www.php.net/manual/en/language.namespaces.php)
[Trait(特质)](http://www.php.net/manual/en/language.oop5.traits.php)。理解这些概念将有助于你更快地掌握 Yii 2.0。
安装 Yii
==============
你可以通过两种方式安装 Yii:使用 [Composer](http://getcomposer.org/) 或下载一个存档文件。推荐使用前者,
这样只需执行一条简单的命令就可以安装新的 [扩展](extend-creating-extensions.md) 或更新 Yii 了。
你可以通过两种方式安装 Yii:使用 [Composer](http://getcomposer.org/) 或下载一个归档文件。推荐使用前者,这样只需执行一条简单的命令就可以安装新的[扩展](extend-creating-extensions.md)或更新 Yii 了。
> 注意:和 Yii 1 版本不同,以标准方式安装 Yii 2 时会同时下载并安装框架本身和一个应用程序骨架。
> 注意:和 Yii 1 不同,以标准方式安装 Yii 2 时会同时下载并安装框架本身和一个应用程序骨架。
通过 Composer 安装 <a name="installing-via-composer"></a>
-----------------------
如果还没有安装 Composer,你可以按 [getcomposer.org](https://getcomposer.org/download/) 中的方法安装。
在 Linux 和 Mac OS X 中,可以运行如下命令安装:
如果还没有安装 Composer,你可以按 [getcomposer.org](https://getcomposer.org/download/) 中的方法安装。在 Linux 和 Mac OS X 中可以运行如下命令:
curl -s http://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
在 Windows 中,你需要下载并运行 [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe)
如果遇到了任何问题或者想更深入地学习 Composer,请参考 [Composer 文档(英文)](https://getcomposer.org/doc/)[Composer 中文](https://github.com/5-say/composer-doc-cn)
如果遇到任何问题或者想更深入地学习 Composer,请参考 [Composer 文档(英文)](https://getcomposer.org/doc/)[Composer 中文](https://github.com/5-say/composer-doc-cn)
Composer 安装后,切换到一个可通过 Web 访问的目录,执行如下命令即可安装 Yii :
......@@ -26,12 +24,11 @@ Composer 安装后,切换到一个可通过 Web 访问的目录,执行如下
如上命令会将 Yii 安装在一个名为 `basic` 的目录中。
> 技巧:如果你想安装 Yii 的最新开发版本,可以使用如下命令,它添加了一个
> [stability 选项](https://getcomposer.org/doc/04-schema.md#minimum-stability):
> 技巧:如果你想安装 Yii 的最新开发版本,可以使用如下命令,它添加了一个 [stability 选项](https://getcomposer.org/doc/04-schema.md#minimum-stability):
>
> composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic
>
> 注意,Yii 的开发版不应该用于生产环境中,因为它可能会破坏运行中的代码。.
> 注意,Yii 的开发版不应该用于生产环境中,它可能会破坏运行中的代码。
通过归档文件安装 <a name="installing-from-archive-file"></a>
......@@ -50,28 +47,24 @@ Composer 安装后,切换到一个可通过 Web 访问的目录,执行如下
但是还可以有其他的安装方式:
* 如果你只想安装核心框架,然后从头开始构建一个应用程序,可以参考
[从头构建自定义模版](tutorial-start-from-scratch.md) 一节的介绍。
* 如果你要开始一个更复杂的项目,更好的地适用于团队开发环境的,你可以考虑安装
[高级应用模版](tutorial-advanced-app.md).
* 如果你只想安装核心框架,然后从头开始创建一个应用程序,可以参考[从头构建自定义模版](tutorial-start-from-scratch.md)一节的介绍。
* 如果你要开发一个更复杂的应用,更好的地适用于团队开发环境的,可以考虑安装[高级应用模版](tutorial-advanced-app.md)
验证安装 <a name="verifying-installation"></a>
检查安装 <a name="verifying-installation"></a>
--------------------------
安装完成后,就可以使用浏览器通过如下 URL 访问刚安装完的 Yii 应用程序了:
安装完成后,就可以使用浏览器通过如下 URL 访问刚安装完的 Yii 应用了:
```
http://localhost/basic/web/index.php
```
这个 URL 假设你将 Yii 安装到了一个位于 Web 服务器文档根目录下的 `basic` 目录中,且该 Web 服务器正运行在你自己的电脑上
`localhost`)。你可能需要将其调整为自己的安装环境。
这个 URL 假设你将 Yii 安装到了一个位于 Web 服务器根目录下的 `basic` 目录中,且该 Web 服务器正运行在你自己的电脑上 (`localhost`)。你可能需要将其调整为适应自己的安装环境。
![Yii 安装成功](images/start-app-installed.png)
你应该可以在浏览器中看到如上所示的 "Congratulations!" 页面。如果没有,请检查你安装的 PHP 环境是否符合 Yii 的需求,
可以通过如下任意一种方式检查是否满足最小需求:
你应该可以在浏览器中看到如上所示的 “Congratulations!” 页面。如果没有,请检查你安装的 PHP 环境是否符合 Yii 的需求,可以通过如下任意一种方式检查是否满足最小需求:
* 通过浏览器访问 URL `http://localhost/basic/requirements.php`
* 执行如下命令:
......@@ -81,64 +74,56 @@ http://localhost/basic/web/index.php
php requirements.php
```
你需要配置好 PHP 安装环境,使其符合 Yii 的最小需求。最重要的是需要有 PHP 5.4 以上版本。如果你的应用程序需要用到数据库,那还要安装 [PDO PHP 扩展](http://www.php.net/manual/en/pdo.installation.php) 和相应的数据库驱动(例如访问 MySQL 数据库所需的 `pdo_mysql` )。
你需要配置好 PHP 安装环境,使其符合 Yii 的最小需求。最重要的是需要有 PHP 5.4 以上版本。如果应用需要用到数据库,那还要安装 [PDO PHP 扩展](http://www.php.net/manual/en/pdo.installation.php) 和相应的数据库驱动(例如访问 MySQL 数据库所需的 `pdo_mysql`)。
配置 Web 服务器 <a name="configuring-web-servers"></a>
-----------------------
>补充:如果你现在只是要试用 Yii 而不是要将其部署到生产环境中的服务器上,下面的这一节可以跳过。
>补充:如果你现在只是要试用 Yii 而不是要将其部署到生产环境中的服务器上,本小节可以跳过。
通过上述方法安装的应用程序在 Windows,Max OS X 或 Linux 中的 [Apache HTTP 服务器](http://httpd.apache.org/)
或者 [Nginx HTTP 服务器](http://nginx.org/) 上都可以直接运行。
通过上述方法安装的应用程序在 Windows,Max OS X, Linux 中的 [Apache HTTP 服务器](http://httpd.apache.org/)或 [Nginx HTTP 服务器](http://nginx.org/) 上都可以直接运行。
在生产环境的服务器上,你可能会想配置服务器让应用程序可以通过 URL `http://www.example.com/index.php` 访问而不是通过
`http://www.example.com/basic/web/index.php`。这种配置需要将 Web 服务器的文档根目录指向 `basic/web` 目录。
可能你还会想隐藏掉 URL 中的 `index.php`,[URL 解析和生成](runtime-url-handling.md) 一章中有介绍。
在这一节中,你将学到如何配置 Apache 或 Nginx 服务器实现这些目标。
在生产环境的服务器上,你可能会想配置服务器让应用程序可以通过 URL `http://www.example.com/index.php` 访问而不是 `http://www.example.com/basic/web/index.php`。这种配置需要将 Web 服务器的根目录指向 `basic/web` 目录。可能你还会想隐藏掉 URL 中的 `index.php`,具体细节在 [URL 解析和生成](runtime-url-handling.md) 一章中有介绍,你将学到如何配置 Apache 或 Nginx 服务器实现这些目标。
>补充:将 `basic/web` 设置为文档根目录,可以防止终端用户访问 `basic/web` 相邻目录中的私有应用程序代码和敏感数据文件。
禁止对其他目录的访问是一个切实可行的安全改进。
>补充:将 `basic/web` 设置为文档根目录,可以防止终端用户访问 `basic/web` 相邻目录中的私有应用程序代码和敏感数据文件。禁止对其他目录的访问是一个切实可行的安全改进。
>补充:如果你的应用程序将来要运行在共享的主机环境中,没有权限修改它的 Web 服务器配置,你依然可以调整应用程序的结构
提升安全性。详情请参考 [共享主机环境](tutorial-shared-hosting.md) 一章。
>补充:如果你的应用程序将来要运行在共享的主机环境中,没有权限修改它的 Web 服务器配置,你依然可以调整应用程序的结构提升安全性。详情请参考[共享主机环境](tutorial-shared-hosting.md) 一章。
### 推荐使用的 Apache 配置 <a name="recommended-apache-configuration"></a>
在 Apache 的 `httpd.conf` 文件或在一个虚拟主机配置文件中使用如下配置。
注意,你应该将 `path/to/basic/web` 替换为实际的 `basic/web` 目录。
在 Apache 的 `httpd.conf` 文件或在一个虚拟主机配置文件中使用如下配置。注意,你应该将 `path/to/basic/web` 替换为实际的 `basic/web` 目录。
```
# Set document root to be "basic/web"
# 设置文档根目录为 “basic/web”
DocumentRoot "path/to/basic/web"
<Directory "path/to/basic/web">
RewriteEngine on
# If a directory or a file exists, use the request directly
# 如果请求的是真实存在的文件或目录,直接访问
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Otherwise forward the request to index.php
# 如果请求的不是真实文件或目录,分发请求至 index.php
RewriteRule . index.php
# ...other settings...
# ...其它设置...
</Directory>
```
### 推荐使用的 Nginx 配置 <a name="recommended-nginx-configuration"></a>
为了使用 [Nginx](http://wiki.nginx.org/),你应该已经将 PHP 安装为 [FPM SAPI](http://php.net/install.fpm) 了。
使用如下 Nginx 配置,将 `path/to/basic/web` 替换为实际的 `basic/web` 目录, `mysite.local` 替换为实际的主机名以提供服务。
为了使用 [Nginx](http://wiki.nginx.org/),你应该已经将 PHP 安装为 [FPM SAPI](http://php.net/install.fpm) 了。使用如下 Nginx 配置,将 `path/to/basic/web` 替换为实际的 `basic/web` 目录,`mysite.local` 替换为实际的主机名以提供服务。
```
server {
charset utf-8;
client_max_body_size 128M;
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
listen 80; ## 监听 ipv4 上的 80 端口
#listen [::]:80 default_server ipv6only=on; ## 监听 ipv6 上的 80 端口
server_name mysite.local;
root /path/to/basic/web;
......@@ -148,11 +133,11 @@ server {
error_log /path/to/basic/log/error.log;
location / {
# Redirect everything that isn't a real file to index.php
# 如果找不到真实存在的文件,把请求重定向给 index.php
try_files $uri $uri/ /index.php?$args;
}
# uncomment to avoid processing of calls to non-existing static files by Yii
# 给这段解除注释,能够避免 Yii 接管不存在文件的处理过程(404)
#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
# try_files $uri =404;
#}
......
......@@ -141,6 +141,7 @@ Layout can be used to setup mail CSS styles or other shared content:
use yii\helpers\Html;
/* @var $this \yii\web\View view component instance */
/* @var $message \yii\mail\MessageInterface the message being composed */
/* @var $content string main view render result */
?>
<?php $this->beginPage() ?>
......@@ -227,4 +228,4 @@ another one for the 'Message'.
You can use `yii\mail\BaseMailer` and `yii\mail\BaseMessage` as a base classes for your solution. These classes
already contains basic logic, which is described in this guide. However, their usage is not mandatory, it is enough
to implement `yii\mail\MailerInterface` and `yii\mail\MessageInterface` interfaces.
Then you need to implement all abstract methods to build you solution.
\ No newline at end of file
Then you need to implement all abstract methods to build you solution.
......@@ -63,7 +63,7 @@ class SiteController extends Controller
'class' => 'yii\authclient\AuthAction',
'successCallback' => [$this, 'successCallback'],
],
]
];
}
public function successCallback($client)
......
......@@ -62,7 +62,9 @@ Yii Framework 2 Change Log
- Bug #3989: Fixed yii\log\FileTarget::$rotateByCopy to avoid any rename (cebe)
- Bug #3996: Traversing `Yii::$app->session` may cause a PHP error (qiangxue)
- Bug #4020: OCI column detection did not work so gii and other things failed (Sanya1991)
- Bug #4123: Trace level in logger had no effect in Targets, traces where not logged (cebe)
- Bug #4127: `CaptchaValidator` clientside error message wasn't formed properly (samdark)
- Bug #4162: Fixed bug where schema name was not used in ’SHOW CREATE TABLE’ query in `yii\db\mysql\Schema` (stevekr)
- Bug: Fixed inconsistent return of `\yii\console\Application::runAction()` (samdark)
- Bug: URL encoding for the route parameter added to `\yii\web\UrlManager` (klimov-paul)
- Bug: Fixed the bug that requesting protected or private action methods would cause 500 error instead of 404 (qiangxue)
......@@ -121,6 +123,7 @@ Yii Framework 2 Change Log
- Removed character maps for non-latin languages.
- Improved overall slug results.
- Added note about the fact that intl is required for non-latin languages to requirements checker.
- Enh #3992: In mail layouts you can now access the message object via `$message` variable (qiangxue)
- Enh #4028: Added ability to `yii\widgets\Menu` to encode each item's label separately (creocoder, umneeq)
- Enh #4072: `\yii\rbac\PhpManager` adjustments (samdark)
- Data is now stored in three separate files for items, assignments and rules. File format is simpler.
......@@ -163,6 +166,7 @@ Yii Framework 2 Change Log
- Chg #3956: Flash messages set via `Yii::$app->session->setFlash()` will be removed only if they are accessed (qiangxue)
- Chg #3989: The default value for `yii\log\FileTarget::$rotateByCopy` now defaults to true to work on windows by default (cebe)
- Chg #4071: `mail` component renamed to `mailer`, `yii\log\EmailTarget::$mail` renamed to `yii\log\EmailTarget::$mailer` (samdark)
- Chg #4147: `BaseMailer::compose()` will not overwrite the `message` parameter if it is explicitly provided (qiangxue)
- Chg: Replaced `clearAll()` and `clearAllAssignments()` in `yii\rbac\ManagerInterface` with `removeAll()`, `removeAllRoles()`, `removeAllPermissions()`, `removeAllRules()` and `removeAllAssignments()` (qiangxue)
- Chg: Added `$user` as the first parameter of `yii\rbac\Rule::execute()` (qiangxue)
- Chg: `yii\grid\DataColumn::getDataCellValue()` visibility is now `public` to allow accessing the value from a GridView directly (cebe)
......@@ -170,6 +174,7 @@ Yii Framework 2 Change Log
- Chg: Removed `yii\rest\ActiveController::$transactional` property and connected functionality (samdark)
- Chg: Changed the default value of the `keyPrefix` property of cache components to be null (qiangxue)
- Chg: Added `prefix` column to `yii\log\DbTarget` to have the same amount of information logged as in files and emails (cebe)
- Chg: Use `limit(null)` instead of `limit(-1)` in migration controller to be compatible to more backends (cebe)
- New #3911: Added `yii\behaviors\SluggableBehavior` that fills the specified model attribute with the transliterated and adjusted version to use in URLs (creocoder)
......
......@@ -328,7 +328,7 @@ abstract class BaseMigrateController extends Controller
}
// try mark down
$migrations = array_keys($this->getMigrationHistory(-1));
$migrations = array_keys($this->getMigrationHistory(null));
foreach ($migrations as $i => $migration) {
if (strpos($migration, $version . '_') === 0) {
if ($i === 0) {
......@@ -544,7 +544,7 @@ abstract class BaseMigrateController extends Controller
protected function migrateToTime($time)
{
$count = 0;
$migrations = array_values($this->getMigrationHistory(-1));
$migrations = array_values($this->getMigrationHistory(null));
while ($count < count($migrations) && $migrations[$count] > $time) {
++$count;
}
......@@ -575,7 +575,7 @@ abstract class BaseMigrateController extends Controller
}
// try migrate down
$migrations = array_keys($this->getMigrationHistory(-1));
$migrations = array_keys($this->getMigrationHistory(null));
foreach ($migrations as $i => $migration) {
if (strpos($migration, $version . '_') === 0) {
if ($i === 0) {
......@@ -598,7 +598,7 @@ abstract class BaseMigrateController extends Controller
protected function getNewMigrations()
{
$applied = [];
foreach ($this->getMigrationHistory(-1) as $version => $time) {
foreach ($this->getMigrationHistory(null) as $version => $time) {
$applied[substr($version, 1, 13)] = true;
}
......@@ -621,7 +621,7 @@ abstract class BaseMigrateController extends Controller
/**
* Returns the migration history.
* @param integer $limit the maximum number of records in the history to be returned
* @param integer $limit the maximum number of records in the history to be returned. `null` for "no limit".
* @return array the migration history
*/
abstract protected function getMigrationHistory($limit);
......
......@@ -716,7 +716,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
$changedAttributes = [];
foreach ($values as $name => $value) {
$changedAttributes[$name] = $this->_oldAttributes[$name];
$changedAttributes[$name] = isset($this->_oldAttributes[$name]) ? $this->_oldAttributes[$name] : null;
$this->_oldAttributes[$name] = $value;
}
$this->afterSave(false, $changedAttributes);
......
......@@ -225,7 +225,7 @@ class Schema extends \yii\db\Schema
*/
protected function getCreateTableSql($table)
{
$row = $this->db->createCommand('SHOW CREATE TABLE ' . $this->quoteSimpleTableName($table->name))->queryOne();
$row = $this->db->createCommand('SHOW CREATE TABLE ' . $this->quoteTableName($table->fullName))->queryOne();
if (isset($row['Create Table'])) {
$sql = $row['Create Table'];
} else {
......
......@@ -47,6 +47,6 @@ class QueryParamAuth extends AuthMethod
*/
public function handleFailure($response)
{
throw new UnauthorizedHttpException('You are requesting with an invalid access token.');
throw new UnauthorizedHttpException(Yii::t('yii', 'You are requesting with an invalid access token.'));
}
}
......@@ -9,6 +9,7 @@ namespace yii\log;
use Yii;
use yii\base\Component;
use yii\base\ErrorHandler;
/**
* Dispatcher manages a set of [[Target|log targets]].
......@@ -183,7 +184,7 @@ class Dispatcher extends Component
} catch (\Exception $e) {
$target->enabled = false;
$targetErrors[] = [
'Unable to send log via '. get_class($target) .': ' . $e->getMessage(),
'Unable to send log via ' . get_class($target) . ': ' . ErrorHandler::convertExceptionToString($e),
Logger::LEVEL_WARNING,
__METHOD__,
microtime(true),
......
......@@ -235,9 +235,16 @@ abstract class Target extends Component
if (!is_string($text)) {
$text = VarDumper::export($text);
}
$traces = [];
if (isset($message[4])) {
foreach($message[4] as $trace) {
$traces[] = "in {$trace['file']}:{$trace['line']}";
}
}
$prefix = $this->getMessagePrefix($message);
return date('Y-m-d H:i:s', $timestamp) . " {$prefix}[$level][$category] $text";
return date('Y-m-d H:i:s', $timestamp) . " {$prefix}[$level][$category] $text"
. (empty($traces) ? '' : "\n " . implode("\n ", $traces));
}
/**
......
......@@ -144,6 +144,8 @@ abstract class BaseMailer extends Component implements MailerInterface, ViewCont
return Yii::createObject($config);
}
private $_message;
/**
* Creates a new message instance and optionally composes its body content via view rendering.
*
......@@ -167,30 +169,41 @@ abstract class BaseMailer extends Component implements MailerInterface, ViewCont
public function compose($view = null, array $params = [])
{
$message = $this->createMessage();
if ($view !== null) {
if ($view === null) {
return $message;
}
if (!array_key_exists('message', $params)) {
$params['message'] = $message;
if (is_array($view)) {
if (isset($view['html'])) {
$html = $this->render($view['html'], $params, $this->htmlLayout);
}
if (isset($view['text'])) {
$text = $this->render($view['text'], $params, $this->textLayout);
}
} else {
$html = $this->render($view, $params, $this->htmlLayout);
}
$this->_message = $message;
if (is_array($view)) {
if (isset($view['html'])) {
$html = $this->render($view['html'], $params, $this->htmlLayout);
}
if (isset($html)) {
$message->setHtmlBody($html);
if (isset($view['text'])) {
$text = $this->render($view['text'], $params, $this->textLayout);
}
if (isset($text)) {
$message->setTextBody($text);
} elseif (isset($html)) {
if (preg_match('|<body[^>]*>(.*?)</body>|is', $html, $match)) {
$html = $match[1];
}
$html = preg_replace('|<style[^>]*>(.*?)</style>|is', '', $html);
$message->setTextBody(strip_tags($html));
} else {
$html = $this->render($view, $params, $this->htmlLayout);
}
$this->_message = null;
if (isset($html)) {
$message->setHtmlBody($html);
}
if (isset($text)) {
$message->setTextBody($text);
} elseif (isset($html)) {
if (preg_match('|<body[^>]*>(.*?)</body>|is', $html, $match)) {
$html = $match[1];
}
$html = preg_replace('|<style[^>]*>(.*?)</style>|is', '', $html);
$message->setTextBody(strip_tags($html));
}
return $message;
}
......@@ -277,7 +290,7 @@ abstract class BaseMailer extends Component implements MailerInterface, ViewCont
{
$output = $this->getView()->render($view, $params, $this);
if ($layout !== false) {
return $this->getView()->render($layout, ['content' => $output], $this);
return $this->getView()->render($layout, ['content' => $output, 'message' => $this->_message], $this);
} else {
return $output;
}
......
......@@ -7,14 +7,14 @@ else
# basic application:
composer install --dev --prefer-dist -d apps/basic
cd apps/basic && composer require --dev codeception/codeception:1.8.*@dev codeception/specify:* codeception/verify:*
cd apps/basic && composer require --dev codeception/codeception:2.0.* codeception/specify:* codeception/verify:*
php vendor/bin/codecept build && cd ../..
# advanced application:
composer install --dev --prefer-dist -d apps/advanced
cd apps/advanced && composer require --dev codeception/codeception:1.8.*@dev codeception/specify:* codeception/verify:*
cd apps/advanced && composer require --dev codeception/codeception:2.0.* codeception/specify:* codeception/verify:*
./init --env=Development
sed -i s/root/travis/ common/config/main-local.php
cd backend && php ../vendor/bin/codecept build
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment