Commit fe93f8d1 by Aleksandr

Merge pull request #4 from yiisoft/master

pull)
parents eb8cfe47 79815252
La guida definitiva a Yii 2.0
=============================
Questa guida è rilasciata nei [termini della documnetazione di Yii](http://www.yiiframework.com/doc/terms/).
Questa guida è rilasciata nei [termini della documentazione di Yii](http://www.yiiframework.com/doc/terms/).
Tutti i diritti riservati.
......
......@@ -66,14 +66,14 @@
необходимые параметры, такие как [[yii\db\Connection::dsn]].
Более детальная информация представлена в разделе [Объекты доступа к данным (DAO)](db-dao.md);
* [[yii\base\Application::errorHandler|errorHandler]]: осуществляет обработку PHP ошибок и исключений.
Более детальная информация представлена в разделе [Обработка ошибок](tutorial-handling-errors.md);
Более детальная информация представлена в разделе [Обработка ошибок](runtime-handling-errors.md);
* [[yii\base\Formatter|formatter]]: форматирует данные для отображения их конечному пользователю. Например, число может
быть отображено с различными разделителями, дата может быть отображена в формате `long`.
Более детальная информация представлена в разделе [Форматирование данных](output-formatting.md);
* [[yii\i18n\I18N|i18n]]: используется для перевода сообщений и форматирования.
Более детальная информация представлена в разделе [Интернационализация](tutorial-i18n.md);
* [[yii\log\Dispatcher|log]]: обработка и маршрутизация логов.
Более детальная информация представлена в разделе [Логирование](tutorial-logging.md);
Более детальная информация представлена в разделе [Логирование](runtime-logging.md);
* [[yii\swiftmailer\Mailer|mail]]: предоставляет возможности для составления и рассылки писем.
Более детальная информация представлена в разделе [Отправка почты](tutorial-mailing.md);
* [[yii\base\Application::response|response]]: представляет собой данные от сервера, которые будет направлены пользователю.
......
Yii 2.0 bo`yicha to`liq qo`llanma
Yii 2.0 bo'yicha to'liq qo'llanma
=============================
Ushbu qo`llanma [Yii qo`llanmalarining holati bilan](http://www.yiiframework.com/doc/terms/) bilan mos holda yo`lga qo`yildi.
Ushbu qo'llanma [Yii qo'llanmalarining holati bilan](http://www.yiiframework.com/doc/terms/) bilan mos holda yo'lga qo'yildi.
<<<<<<< HEAD
All Rights Reserved.
2014 © Yii Software LLC.
......@@ -18,11 +17,11 @@ Kirish
Birinchi tanishuv
-----------------
* [Yii ni o`rnatish](start-installation.md)
* [Yii ni o'rnatish](start-installation.md)
* [Ilovani ishga tushirish](start-workflow.md)
* [«Salom» deymiz](start-hello.md)
* [Formalar bilan ishlash](start-forms.md)
* [Ma`lumotlar ombori bilan ishlash](start-databases.md)
* [Ma'lumotlar ombori bilan ishlash](start-databases.md)
* [Gii yordamida kodlarni generatsiya qilish](start-gii.md)
* [Keyin nima?](start-looking-ahead.md)
......@@ -34,26 +33,26 @@ Ilova strukturasi
* [Kirish skriptlari](structure-entry-scripts.md)
* [Ilova](structure-applications.md)
* [Ilova komponentlari](structure-application-components.md)
* [Kontrollerlar](structure-controllers.md)
* [Kontrollyorlar](structure-controllers.md)
* [Namoyish](structure-views.md)
* [Modellar](structure-models.md)
* **TBD** [Filtrlar](structure-filters.md)
* **TBD** [Vidjetlar](structure-widgets.md)
* **TBD** [Modullar](structure-modules.md)
* [Ресурсы](structure-assets.md)
* [Resurslar](structure-assets.md)
* **TBD** [Kengaytmalar](structure-extensions.md)
So`rovlarni qayta ishlash
So'rovlarni qayta ishlash
-------------------------
* **TBD** [Bootstrapping](runtime-bootstrapping.md)
* **TBD** [Routing](runtime-routing.md)
* **TBD** [So`rovlar](runtime-requests.md)
* **TBD** [So'rovlar](runtime-requests.md)
* **TBD** [Javoblar](runtime-responses.md)
* **TBD** [Sessiyalar va kuklar](runtime-sessions-cookies.md)
* [URL ni tahlil va generatsiya qilish](runtime-url-handling.md)
* [Xatolilarni qayta ishlash](runtime-handling-errors.md)
* [Xatoliklarni qayta ishlash](runtime-handling-errors.md)
* [Jurnallarga yozish](runtime-logging.md)
......@@ -63,28 +62,28 @@ Asosiy tushunchalar
* [Komponentlar](concept-components.md)
* [Xususiyat](concept-properties.md)
* [Xodisa](concept-events.md)
* [O`zini tutish](concept-behaviors.md)
* [Muxim sozlashlar](concept-configurations.md)
* [O'zini tutish](concept-behaviors.md)
* [Muhim sozlashlar](concept-configurations.md)
* [Taxalluslar](concept-aliases.md)
* [Sinflarni avtoyuklash](concept-autoloading.md)
* [Service Locator](concept-service-locator.md)
* [Dependency Injection Container](concept-di-container.md)
Ma`lumotlar ombori bilan ishlash
Ma'lumotlar ombori bilan ishlash
--------------------------------
* [Ma`lumotlarga imkon beruvchi obektlar(DAO)](db-dao.md) - Ma`lumotlar ombori bilan bog`lanish, oddiy so`rovlar, tranzaksiya va sxema bilan ishlash.
* [So`rovlarni yaratuvchi](db-query-builder.md) - Ma`lumotlar omboriga abstraksiyaning oddiy qatlamidan so`rovlar.
* [Active Record](db-active-record.md) - AR obektlarini olish, ular bilan ishlash va bog`lanishlarni aniqlash.
* [Migratsiyalar](db-migrations.md) - Komandada ishlaganda ma`lumotlar sxemasini talqinlarini boshqarish.
* [Ma'lumotlar bilan ishlashga imkon beruvchi obektlar(DAO)](db-dao.md) - Ma'lumotlar ombori bilan bog'lanish, oddiy so'rovlar, tranzaksiya va sxema bilan ishlash.
* [So'rovlarni yaratuvchi](db-query-builder.md) - Ma'lumotlar omboriga abstraksiyaning oddiy qatlamidan so'rovlar.
* [Active Record](db-active-record.md) - AR obektlarini olish, ular bilan ishlash va bog'lanishlarni aniqlash.
* [Migratsiyalar](db-migrations.md) - Komandada (jamoada) ishlaganda ma'lumotlar sxemasini talqinlarini boshqarish.
* **TBD** [Sphinx](db-sphinx.md)
* **TBD** [Redis](db-redis.md)
* **TBD** [MongoDB](db-mongodb.md)
* **TBD** [ElasticSearch](db-elastic-search.md)
Foydalanuvchidan ma`lumotlarni qabul qilish
Foydalanuvchidan ma'lumotlarni qabul qilish
-------------------------------------------
* [Formani yaratish](input-forms.md)
......@@ -93,14 +92,14 @@ Foydalanuvchidan ma`lumotlarni qabul qilish
* **TBD** [Bir nechta modellar bilan ishlash](input-multiple-models.md)
Ma`lumotlarni namoyish etish
Ma'lumotlarni namoyish etish
----------------------------
* **TBD** [Ma`lumotlarni formatlash](output-formatting.md)
* **TBD** [Sahifalar bo`yicha bo`ajratish](output-pagination.md)
* **TBD** [Ma'lumotlarni formatlash](output-formatting.md)
* **TBD** [Sahifalar bo'yicha ajratish](output-pagination.md)
* **TBD** [Saralash](output-sorting.md)
* [Ma`lumotlar provayderlari](output-data-providers.md)
* [Ma`lumotlar uchun vidjetlar](output-data-widgets.md)
* [Ma'lumotlar provayderlari](output-data-providers.md)
* [Ma'lumotlar uchun vidjetlar](output-data-widgets.md)
* [Mavzulashtirish](output-theming.md)
......@@ -108,9 +107,9 @@ Xavfsizlik
----------
* [Autentifikatsiya](security-authentication.md)
* [Mualliflikka tekshiruvi](security-authorization.md)
* [Avtorizatsiya](security-authorization.md)
* [Parollar bilan ishlash](security-passwords.md)
* **TBD** [Mualliflikka tekshiruvlar mijozlari](security-auth-clients.md)
* **TBD** [Avtorizatsiya mijozlari](security-auth-clients.md)
* **TBD** [Eng yaxshi amaliyotlar](security-best-practices.md)
......@@ -118,35 +117,35 @@ Keshlash
--------
* [Sharh](caching-overview.md)
* [Ma`lumotlarni keshlash](caching-data.md)
* [Fragmentlasrni keshlash](caching-fragment.md)
* [Ma'lumotlarni keshlash](caching-data.md)
* [Fragmentlarni keshlash](caching-fragment.md)
* [Sahifalarni keshlash](caching-page.md)
* [HTTP ni keshlash](caching-http.md)
REST veb-xizmatlari
REST web-xizmatlari
-------------------
* [Tezkor boshlash](rest-quick-start.md)
* [Resurslar](rest-resources.md)
* [Kontrollerlar](rest-controllers.md)
* [Kontrollyorlar](rest-controllers.md)
* [Routing](rest-routing.md)
* [Javoblarni formatlash](rest-response-formatting.md)
* [Autentifikatsiya](rest-authentication.md)
* [So`rovlarni chastotasini chegaralash](rest-rate-limiting.md)
* [So'rovlarni chastotasini chegaralash](rest-rate-limiting.md)
* [Talqin yaratish](rest-versioning.md)
* [Xatoliklarni qayta ishlash](rest-error-handling.md)
Ishlab chiquvchi uskunalari
Ishlab chiquvchining uskunalari
---------------------------
* [Sozlashlar paneli va sozlovchi](tool-debugger.md)
* [Qayta ishlash paneli va qayta ishlovchi](tool-debugger.md)
* [Gii bilan kodni generatsiya qilish](tool-gii.md)
* **TBD** [API qo`llanmani generatori](tool-api-doc.md)
* **TBD** [API qo'llanmani generatori](tool-api-doc.md)
Test o`tkazish
Test o'tkazish
--------------
* [Sharh](test-overview.md)
......@@ -161,7 +160,7 @@ Yii kengaytmalari
* [Kengaytmani yaratish](extend-creating-extensions.md)
* [Freymvork kodini kengaytirish](extend-customizing-core.md)
* [Tashqi kutubxonalarni qo`llash](extend-using-libs.md)
* [Tashqi kutubxonalarni qo'llash](extend-using-libs.md)
* **TBD** [Tashqi tizimlarda Yii integratsiyasi](extend-embedding-in-others.md)
* **TBD** [Yii 1.1 va 2.0 larni bir vaqtda ishlatish](extend-using-v1-v2.md)
* [Composer ni ishlatish](extend-using-composer.md)
......@@ -202,9 +201,4 @@ Xelperlar
* **TBD** [ArrayHelper](helper-array.md)
* **TBD** [Html](helper-html.md)
* **TBD** [Url](helper-url.md)
* **TBD** [Security](helper-security.md)
=======
Barcha huquqlar ximoyalangan.
2014 © Yii Software LLC.
>>>>>>> 6a3cce2e267f590c38f910d571adea6a38028329
* **TBD** [Security](helper-security.md)
\ No newline at end of file
......@@ -28,7 +28,7 @@ Yii 2.0 权威指南
应用结构
--------
* **已定稿** [结构总览](structure-overview.md)
* **已定稿** [结构概述](structure-overview.md)
* **已定稿** [入口脚本](structure-entry-scripts.md)
* **已定稿** [应用](structure-applications.md)
* **已定稿** [应用组件](structure-application-components.md)
......@@ -44,11 +44,12 @@ Yii 2.0 权威指南
请求处理
--------
* **待定中** [引导(Bootstrapping)](runtime-bootstrapping.md)
* **待定中** [路由(Routing)](runtime-routing.md)
* **待定中** [请求(Request)](runtime-requests.md)
* **待定中** [响应(Response)](runtime-responses.md)
* **待定中** [Sessions(会话)和 Cookies](runtime-sessions-cookies.md)
* **已定稿** [运行概述](runtime-overview.md)
* **已定稿** [引导(Bootstrapping)](runtime-bootstrapping.md)
* **已定稿** [路由(Routing)](runtime-routing.md)
* **已定稿** [请求(Request)](runtime-requests.md)
* **已定稿** [响应(Response)](runtime-responses.md)
* **已定稿** [Sessions(会话)和 Cookies](runtime-sessions-cookies.md)
* **编撰中** [URL 解析和生成](runtime-url-handling.md)
* **编撰中** [错误处理](runtime-handling-errors.md)
* **编撰中** [日志](runtime-logging.md)
......@@ -89,7 +90,7 @@ Yii 2.0 权威指南
显示数据
--------
* **待定中** [格式化输出数据](output-formatting.md)
* **待定中** [格式化输出数据](output-formatter.md)
* **待定中** [分页(Pagination)](output-pagination.md)
* **待定中** [排序(Sorting)](output-sorting.md)
* **编撰中** [数据提供器](output-data-providers.md)
......
......@@ -11,7 +11,7 @@
安装
------------
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 需求
......@@ -33,17 +33,17 @@ Yii 2.0 需要 PHP 5.4 或更高版本,该版本相对于 Yii 1.1 所需求的
命名空间
---------
Yii 2.0 里最明显的改动就数命名空间的使用了。几乎每一个核心类都引入了命名空间,比如 `yii\web\Request`。1.1 版用于类名前的字母 “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 来定义[对象的属性](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]] 类作为基类。这种类通常用来表示基本的数据结构
对象的配置
......@@ -65,12 +65,12 @@ class MyClass extends \yii\base\Object
{
parent::init();
// ...配置生效后的初始化过程
// ... 配置生效后的初始化过程
}
}
```
在上面的例子里,构造方法的最后一个参数必须入一个配置数组,包含一系列用于在方法结尾初始化相关属性的键值对。你可以重写 [[yii\base\Object::init()|init()]] 方法来执行一些需要在配置生效后进行的初始化工作。
在上面的例子里,构造方法的最后一个参数必须入一个配置数组,包含一系列用于在方法结尾初始化相关属性的键值对。你可以重写 [[yii\base\Object::init()|init()]] 方法来执行一些需要在配置生效后进行的初始化工作。
你可以通过遵循以下约定俗成的编码习惯,来使用配置数组创建并配置新的对象:
......@@ -95,11 +95,11 @@ $event = new \yii\base\Event;
$component->trigger($eventName, $event);
```
要给事件附加一个事件句柄(Event Handler 或者叫事件处理器),需要使用 [[yii\base\Component::on()|on()]] 方法:
要给事件附加一个事件事件处理器,需要使用 [[yii\base\Component::on()|on()]] 方法:
```php
$component->on($eventName, $handler);
// 要解除相关句柄,使用 off 方法:
// 解除事件处理器,使用 off 方法:
// $component->off($eventName, $handler);
```
......@@ -174,7 +174,7 @@ public function actionView($id)
}
```
请查看 [控制器(Controller)](structure-controllers.md) 章节了解有关控制器的更多细节。
请查看[控制器(Controller)](structure-controllers.md)章节了解有关控制器的更多细节。
小部件(Widget)
......@@ -283,7 +283,7 @@ Yii 2.0 很多常用的静态助手类,包括:
表单
-----
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(); ?>
......@@ -327,14 +327,14 @@ Yii 2.0 的[活动记录](db-active-record.md)改动了很多。两个最显而
1.1 中的 `CDbCriteria` 类在 Yii 2 中被 [[yii\db\ActiveQuery]] 所替代。这个类是继承自 [[yii\db\Query]],因此也继承了所有查询生成方法。开始拼装一个查询可以调用 [[yii\db\ActiveRecord::find()]] 方法进行:
```php
// 检索所有 *活动的* 客户和订单,并以 ID 排序:
// 检索所有“活动的”客户和订单,并以 ID 排序:
$customers = Customer::find()
->where(['status' => $active])
->orderBy('id')
->all();
```
要声明一个关联关系,只需简单地定义一个 getter 方法来返回一个 [[yii\db\ActiveQuery|ActiveQuery]] 对象。getter 方法定义的属性名(译者注:即 getOrders() 中的 orders)表示关联关系名。如,以下代码声明了一个名为 `orders` 的关系(1.1 中必须在 `relations()` 方法内声明关系):
要声明一个关联关系,只需简单地定义一个 getter 方法来返回一个 [[yii\db\ActiveQuery|ActiveQuery]] 对象。getter 方法定义的属性名代表关联表名称。如,以下代码声明了一个名为 `orders` 的关系(1.1 中必须在 `relations()` 方法内声明关系):
```php
class Customer extends \yii\db\ActiveRecord
......@@ -360,7 +360,7 @@ $orders = $customer->getOrders()->andWhere('status=1')->all();
$customers = Customer::find()->asArray()->all();
```
另一个改变是你不能再通过公共数据定属性(Attribute)的默认值了。如果你需要这么做的话,可以在你的记录类的 `init` 方法中设置它们。
另一个改变是你不能再通过公共变量定义属性(Attribute)的默认值了。如果你需要这么做的话,可以在你的记录类的 `init` 方法中设置它们。
```php
public function init()
......@@ -370,11 +370,41 @@ public function init()
}
```
曾几何时,在 1.1 中重写一个活动记录类的构造方法(Constructor)会导致一些问题。它们不会在 2.0 中出现了。需要注意的是,如果你需要在构造方法中添加一些参数,恐怕必须重写 [[yii\db\ActiveRecord::instantiate()]] 方法。
曾几何时,在 1.1 中重写一个活动记录类的构造方法会导致一些问题。它们不会在 2.0 中出现了。需要注意的是,如果你需要在构造方法中添加一些参数,恐怕必须重写 [[yii\db\ActiveRecord::instantiate()]] 方法。
活动记录方面还有很多其他的变化与改进,请参考[活动记录](db-active-record.md)章节以了解更多细节。
活动记录行为(Active Record Behaviors)
------------------------------------
在 2.0 中遗弃了活动记录行为基类 `CActiveRecordBehavior`。如果你想创建活动记录行为,需要直接继承 `yii\base\Behavior`。如果行为类中需要表示一些事件,需要像这样覆写 `events()` 方法:
```php
namespace app\components;
use yii\db\ActiveRecord;
use yii\base\Behavior;
class MyBehavior extends Behavior
{
// ...
public function events()
{
return [
ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
];
}
public function beforeValidate($event)
{
// ...
}
}
```
用户及身份验证接口(IdentityInterface)
-------------------------------------
......@@ -401,4 +431,4 @@ Yii 2.0 的 URL 管理跟 1.1 中很像。一个主要的改进是现在的 URL
同时使用 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 共用](tutorial-yii-integration.md)章节。
Yii 是什么
===========
Yii 是一个高性能,基于组件的 PHP 框架,用于快速开发现代 Web 应用程序。名字 Yii (读作 `易`)在中文里有 “极致简单与不断演变” 两重含义,也可看作 **Yes It Is**! 的缩写。
Yii 是一个高性能,基于组件的 PHP 框架,用于快速开发现代 Web 应用程序。名字 Yii (读作 `易`)在中文里有“极致简单与不断演变”两重含义,也可看作 **Yes It Is**! 的缩写。
Yii 最适合做什么?
---------------------
Yii 是一个通用的 Web 编程框架,即可以用于开发各种基于 PHP 的 Web 应用。因为基于组件的框架结构和设计精巧的缓存支持,Yii 特别适合开发大型应用,如门户网站、论坛、内容管理系统(CMS)、电子商务项目和 RESTful Web 服务等。
Yii 是一个通用的 Web 编程框架,即可以用于开发各种基于 PHP 的 Web 应用。因为基于组件的框架结构和设计精巧的缓存支持,它特别适合开发大型应用,如门户网站、社区、内容管理系统(CMS)、电子商务项目和 RESTful Web 服务等。
Yii 和其他框架相比呢?
-------------------------------------------
如果你有其它框架使用经验,那么你会很开心看到 Yii 所做的努力:
- 和其他 PHP 框架类似,Yii 实现了 MVC(Model-View-Controller)设计模式并基于该模式组织代码。
- Yii 的代码简洁优雅,这是 Yii 的编程哲学。它永远不会为了要迎合某个设计模式而对代码进行过度的设计。
- Yii 是一个全栈框架,提供了大量久经考验,开箱即用的特性,例如:对关系型和 NoSQL 数据库都提供了查询生成器(QueryBuilders)和 ActiveRecord;RESTful API 的开发支持;多层缓存支持,等等。
- Yii 的代码简洁优雅,这是它的编程哲学。它永远不会为了严格遵照某种设计模式而对代码进行过度的设计。
- Yii 是一个全栈框架,提供了大量久经考验,开箱即用的特性:对关系型和 NoSQL 数据库都提供了查询生成器和 ActiveRecord;RESTful API 的开发支持;多层缓存支持,等等。
- Yii 非常易于扩展。你可以自定义或替换几乎任何一处核心代码。你还会受益于它坚实可靠的扩展架构,使用、再开发或再发布扩展。
- 高性能始终是 Yii 的首要目标之一。
Yii 不是一场独角戏,它由一个[强大的开发者团队](http://www.yiiframework.com/about/)提供支持,也有一个庞大的专家社区,持续不断地对 Yii 的开发作出贡献。Yii 开发者团队始终对 Web 开发最新潮流和其他框架及项目中的最佳实践和特性保持密切关注,那些有意义的最佳实践及特性会被不定期的整合进核心框架中,并提供简单优雅的接口。
Yii 不是一场独角戏,它由一个[强大的开发者团队](http://www.yiiframework.com/about/)提供支持,也有一个庞大的专家社区,持续不断地对 Yii 的开发作出贡献。Yii 开发者团队始终对 Web 开发趋势和其他框架及项目中的最佳实践和特性保持密切关注,那些有意义的最佳实践及特性会被不定期的整合进核心框架中,并提供简单优雅的接口。
Yii 版本
------------
Yii 当前有两个主要版本:1.1 和 2.0。 1.1 版是上代的老版本,现在处于维护状态。2.0 版是一个完全重写的版本,采用了最新的技术和协议,包括依赖包管理器(Composer)、PHP 代码规范(PSR)、命名空间、Traits(特质)等等。 2.0 版代表了最新一代框架,是未来几年中我们的主要开发版本。本指南主要基于 2.0 版编写。
Yii 当前有两个主要版本:1.1 和 2.0。 1.1 版是上代的老版本,现在处于维护状态。2.0 版是一个完全重写的版本,采用了最新的技术和协议,包括依赖包管理器 Composer、PHP 代码规范 PSR、命名空间、Traits(特质)等等。 2.0 版代表新一代框架,是未来几年中我们的主要开发版本。本指南主要基于 2.0 版编写。
系统要求和先决条件
......@@ -32,5 +34,5 @@ Yii 当前有两个主要版本:1.1 和 2.0。 1.1 版是上代的老版本,
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。
使用数据库
======================
本章节将介绍如何如何创建一个从数据表 `country`取国家数据并显示出来的页面。为了实现这个目标,你将会配置一个数据库连接,创建一个[活动记录](db-active-record.md)类,并且创建一个[操作](structure-controllers.md)及一个[视图](structure-views.md)
本章节将介绍如何如何创建一个从数据表 `country`取国家数据并显示出来的页面。为了实现这个目标,你将会配置一个数据库连接,创建一个[活动记录](db-active-record.md)类,并且创建一个[操作](structure-controllers.md)及一个[视图](structure-views.md)
贯穿整个章节,你将会学到:
......@@ -16,7 +16,7 @@
准备数据库 <a name="preparing-database"></a>
--------------------
首先创建一个名为 `yii2basic` 的数据库,应用将从这个数据库中获取数据。你可以创建 SQLite,MySQL,PostregSQL,MSSQL 或 Oracle 数据库,Yii 内置多种数据库支持。简单起见后面的内容将以 MySQL 为例做演示。
首先创建一个名为 `yii2basic` 的数据库,应用将从这个数据库中读取数据。你可以创建 SQLite,MySQL,PostregSQL,MSSQL 或 Oracle 数据库,Yii 内置多种数据库支持。简单起见,后面的内容将以 MySQL 为例做演示。
然后在数据库中创建一个名为 `country` 的表并插入简单的数据。可以执行下面的语句:
......@@ -39,7 +39,7 @@ INSERT INTO `country` VALUES ('RU','Russia',146934000);
INSERT INTO `country` VALUES ('US','United States',278357000);
```
于是便有了一个名为 `yii2basic` 的数据库,在这个数据库中有一个包含三个字段的数据表 `country`,表中有十行数据。
此时便有了一个名为 `yii2basic` 的数据库,在这个数据库中有一个包含三个字段的数据表 `country`,表中有十行数据。
配置数据库连接 <a name="configuring-db-connection"></a>
---------------------------
......@@ -62,7 +62,7 @@ return [
`config/db/php` 是一个典型的基于文件的[配置](concept-configurations.md)工具。这个文件配置了数据库连接 [[yii\db\Connection]] 的创建和初始化参数,应用的 SQL 查询正是基于这个数据库。
上面配置的数据库连接可以在应用中通过 `Yii::$app->db` 访问。
上面配置的数据库连接可以在应用中通过 `Yii::$app->db` 表达式访问。
> 补充:`config/db.php` 将被包含在应用配置文件 `config/web.php` 中,后者指定了整个[应用](structure-applications.md)如何初始化。请参考[配置](concept-configurations.md)章节了解更多信息。
......@@ -70,7 +70,7 @@ return [
创建活动记录 <a name="creating-active-record"></a>
-------------------------
创建一个继承自[活动记录](db-active-record.md)类的类 `Country`,把它放在 `models/Country.php`,去表示和获`country` 表的数据。
创建一个继承自[活动记录](db-active-record.md)类的类 `Country`,把它放在 `models/Country.php` 文件,去代表和读`country` 表的数据。
```php
<?php
......@@ -86,7 +86,7 @@ class Country extends ActiveRecord
这个 `Country` 类继承自 [[yii\db\ActiveRecord]]。你不用在里面写任何代码。只需要像现在这样,Yii 就能根据类名去猜测对应的数据表名。
> 补充:如果类名和数据表名不能直接对应,可以写 [[yii\db\ActiveRecord::tableName()|tableName()]] 方法去显式指定相关表名。
> 补充:如果类名和数据表名不能直接对应,可以写 [[yii\db\ActiveRecord::tableName()|tableName()]] 方法去显式指定相关表名。
使用 `Country` 类可以很容易地操作 `country` 表数据,就像这段代码:
......@@ -107,7 +107,7 @@ $country->name = 'U.S.A.';
$country->save();
```
> 补充:活动记录是面向对象、功能强大的访问和操作数据库数据的方式。你可以在[活动记录](db-active-record.md)章节了解更多信息。除此之外你还可以使用另一种更原生的称做[数据访问对象](db-dao)的方法操作数据库数据。
> 补充:活动记录是面向对象、功能强大的访问和操作数据库数据的方式。你可以在[活动记录](db-active-record.md)章节了解更多信息。除此之外你还可以使用另一种更原生的称做[数据访问对象](db-dao)的方法操作数据库数据。
创建操作 <a name="creating-action"></a>
......@@ -148,7 +148,7 @@ class CountryController extends Controller
}
```
把上面的代码保存在 `controllers/CountryController.php`
把上面的代码保存在 `controllers/CountryController.php` 文件中
`index` 操作调用了活动记录 `Country::find()` 方法,去生成查询语句并从 `country` 表中取回所有数据。为了限定每个请求所返回的国家数量,查询在 [[yii\data\Pagination]] 对象的帮助下进行分页。 `Pagination` 对象的使命主要有两点:
......@@ -184,7 +184,7 @@ use yii\widgets\LinkPager;
这个视图包含两部分用以显示国家数据。第一部分遍历国家数据并以无序 HTML 列表渲染出来。第二部分使用 [[yii\widgets\LinkPager]] 去渲染从操作中传来的分页信息。小部件 `LinkPager` 显示一个分页按钮的列表。点击任何一个按钮都会跳转到对应的分页。
尝试下 <a name="trying-it-out"></a>
试运行 <a name="trying-it-out"></a>
-------------
浏览器访问下面的 URL 看看能否工作:
......
使用表单
==================
本章将介绍如何创建一个从用户那搜集数据的表单页。该页将显示一个包含 name 输入框和 email 输入框的表单。当搜集完这两部分信息后,页面将会显示用户输入的信息。
本章将介绍如何创建一个从用户那搜集数据的表单页。该页将显示一个包含 name 输入框和 email 输入框的表单。当搜集完这两部分信息后,页面将会显示用户输入的信息。
为了实现这个目标,除了创建一个[操作](structure-controllers.md)和两个[视图](structure-views)外,还需要创建一个[模型](structure-models.md)
......@@ -39,11 +39,11 @@ class EntryForm extends Model
}
```
该类继承自 [[yii\base\Model]],Yii 提供的一个基类,通常用来表示数据。
该类继承自 [[yii\base\Model]],Yii 提供的一个基类,通常用来代表表单数据。
> 补充:[[yii\base\Model]] 被用于普通模型类的父类并与数据表**无关**。[[yii\db\ActiveRecord]] 通常是普通模型类的父类但与数据表有关联(译者注:[[yii\db\ActiveRecord]] 类其实也是继承自 [[yii\base\Model]],增加了数据库处理)
> 补充:[[yii\base\Model]] 被用于普通模型类的父类并与数据表**无关**。[[yii\db\ActiveRecord]] 通常是普通模型类的父类但与数据表有关联。
`EntryForm` 类包含 `name``email` 两个公共成员,用来储存用户输入的数据。它还包含一个名为 `rules()` 的方法,用来返回数据验证规则的集合。上面声明的验证规则表示:
`EntryForm` 类包含 `name``email` 两个公共变量,用来储存用户输入的数据。它还包含一个名为 `rules()` 的方法,用来返回数据验证规则的集合。上面声明的验证规则表示:
* `name``email` 值都是必须的
* `mail` 的值必须满足 email 地址验证
......@@ -67,7 +67,7 @@ if ($model->validate()) {
创建操作 <a name="creating-action"></a>
------------------
下面你得`site` 控制器中创建一个 `entry` 操作用于新建的模型。操作的创建和使用已经在[说一声你好](start-hello.md)小节中解释了。
接下来你需要`site` 控制器中创建一个 `entry` 操作用于新建的模型。操作的创建和使用已经在[说一声你好](start-hello.md)小节中解释了。
```php
<?php
......@@ -104,7 +104,7 @@ class SiteController extends Controller
> 补充:表达式 `Yii::$app` 代表[应用](structure-applications.md)实例,它是一个全局可访问的单例。同时它也是一个[服务定位器](concept-service-locator.md),能提供 `request`,`response`,`db` 等等特定功能的组件。在上面的代码里就是使用 `request` 组件来访问应用实例收到的 `$_POST` 数据。
用户提交表单后,操作将会渲染一个名为 `entry-confirm` 的视图去确认用户输入的数据。如果没填表单就提交,或数据包含错误(译者:如 email 格式不对)`entry` 视图将会渲染输出,连同表单一起输出的还有验证错误的详细信息。
用户提交表单后,操作将会渲染一个名为 `entry-confirm` 的视图去确认用户输入的数据。如果没填表单就提交,或数据包含错误,`entry` 视图将会渲染输出,连同表单一起输出的还有验证错误的详细信息。
> 注意:在这个简单例子里我们只是呈现了有效数据的确认页面。实践中你应该考虑使用 [[yii\web\Controller::refresh()|refresh()]] 或 [[yii\web\Controller::redirect()|redirect()]] 去避免[表单重复提交问题](http://en.wikipedia.org/wiki/Post/Redirect/Get)。
......@@ -148,10 +148,10 @@ use yii\widgets\ActiveForm;
<?php ActiveForm::end(); ?>
```
视图使用了一个功能强大的[小部件](structure-widgets.md) [[yii\widgets\ActiveForm|ActiveForm]] 去生成 HTML 表单。其中的 `begin()``end()` 分别用来渲染表单的开始和关闭标签。在这两个方法之间使用了 [[yii\widgets\ActiveForm::field()|field()]] 方法去创建输入框。第一个输入框用于 “name”,第二个输入框用于 “email”。之后使用 [[yii\helpers\Html::submitButton()]] 方法生成提交按钮。
视图使用了一个功能强大的[小部件](structure-widgets.md) [[yii\widgets\ActiveForm|ActiveForm]] 去生成 HTML 表单。其中的 `begin()``end()` 分别用来渲染表单的开始和关闭标签。在这两个方法之间使用了 [[yii\widgets\ActiveForm::field()|field()]] 方法去创建表单栏。第一个表单栏用于 “name”,第二个表单栏用于 “email”。之后使用 [[yii\helpers\Html::submitButton()]] 方法生成提交按钮。
尝试下 <a name="trying-it-out"></a>
试运行 <a name="trying-it-out"></a>
-------------
用浏览器访问下面的 URL 看它能否工作:
......@@ -160,7 +160,7 @@ use yii\widgets\ActiveForm;
http://hostname/index.php?r=site/entry
```
你会看到一个包含两个输入框的表单的页面。每个输入框的前面都有一个标签指明应该输入的数据类型。如果什么都不填就点击提交按钮,或填入格式不正确的 email 地址,将会看到在对应的输入框下显示错误信息。
你会看到一个包含两个表单栏的页面。每个表单栏的前面都有一个标签指明应该输入的数据类型。如果什么都不填就点击提交按钮,或填入格式不正确的 email 地址,将会看到在对应的表单栏下显示错误信息。
![验证错误的表单](images/start-form-validation.png)
......@@ -172,13 +172,13 @@ http://hostname/index.php?r=site/entry
### 效果说明 <a name="magic-explained"></a>
你可能会好奇 HTML 表单暗地里是如何工作的呢,看起来它可以为每个输入框显示文字标签,而当你没输入正确的信息时又不需要刷新页面就能给出错误提示,似乎有些神奇。
你可能会好奇 HTML 表单暗地里是如何工作的,看起来它可以为每个表单栏显示文字标签,而当你没输入正确的信息时又不需要刷新页面就能给出错误提示,似乎有些神奇。
是的,其实数据首先由客户端 JavaScript 脚本验证,然后才会提交给服务器通过 PHP 验证。[[yii\widgets\ActiveForm]] 足够智能到把你在 `EntryForm` 模型中声明的验证规则转化成客户端 JavaScript 脚本去执行验证。如果用户浏览器禁用了 JavaScript, 服务器端仍然会像 `actionEntry()` 方法里这样验证一遍数据。这保证了任何情况下用户提交的数据都是有效的。
> 警告:客户端验证是提高用户体验的手段。无论它是否正常启用,服务端验证则都是必须的,请不要忽略它。
> 警告:客户端验证是提高用户体验的手段。无论它是否正常启用,服务端验证则都是必须的,请不要忽略它。
输入框的文字标签是 `field()` 方法生成的,内容就是模型中该数据的属性名。例如模型中的 `name` 属性生成的标签就是 `Name`
表单栏的文字标签是 `field()` 方法生成的,内容就是模型中该数据的属性名。例如模型中的 `name` 属性生成的标签就是 `Name`
你可以在视图中自定义标签:
......@@ -193,7 +193,7 @@ http://hostname/index.php?r=site/entry
总结 <a name="summary"></a>
-------
本章指南中你接触了 MVC 设计模式的每个部分。学到了如何创建一个模型代表用户数据并验证它的有效性。
本章指南中你接触了 MVC 设计模式的每个部分。学到了如何创建一个模型代表用户数据并验证它的有效性。
你还学到了如何从用户那获取数据并在浏览器上回显给用户。这本来是开发应用的过程中比较耗时的任务,好在 Yii 提供了强大的小部件让它变得如此简单。
......
使用 Gii 生成代码
========================
本章将介绍如何使用 [Gii](tool-gii.md) 去自动生成 Web 站点常用功能的代码。使用 Gii 生成代码非常简单,只要按照 Gii 页面上的介绍输入正确的信息即可。
本章将介绍如何使用 [Gii](tool-gii.md) 去自动生成 Web 站点常用功能的代码。使用 Gii 生成代码非常简单,只要按照 Gii 页面上的介绍输入正确的信息即可。
贯穿本章节,你将会学到:
......@@ -25,7 +25,7 @@ if (YII_ENV_DEV) {
}
```
这段配置的意思是如果当前是[开发环境](concept-configurations.md#environment-constants),应用会包含 `gii` 模块,模块类是 [[yii\gii\Module]]。
这段配置表明,如果当前是[开发环境](concept-configurations.md#environment-constants),应用会包含 `gii` 模块,模块类是 [[yii\gii\Module]]。
如果你检查应用的[入口脚本](structure-entry-scripts.md) `web/index.php`,将看到这行代码将 `YII_ENV_DEV` 设为 true:
......@@ -33,16 +33,18 @@ if (YII_ENV_DEV) {
defined('YII_ENV') or define('YII_ENV', 'dev');
```
代码设置应用处于开发模式下,按照上面的配置会打开 Gii 模块。你可以直接通过 URL 访问 Gii:
鉴于这行代码的定义,应用处于开发模式下,按照上面的配置会打开 Gii 模块。你可以直接通过 URL 访问 Gii:
```
http://hostname/index.php?r=gii
```
> 提示:如果不是通过localhost而是通过IP地址访问Gii,出于安全考虑系统默认禁止,按照如下在配置文件的gii部分添加允许IP地址访问。
> 补充: 如果你通过本机以外的机器访问 Gii,请求会被出于安全原因拒绝。你可以配置 Gii 为其添加允许访问的 IP 地址:
>
```php
'gii' => [
'class' => 'yii\gii\Module',
'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.178.20'] // 根据你自己的需要调整
'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.178.20'] // 按需调整这里
],
```
......@@ -61,7 +63,7 @@ http://hostname/index.php?r=gii
然后点击 “Preview” 按钮。你会看到 `models/Country.php` 被列在将要生成的文件列表中。可以点击文件名预览内容。
如果你已经创建过同样的文件,使用 Gii 可以覆写它,点击文件名旁边的 `diff` 能查看现有文件与将要生成的文件的内容区别。
如果你已经创建过同样的文件,使用 Gii 覆写它,点击文件名旁边的 `diff` 能查看现有文件与将要生成的文件的内容区别。
![模型生成器预览](images/start-gii-model-preview.png)
......@@ -73,7 +75,7 @@ http://hostname/index.php?r=gii
生成 CRUD 代码 <a name="generating-crud"></a>
--------------------
CRUD 代表增,查,改,删操作,这是绝大多数 Web 站点常用的数据处理方式。选择 Gii 中的 “CRUD Generator” (点击 Gii 首页的链接)去创建 CRUD 功能。之前的 “country” 例子需要像这样填写表单:
CRUD 代表增,查,改,删操作,这是绝大多数 Web 站点常用的数据处理方式。选择 Gii 中的 “CRUD Generator” (点击 Gii 首页的链接)去创建 CRUD 功能。本例 “country” 中需要这样填写表单:
* Model Class: `app\models\Country`
* Search Model Class: `app\models\CountrySearch`
......@@ -83,12 +85,12 @@ CRUD 代表增,查,改,删操作,这是绝大多数 Web 站点常用的
然后点击 “Preview” 按钮。你会看到下述将要生成的文件列表。
![CRUD 生成器预览](images/start-gii-crud-preview.png)
[[NEED THE IMAGE HERE / 等待官方补充图片]]
如果你之前创建过 `controllers/CountryController.php``views/country/index.php` 文件(在指南的使用数据库节),选中 “overwrite” 下的复选框覆写它们(之前的文件没能全部支持 CRUD)。
如果你之前创建过 `controllers/CountryController.php``views/country/index.php` 文件(在指南的使用数据库节),选中 “overwrite” 下的复选框覆写它们(之前的文件没能全部支持 CRUD)。
尝试下<a name="trying-it-out"></a>
试运行 <a name="trying-it-out"></a>
-------------
用浏览器访问下面的 URL 查看生成代码的运行:
......@@ -97,7 +99,7 @@ CRUD 代表增,查,改,删操作,这是绝大多数 Web 站点常用的
http://hostname/index.php?r=country/index
```
可以看到一个栅格显示着从数据表中取的国家数据。支持在列头对数据进行排序,输入筛选条件进行筛选。
可以看到一个栅格显示着从数据表中取的国家数据。支持在列头对数据进行排序,输入筛选条件进行筛选。
可以浏览详情,编辑,或删除栅格中的每个国家。还可以点击栅格上方的 “Create Country” 按钮通过表单创建新国家。
......@@ -111,7 +113,7 @@ http://hostname/index.php?r=country/index
* 模型:`models/Country.php``models/CountrySearch.php`
* 视图:`views/country/*.php`
> 补充:Gii 被设计成高度可定制和可扩展的代码生成工具。使用它可以大幅提高应用开发速度。请参考 [Gii](tool-gii.md) 节了解更多内容。
> 补充:Gii 被设计成高度可定制和可扩展的代码生成工具。使用它可以大幅提高应用开发速度。请参考 [Gii](tool-gii.md) 节了解更多内容。
总结 <a name="summary"></a>
......
说声 Hello
============
本章节描述了如何在你的应用中创建一个新的 “Hello” 页面。为了做到这点,将会创建一个[操作](structure-controllers.md#creating-actions)和一个[视图](structure-views.md)
本章描述了如何在你的应用中创建一个新的 “Hello” 页面。为了实现这一目标,将会创建一个[操作](structure-controllers.md#creating-actions)和一个[视图](structure-views.md)
* 应用将会分派页面请求给操作
* 操作将会依次渲染视图呈现 “Hello” 给最终用户
......@@ -16,7 +16,7 @@
创建操作 <a name="creating-action"></a>
------------------
为了 “Hello”,需要创建一个 `say` [操作](structure-controllers.md#creating-actions),从请求中接收 `message` 参数并显示给最终用户。如果请求没有提供 `message` 参数,操作将显示默认参数 “Hello”。
为了 “Hello”,需要创建一个 `say` [操作](structure-controllers.md#creating-actions),从请求中接收 `message` 参数并显示给最终用户。如果请求没有提供 `message` 参数,操作将显示默认参数 “Hello”。
> 补充:[操作](structure-controllers.md#creating-actions)是最终用户可以直接访问并执行的对象。操作被组织在[控制器](structure-controllers.md)中。一个操作的执行结果就是最终用户收到的响应内容。
......@@ -33,7 +33,7 @@ class SiteController extends Controller
{
// ...其它代码...
public function actionSay($message = '你好')
public function actionSay($message = 'Hello')
{
return $this->render('say', ['message' => $message]);
}
......@@ -68,7 +68,7 @@ use yii\helpers\Html;
当然了,你大概会在 `say` 视图里放入更多内容。内容可以由 HTML 标签,纯文本,甚至 PHP 语句组成。实际上 `say` 视图就是一个由 [[yii\web\Controller::render()|render()]] 执行的 PHP 脚本。视图脚本输出的内容将会作为响应结果返回给应用。应用将依次输出结果给最终用户。
尝试下 <a name="trying-it-out"></a>
试运行 <a name="trying-it-out"></a>
-------------
创建完操作和视图后,你就可以通过下面的 URL 访问新页面了:
......
......@@ -90,9 +90,9 @@ http://localhost/basic/web/index.php
>补充:如果你现在只是要试用 Yii 而不是将其部署到生产环境中,本小节可以跳过。
通过上述方法安装的应用程序在 Windows,Max OS X,Linux 中的 [Apache HTTP 服务器](http://httpd.apache.org/)或 [Nginx HTTP 服务器](http://nginx.org/) 且PHP版本为5.4或更高都可以直接运行。Yii 2.0 也兼容 Facebook 公司的 [HHVM](http://hhvm.com/),由于 HHVM 和标准 PHP 在边界案例上有些地方略有不同,在使用 HHVM 时需稍作处理。
通过上述方法安装的应用程序在 Windows,Max OS X,Linux 中的 [Apache HTTP 服务器](http://httpd.apache.org/)或 [Nginx HTTP 服务器](http://nginx.org/)且PHP版本为5.4或更高都可以直接运行。Yii 2.0 也兼容 Facebook 公司的 [HHVM](http://hhvm.com/),由于 HHVM 和标准 PHP 在边界案例上有些地方略有不同,在使用 HHVM 时需稍作处理。
在生产环境的服务器上,你可能会想配置服务器让应用程序可以通过 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` 相邻目录中的私有应用代码和敏感数据文件。禁止对其他目录的访问是一个不错的安全改进。
......@@ -141,7 +141,7 @@ server {
error_log /path/to/basic/log/error.log;
location / {
# 如果找不到真实存在的文件,把请求重定向给 index.php
# 如果找不到真实存在的文件,把请求分发至 index.php
try_files $uri $uri/ /index.php?$args;
}
......
更上一层楼
=============
通篇阅读完整个“入门”板块,你就完成了一个完整 Yii 应用的创建。在此过程中你学到了如何实现一些常用功能,例如通过 HTML 表单从用户那获取数据,从数据库中获取数据并以分页形式显示。你还学到了如何通过 [Gii](tool-gii.md) 去自动生成代码。使用 Gii 生成代码把 Web 开发中多数繁杂的过程转化为仅仅填写几个表单就行。
通篇阅读完整个“入门”部分,你就完成了一个完整 Yii 应用的创建。在此过程中你学到了如何实现一些常用功能,例如通过 HTML 表单从用户那获取数据,从数据库中获取数据并以分页形式显示。你还学到了如何通过 [Gii](tool-gii.md) 去自动生成代码。使用 Gii 生成代码把 Web 开发中多数繁杂的过程转化为仅仅填写几个表单就行。
本章将介绍一些有助于更好使用 Yii 的资源:
本章将介绍一些有助于更好使用 Yii 的资源:
* 文档
- 权威指南:
顾名思义,指南详细描述了 Yii 的工作原理并提供了如何使用它的常规引导。这是最重要的 Yii 辅助资料,强烈建议在开始写 Yii 代码之前阅读。
- 类参考手册:
描述了 Yii 中每个类的用法。在编码过程中这极为有用,能够帮你理清某个特定类,方法,和属性的用法。类参考手册最好在整个框架的语境下去理解。
- Wiki 文章:
Wiki 文章是 Yii 用户在其自身经验基础上分享出来的。大多数是使用教程或如何使用 Yii 解决特定问题。虽然这些文章质量可能并不如权威指南,但它们往往覆盖了更广泛的话题,并常常提供解决方案,所以它们也很有用。
- 权威指南:顾名思义,指南详细描述了 Yii 的工作原理并提供了如何使用它的常规引导。这是最重要的 Yii 辅助资料,强烈建议在开始写 Yii 代码之前阅读。
- 类参考手册:描述了 Yii 中每个类的用法。在编码过程中这极为有用,能够帮你理清某个特定类,方法,和属性的用法。类参考手册最好在整个框架的语境下去理解。
- Wiki 文章:Wiki 文章是 Yii 用户在其自身经验基础上分享出来的。大多数是使用教程或如何使用 Yii 解决特定问题。虽然这些文章质量可能并不如权威指南,但它们往往覆盖了更广泛的话题,并常常提供解决方案,所以它们也很有用。
- 书籍
* [扩展](http://www.yiiframework.com/extensions/):
Yii 拥有数以千计用户提供的扩展,这些扩展能非常方便的插入到应用中,使你的应用开发过程更加方便快捷。
* [扩展](http://www.yiiframework.com/extensions/):Yii 拥有数以千计用户提供的扩展,这些扩展能非常方便的插入到应用中,使你的应用开发过程更加方便快捷。
* 社区
- [官方论坛](http://www.yiiframework.com/forum/)
- [GitHub](https://github.com/yiisoft/yii2)
......
应用组件
======================
应用主体是[服务定位器](concept-service-locator.md),它部署一组提供各种不同功能的 *应用组件* 来处理请求。
例如,`urlManager`组件负责处理网页请求路由到对应的控制器。`db`组件提供数据库相关服务等等。
在同一个应用中,每个应用组件都有一个独一无二的 ID 用来区分其他应用组件,你可以通过如下表达式访问应用组件。
```php
\Yii::$app->componentID
```
例如,可以使用 `\Yii::$app->db` 来获取到已注册到应用的 [[yii\db\Connection|DB connection]],
使用 `\Yii::$app->cache` 来获取到已注册到应用的 [[yii\caching\Cache|primary cache]]。
第一次使用以上表达式时候会创建应用组件实例,后续再访问会返回此实例,无需再次创建。
应用组件可以是任意对象,可以在 [应用主体配置](structure-applications.md#application-configurations)配置 [[yii\base\Application::components]] 属性 .
例如:
```php
[
'components' => [
// 使用类名注册 "cache" 组件
'cache' => 'yii\caching\ApcCache',
// 使用配置数组注册 "db" 组件
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=demo',
'username' => 'root',
'password' => '',
],
// 使用函数注册"search" 组件
'search' => function () {
return new app\components\SolrService;
},
],
]
```
> 补充:请谨慎注册太多应用组件,应用组件就像全局变量,使用太多可能加大测试和维护的难度。
一般情况下可以在需要时再创建本地组件。
## 引导启动组件 <a name="bootstrapping-components"></a>
上面提到一个应用组件只会在第一次访问时实例化,如果处理请求过程没有访问的话就不实例化。
有时你想在每个请求处理过程都实例化某个组件即便它不会被访问,
可以将该组件ID加入到应用主体的 [[yii\base\Application::bootstrap|bootstrap]] 属性中。
例如, 如下的应用主体配置保证了 `log` 组件一直被加载。
```php
[
'bootstrap' => [
// 将 log 组件 ID 加入引导让它始终载入
'log',
],
'components' => [
'log' => [
// "log" 组件的配置
],
],
]
```
## 核心应用组件 <a name="core-application-components"></a>
Yii 定义了一组固定ID和默认配置的 *核心* 组件,例如 [[yii\web\Application::request|request]] 组件
用来收集用户请求并解析 [路由](runtime-routing.md)
[[yii\base\Application::db|db]] 代表一个可以执行数据库操作的数据库连接。
通过这些组件,Yii应用主体能处理用户请求。
下面是预定义的核心应用组件列表,可以和普通应用组件一样配置和自定义它们。
当你配置一个核心组件,不指定它的类名的话就会使用Yii默认指定的类。
* [[yii\web\AssetManager|assetManager]]: 管理资源包和资源发布,详情请参考 [管理资源](output-assets.md) 一节。
* [[yii\db\Connection|db]]: 代表一个可以执行数据库操作的数据库连接,
注意配置该组件时必须指定组件类名和其他相关组件属性,如[[yii\db\Connection::dsn]]。
详情请参考 [数据访问对象](db-dao.md) 一节。
* [[yii\base\Application::errorHandler|errorHandler]]: 处理 PHP 错误和异常,
详情请参考 [错误处理](tutorial-handling-errors.md) 一节。
* [[yii\i18n\Formatter|formatter]]: 格式化输出显示给终端用户的数据,例如数字可能要带分隔符,
日期使用长格式。详情请参考 [格式化输出数据](output-formatting.md) 一节。
* [[yii\i18n\I18N|i18n]]: 支持信息翻译和格式化。详情请参考 [国际化](tutorial-i18n.md) 一节。
* [[yii\log\Dispatcher|log]]: 管理日志对象。详情请参考 [日志](tutorial-logging.md) 一节。
* [[yii\swiftmailer\Mailer|mail]]: 支持生成邮件结构并发送,详情请参考 [邮件](tutorial-mailing.md) 一节。
* [[yii\base\Application::response|response]]: 代表发送给用户的响应,
详情请参考 [响应](runtime-responses.md) 一节。
* [[yii\base\Application::request|request]]: 代表从终端用户处接收到的请求,
详情请参考 [请求](runtime-requests.md) 一节。
* [[yii\web\Session|session]]: 代表会话信息,仅在[[yii\web\Application|Web applications]] 网页应用中可用,
详情请参考 [Sessions (会话) and Cookies](runtime-sessions-cookies.md) 一节。
* [[yii\web\UrlManager|urlManager]]: 支持URL地址解析和创建,
详情请参考 [URL 解析和生成](runtime-url-handling.md) 一节。
* [[yii\web\User|user]]: 代表认证登录用户信息,仅在[[yii\web\Application|Web applications]] 网页应用中可用,
详情请参考 [认证](security-authentication.md) 一节。
* [[yii\web\View|view]]: 支持渲染视图,详情请参考 [Views](structure-views.md) 一节。
入口脚本
=============
入口脚本是应用启动流程中的第一环,一个应用(不管是网页应用还是控制台应用)只有一个入口脚本。终端用户的请求通过入口脚本实例化应用并将将请求转发到应用。
Web 应用的入口脚本必须放在终端用户能够访问的目录下,通常命名为 `index.php`,也可以使用 Web 服务器能定位到的其他名称。
控制台应用的入口脚本一般在应用根目录下命名为 `yii`(后缀为.php),该文件需要有执行权限,这样用户就能通过命令 `./yii <route> [arguments] [options]` 来运行控制台应用。
入口脚本主要完成以下工作:
* 定义全局常量;
* 注册 [Composer 自动加载器](http://getcomposer.org/doc/01-basic-usage.md#autoloading)
* 包含 [[Yii]] 类文件;
* 加载应用配置;
* 创建一个[应用](structure-applications.md)实例并配置;
* 调用 [[yii\base\Application::run()]] 来处理请求。
## Web 应用 <a name="web-applications"></a>
以下是[基础应用模版](start-installation.md)入口脚本的代码:
```php
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
// 注册 Composer 自动加载器
require(__DIR__ . '/../vendor/autoload.php');
// 包含 Yii 类文件
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
// 加载应用配置
$config = require(__DIR__ . '/../config/web.php');
// 创建、配置、运行一个应用
(new yii\web\Application($config))->run();
```
## 控制台应用 <a name="console-applications"></a>
以下是一个控制台应用的入口脚本:
```php
#!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
defined('YII_DEBUG') or define('YII_DEBUG', true);
// fcgi 默认没有定义 STDIN 和 STDOUT
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
// 注册 Composer 自动加载器
require(__DIR__ . '/vendor/autoload.php');
// 包含 Yii 类文件
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
// 加载应用配置
$config = require(__DIR__ . '/config/console.php');
$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);
```
## 定义常量 <a name="defining-constants"></a>
入口脚本是定义全局常量的最好地方,Yii 支持以下三个常量:
* `YII_DEBUG`:标识应用是否运行在调试模式。当在调试模式下,应用会保留更多日志信息,如果抛出异常,会显示详细的错误调用堆栈。因此,调试模式主要适合在开发阶段使用,`YII_DEBUG` 默认值为 false。
* `YII_ENV`:标识应用运行的环境,详情请查阅[配置](concept-configurations.md#environment-constants)章节。`YII_ENV` 默认值为 `'prod'`,表示应用运行在线上产品环境。
* `YII_ENABLE_ERROR_HANDLER`:标识是否启用 Yii 提供的错误处理,默认为 true。
当定义一个常量时,通常使用类似如下代码来定义:
```php
defined('YII_DEBUG') or define('YII_DEBUG', true);
```
上面的代码等同于:
```php
if (!defined('YII_DEBUG')) {
define('YII_DEBUG', true);
}
```
显然第一段代码更加简洁易懂。
常量定义应该在入口脚本的开头,这样包含其他 PHP 文件时,常量就能生效。
\ No newline at end of file
总览
========
Yii 应用参照[模型-视图-控制器 (MVC)](http://wikipedia.org/wiki/Model-view-controller)
设计模式来组织。 [模型](structure-models.md)代表数据、业务逻辑和规则;[视图](structure-views.md)展示模型的输出;[控制器](structure-controllers.md)接受出入并将其转换为[模型](structure-models.md)[视图](structure-views.md)命令。
除了 MVC, Yii 应用还有以下部分:
* [入口脚本](structure-entry-scripts.md):终端用户能直接访问的 PHP 脚本,负责启动一个请求处理周期。
* [应用](structure-applications.md):能全局范围内访问的对象,管理协调组件来完成请求.
* [应用组件](structure-application-components.md):在应用中注册的对象,提供不同的功能来完成请求。
* [模块](structure-modules.md):包含完整 MVC 结构的独立包,一个应用可以由多个模块组建。
* [过滤器](structure-filters.md):控制器在处理请求之前或之后需要触发执行的代码。
* [小部件](structure-widgets.md):可嵌入到[视图](structure-views.md)中的对象,可包含控制器逻辑,可被不同视图重复调用。
下面的示意图展示了 Yii 应用的静态结构:
![Yii应用静态结构](images/application-structure.png)
......@@ -125,6 +125,10 @@ All cache components have the same base class [[yii\caching\Cache]] and thus sup
* [[yii\caching\Cache::delete()|delete()]]: removes a data item identified by a key from the cache.
* [[yii\caching\Cache::flush()|flush()]]: removes all data items from the cache.
> Note: Do not cache a `false` boolean value directly because the [[yii\caching\Cache::get()|get()]] method uses
`false` return value to indicate the data item is not found in the cache. You may put `false` in an array and cache
this array instead to avoid this problem.
Some cache storage, such as MemCache, APC, support retrieving multiple cached values in a batch mode,
which may reduce the overhead involved in retrieving cached data. The APIs [[yii\caching\Cache::mget()|mget()]]
and [[yii\caching\Cache::madd()|madd()]] are provided to exploit this feature. In case the underlying cache storage
......
......@@ -47,7 +47,7 @@ if ($this->beginCache($id, ['duration' => 3600])) {
}
```
If the option is not set, it will take the default value 0, which means the cached content will never expire.
If the option is not set, it will take the default value 60, which means the cached content will expire in 60 seconds.
### Dependencies <a name="dependencies"></a>
......
......@@ -191,7 +191,7 @@ WHERE `id` IN (SELECT `id` FROM `user`)
Another way to use the method is the operand format which is `[operator, operand1, operand2, ...]`.
Operator can be one of the following:
Operator can be one of the following (see also [[yii\db\QueryInterface::where()]]):
- `and`: the operands should be concatenated together using `AND`. For example,
`['and', 'id=1', 'id=2']` will generate `id=1 AND id=2`. If an operand is an array,
......
......@@ -19,7 +19,7 @@ Yii 2.0 fully embraces [Composer](https://getcomposer.org/), the de facto PHP pa
of the core framework, as well as extensions, are handled through Composer. Please refer to
the [Installing Yii](start-installation.md) section to learn how to install Yii 2.0. If you want to
create new extensions, or turn your existing 1.1 extensions into 2.0-compatible extensions, please refer to
the [Creating Extensions](extend-creating-extensions.md) section of the guide.
the [Creating Extensions](structure-extensions.md#creating-extensions) section of the guide.
PHP Requirements
......@@ -209,7 +209,7 @@ To learn more details about models, please refer to the [Models](structure-model
Controllers
-----------
Yii 2.0 uses [[yii\web\Controller]] as the base controller class, similar to `CWebController` in Yii 1.1.
Yii 2.0 uses [[yii\web\Controller]] as the base controller class, which is similar to `CController` in Yii 1.1.
[[yii\base\Action]] is the base class for action classes.
The most obvious impact of these changes on your code is that a controller action should return the content
......
......@@ -85,20 +85,20 @@ If you already have a formatted body string, you may assign it to the [[yii\web\
of the response. For example,
```php
Yii::$app->request->content = 'hello world!';
Yii::$app->response->content = 'hello world!';
```
If you data needs to be formatted before sending to end users, you should set both of the
If your data needs to be formatted before sending it to end users, you should set both of the
[[yii\web\Response::format|format]] and [[yii\web\Response::data|data]] properties. The [[yii\web\Response::format|format]]
property specifies in which format should the [[yii\web\Response::data|data]] be formatted as. For example,
property specifies in which format the [[yii\web\Response::data|data]] should be formatted. For example,
```php
$response = Yii::$app->request;
$response = Yii::$app->response;
$response->format = \yii\web\Response::FORMAT_JSON;
$response->data = ['message' => 'hello world'];
```
Yii supports the following formats out of box, each implemented by a [[yii\web\ResponseFormatterInterface|formatter]] class.
Yii supports the following formats out of the box, each implemented by a [[yii\web\ResponseFormatterInterface|formatter]] class.
You can customize these formatters or add new ones by configuring the [[yii\web\Response::formatters]] property.
* [[yii\web\Response::FORMAT_HTML|HTML]]: implemented by [[yii\web\HtmlResponseFormatter]].
......@@ -135,7 +135,7 @@ public function actionInfo()
```
As aforementioned, besides using the default `response` application component, you can also create your own
response objects and send them to end users. You can do so by returning such an object in an action method, like the following,
response objects and send them to end users. You can do so by returning such object in an action method, like the following,
```php
public function actionInfo()
......
......@@ -288,16 +288,24 @@ examples, the [[yii\web\Cookie]] class also defines other properties to fully re
of cookies, such as [[yii\web\Cookie::domain|domain]], [[yii\web\Cookie::expire|expire]]. You may configure these
properties as needed to prepare a cookie and then add it to the response's cookie collection.
> Note: For better security, the default value of [[yii\web\Cookie::httpOnly]] is set true. This helps mitigate
the risk of client side script accessing the protected cookie (if the browser supports it). You may read
the [httpOnly wiki article](https://www.owasp.org/index.php/HttpOnly) for more details.
### Cookie Validation <a name="cookie-validation"></a>
When you are reading and sending cookies through the `request` and `response` components like shown in the last
two subsections, you enjoy the added security of cookie validation which protects cookies from being modified
on the client side. This is achieved by signing each cookie with a hash string. If a cookie is modified somehow,
it will fail the validation of its associated hash and will be removed from the cookie collection in the request.
on the client side. This is achieved by signing each cookie with a hash string, which allows the application to
tell if a cookie is modified on the client side or not. If so, the cookie will NOT be accessible through the
[[yii\web\Request::cookies|cookie collection]] of the `request` component.
> Info: If a cookie fails the validation, you may still access it through `$_COOKIE`. This is because third-party
libraries may manipulate cookies in their own way, which does not involve cookie validation.
Cookie validation is enabled by default. You can disable it by setting the [[yii\web\Request::enableCookieValidation]]
property to be false, although we recommend you not to do so.
property to be false, although we strongly recommend you do not do so.
> Note: Cookies that are directly read/sent via `$_COOKIE` and `setcookie()` will NOT be validated.
......
URL Management
==============
URL Parsing and Generation
==========================
> Note: This section is under development.
......
......@@ -2,7 +2,7 @@ Installing Yii
==============
You can install Yii in two ways, using [Composer](http://getcomposer.org/) or by downloading an archive file.
The former is the preferred way, as it allows you to install new [extensions](extend-creating-extensions.md) or update Yii by simply running a single command.
The former is the preferred way, as it allows you to install new [extensions](structure-extensions.md) or update Yii by simply running a single command.
> Note: Unlike with Yii 1, standard installations of Yii 2 result in both, the framework and an application skeleton being downloaded and installed.
......
......@@ -87,20 +87,20 @@ like you do with normal application components. When you are configuring a core
if you do not specify its class, the default one will be used.
* [[yii\web\AssetManager|assetManager]]: manages asset bundles and asset publishing.
Please refer to the [Managing Assets](output-assets.md) section for more details.
Please refer to the [Managing Assets](structure-assets.md) section for more details.
* [[yii\db\Connection|db]]: represents a database connection through which you can perform DB queries.
Note that when you configure this component, you must specify the component class as well as other required
component properties, such as [[yii\db\Connection::dsn]].
Please refer to the [Data Access Objects](db-dao.md) section for more details.
* [[yii\base\Application::errorHandler|errorHandler]]: handles PHP errors and exceptions.
Please refer to the [Handling Errors](tutorial-handling-errors.md) section for more details.
Please refer to the [Handling Errors](runtime-handling-errors.md) section for more details.
* [[yii\i18n\Formatter|formatter]]: formats data when they are displayed to end users. For example, a number
may be displayed with thousand separator, a date may be formatted in long format.
Please refer to the [Data Formatting](output-formatting.md) section for more details.
Please refer to the [Data Formatting](output-formatter.md) section for more details.
* [[yii\i18n\I18N|i18n]]: supports message translation and formatting.
Please refer to the [Internationalization](tutorial-i18n.md) section for more details.
* [[yii\log\Dispatcher|log]]: manages log targets.
Please refer to the [Logging](tutorial-logging.md) section for more details.
Please refer to the [Logging](runtime-logging.md) section for more details.
* [[yii\swiftmailer\Mailer|mail]]: supports mail composing and sending.
Please refer to the [Mailing](tutorial-mailing.md) section for more details.
* [[yii\base\Application::response|response]]: represents the response being sent to end users.
......
......@@ -523,7 +523,7 @@ to insert your custom code via the event mechanism to intercept the request hand
in the event handler, you may dynamically set the [[yii\base\Application::language]] property based on some parameters.
### [[yii\base\Application::EVENT_BEFORE_REQUEST|EVENT_AFTER_REQUEST]] <a name="afterRequest"></a>
### [[yii\base\Application::EVENT_AFTER_REQUEST|EVENT_AFTER_REQUEST]] <a name="afterRequest"></a>
This event is triggered *after* an application finishes handling a request but *before* sending the response.
The actual event name is `afterRequest`.
......@@ -535,7 +535,7 @@ Note that the [[yii\web\Response|response]] component also triggers some events
response content to end users. Those events are triggered *after* this event.
### [[yii\base\Application::EVENT_BEFORE_REQUEST|EVENT_BEFORE_ACTION]] <a name="beforeAction"></a>
### [[yii\base\Application::EVENT_BEFORE_ACTION|EVENT_BEFORE_ACTION]] <a name="beforeAction"></a>
This event is triggered *before* running every [controller action](structure-controllers.md).
The actual event name is `beforeAction`.
......@@ -561,7 +561,7 @@ triggering this event, followed by modules (if any), and finally controllers. If
sets [[yii\base\ActionEvent::isValid]] to be `false`, all the following events will NOT be triggered.
### [[yii\base\Application::EVENT_BEFORE_REQUEST|EVENT_AFTER_ACTION]] <a name="afterAction"></a>
### [[yii\base\Application::EVENT_AFTER_ACTION|EVENT_AFTER_ACTION]] <a name="afterAction"></a>
This event is triggered *after* running every [controller action](structure-controllers.md).
The actual event name is `afterAction`.
......
......@@ -29,7 +29,7 @@ forum/
### Module Classes <a name="module-classes"></a>
Each module should have a module class which extends from [[yii\base\Module]]. The class should be located
Each module should have a unique module class which extends from [[yii\base\Module]]. The class should be located
directly under the module's [[yii\base\Module::basePath|base path]] and should be [autoloadable](concept-autoloading.md).
When a module is being accessed, a single instance of the corresponding module class will be created.
Like [application instances](structure-applications.md), module instances are used to share data and components
......@@ -173,7 +173,7 @@ different from the one created by Yii in response to a request.
You may also access the instance of a module using the following approaches:
```php
// get the module whose ID is "forum"
// get the child module whose ID is "forum"
$module = \Yii::$app->getModule('forum');
// get the module to which the currently requested controller belongs
......@@ -239,6 +239,10 @@ For a controller within a nested module, its route should include the IDs of all
For example, the route `forum/admin/dashboard/index` represents the `index` action of the `dashboard` controller
in the `admin` module which is a child module of the `forum` module.
> Info: The [[yii\base\Module::getModule()|getModule()]] method only returns the child module directly belonging
to its parent. The [[yii\base\Application::loadedModules]] property keeps a list of loaded modules, including both
direct children and nested ones, indexed by their class names.
## Best Practices <a name="best-practices"></a>
......
O'zbekchaga tarjima qilish bilan qanday ishlash kerak
=====================================================
Yii juda ko'p tillarga tarjima qilinayabdi shu jumladan o'zbekchaga ham. Tarjima qo'llanma va habarlarni o'z ichiga oladi.
Freymvork habari
----------------
Ikki turdagi habarlar bor: istisnolar, qaysiki ishlab chiquvchi nazarda tutgan va ular tarjima qilinmaydi va habarlar, qaysiki foydalanuvchilarga ko'rsatiladigan. Masalan, validatsiyaning xatoliklari.
Tarjimani yangilash uchun:
1. Konsolda `framework` direktoriyani ochamiz, `yii message/extract messages/config.php` ni ishga tushiramiz.
3. Habarlarni `framework/messages/uz/yii.php` ga ko`chiramiz. Muhimi fayllar UTF-8 kodlashda bo'lishi kerak.
4. `uz` dagi tarjimalar bilan [pull request qilamiz](https://github.com/yiisoft/yii2/blob/master/docs/internals/git-workflow.md), qolgan tillarga tegmaymiz.
Tarjima fayllarda massiv joylashgan. Uning kalitlari - boshlang'ich kodlar, qiymatlari - tarjima. Agar qiymat bo'sh bo'lsa habar tarjima qilinmagan hisoblanadi. Kodda boshqa uchramaydigan habarlar tarjimasi '@@' ga o'ralgan. Ayrim habarlar uchun [sonlar bilan qo'llanilishini qo'llab-quvvatlash uchun maxsus format](../guide/i18n.md) ni ishlatish zarur.
Qo'llanma
---------
Qo'llanamani tarjimasi `docs/<original>-uz` da joylashgan, bu yerda <original> - original direktoriyalarga mos keladi, masalan,
`guide` yoki `internals`.
Agar qo'llanma tarjimasi tugagan bo'lsa, build direktoriyasida konsolni ochib va quyidagini bajarib, originaldagi oxirgi tarjimadan keyingi diff o'zgarishlarni olish mumkin:
```
php build translation "../docs/guide" "../docs/guide-uz" "Uzbek guide translation report" > report_guide_uz.html
```
Agar composer uchun urushsa, bosh direktoriyada `composer install` ni bajaring.
Tarjima qilishdan oldin hech kim shug'ullanmayotganligini tekshiring va o'zingizga [barcha tarjima qilinayotgan hujjatlarni ro'yhatini] yozib oling
//Ushbu manzilni ulardan olgandan keyin o'zgartirib qo'yish kerak bo'ladi.
(https://docs.google.com/spreadsheets/d/10dS7VB_3jSxUorryRlplB7nhA59e3i2vLYmTwn_1d3I/edit?usp=sharing).
Barcha o'zgarishlarni quyidagi ko'rinishda olib boramiz [pull request](https://github.com/yiisoft/yii2/blob/master/docs/internals/git-workflow.md).
### Umumiy qoidalar
- Ko'p terminlar o'zbekchada bitta ma'noga ega emas va o'zbekchada ko'p qo'llanilmaydigandir, shu sababli agar matnda
shunday terminlar uchrasa ularni birinchi bor qo'llanilgan joyida qavs ichida ingliz tilidagi varianti
ko'rsatilishi kerak; (terminlarning tarjimasini qo'llanilish variantlari quyida keltirilgan);
- Agar tarjima vaqtida matnning qaysidir qismi mazmuni o'zgarayotgan bo'lsa va siz uni shunday tarjima qilish
kerakligiga ishonchingiz komil bo'lmayotganday tuyulsa ushbu qismni * ichiga oling(ichidagi matn qiya holatga keladi).
Bu olib tashlash/to'g'rilashlar vaqtida ushbu matnlarga alohida e'tibor qaratishga imkon beradi;
- Tarjima vaqtida fakt xatoliklarni qilmang!
- Matnda tashqi manbalarga murojaatlar uchraydi, agar murojaat terminni izohlash maqolasiga olib boradigan bo'lsa, u holda
o'zbekchada tarjimasi bo'r bo'lgan vaziyatda o'zbekchasiga murojaat qilinadi.
Masalan `http://en.wikipedia.org/wiki/Captcha` → `http://uz.wikipedia.org/wiki/Captcha`.
- Sharhlar kodda tarjima qilinadi, agarda birinchi holatdagi mazmunini o'zgartirmasa; Matndagi vaqtinchalik sharhlarni
imkon qadar faqat *lokal*da ishlatish kerak! Aks holda uni reliz ga tushib qolish ehtimoli bor;
- Bo'limlarni tarjima qilish vaqtida `README.md` dagi tarjimani olib ketamiz;
- Shaxsiy qo'shimcha-sharhlarni qo'shish imkoni bor, lekin xaosdan qochish uchun original bitta bo'lishi kerak. Bunga zarurat vaqtida sharh oxiriga
"tar. shar." ni qo'shish kerak;
- Hujjatni umumiy to'g'rilashni o'tkazgandan so'ng mustaqil ravishda faqat ushbu bo'limga tegsihli bo'lgan grammatikadagi, fakt xatoliklardagi o'zgarishlarni kiritish talab darajasida tavsiya etiladi. Boshqa holatlarda gaplarni to'g'rilash, yaxshilash uchun va zarur hollarda o'zgarishlarni markazlashgan tarzda barcha bo'limlar uchun amalga oshirish uchun ularni tahlilga qo'yish zarur.
### Qo'llanma strukturasi
Tarjima qilish vaqtida hujjatning struktura birligini to'g'ri nomlash muhim. Quyida keltirilgan strukturaga amal qilamiz :
- Bob 1
- Bo'lim 1
- Bo'lim 2
- Qism bo'lim 1
- ...
- Bo'lim N
- Bob 2
- ...
- Bob N
### Maxsus habarlarni tarjimasi
- Tip → Ko'rsatma
- Note → Eslatma
- Info → Ma'lumot
### Rasmlarni tarjima qilish
Qo'llanma uchun rasmlar `images` qism katalogida joylashgan. Ularning barchasi [yED](http://www.yworks.com/en/products_yed_about.html) da yaratilgan.
Zarurat tug'ilgan vaqtda fayl tarjima qilinayotgan katalogning `images` katalogiga nusxalanadi va tarjima qilinib png formatida saqlanadi.
Rasmlardagi yozuvlar tarjima qilinadi.
### Grammatika
Oxirgi variantni tashlashdan oldin uni umumiy stilini, orfografiyasini, punktlarini tekshiring. Tarjimani o'zbek tili uchun orfografiyani Wordda tekshirish imkoni bo'lmasada uning yordamida tayyorlashingiz mumkin;
### Terminlar ro'yhati
- action — amal.
- active record — tarjimasiz.
- attach handler — «qayta ishlovchini tayinlash».
- attribute of the model — model atributi.
- camel case — tarjimasiz.
- customization — (nozik) sozlash
- column — ustun (agar MO haqida gap ketayotgan bo'lsa).
- content — tashkil etuvchilari.
- controller — kontrollyor.
- debug (mode) — kod sozlash (tartibi) (production mode ga qarang).
- eager loading — ziqna yuklash uslubi/ziqna yuklash (lazy loading ga qarang).
- PHP extension — PHP kengaytmasi.
- field (of the table) — jadval (yoki atribut) maydoni.
- framework — freymvork.
- front-controller — front-kontrollyor.
- getter — getter.
- (event) handler — qayta ishlovchi (hodisa).
- hash — xesh.
- helper - yordamchi.
- id — qiymatlovchi(identifikatsiyalovchi).
- instance — nusxa.
- lazy loading — chetga olingan yuklash (qanday kerak bo'lsa shunday yuklasymiz va erta emas).
- method — metod (obektniki) //Diqqat! Obekt/klaslarda funksiyasi yo'q, faqat metodlari bor.
- model — model, ma`lumotlar modeli.
- model form — formalar modeli.
- parameter — parametr (metod yoki funksiyada va lekin klasda emas).
- to parse — qayta ishlash, agar *kontekst* tushunarsiz bo'lsa *parsing* qilish.
- placeholder — marker.
- production (mode) — ishlab chiqarish (rejimi) (см. debug mode).
- property — xususiyati (obekt).
- to render — *render* qilish, formallashtirish.
- related, relation — bog'langan, bog'lanish.
- resolve request — so'rovni oldindan qayta ishlash.
- route — marshrut.
- row (of the table) — satr(jadvallarniki).
- setter — setter.
- tabular input — tabli kiritish.
- to validate — tekshirish.
- valid — mos.
- validator — validator.
- validator class — validator klasi.
- view — namoyish.
- query builder — so'rovlar konstruktori.
\ No newline at end of file
......@@ -4,6 +4,8 @@ Yii Framework 2 bootstrap extension Change Log
2.0.0 under development
-----------------------
- Bug #5323: Nested dropdown does not work for `yii\bootstrap\DropDown` (aryraditya)
- Bug #5336: `yii\bootstrap\DropDown` should register bootstrap plugin asset (zelenin)
- Chg #5231: Collapse `items` property uses `label` element instead of array key for headers (nkovacs)
- Chg #5232: Collapse encodes headers by default (nkovacs)
- Chg #5217: Tabs no longer requires content since empty tab could be used dynamically (damiandennis)
......
......@@ -46,7 +46,6 @@ class Dropdown extends Widget
*/
protected $_containerOptions = [];
/**
* Initializes the widget.
* If you override this method, make sure you call the parent implementation first.
......@@ -64,6 +63,7 @@ class Dropdown extends Widget
public function run()
{
echo $this->renderItems($this->items);
BootstrapPluginAsset::register($this->getView());
}
/**
......@@ -95,7 +95,7 @@ class Dropdown extends Widget
$content = Html::a($label, ArrayHelper::getValue($item, 'url', '#'), $linkOptions);
if (!empty($item['items'])) {
unset($this->_containerOptions['id']);
$this->renderItems($item['items']);
$content .= $this->renderItems($item['items']);
Html::addCssClass($options, 'dropdown-submenu');
}
$lines[] = Html::tag('li', $content, $options);
......
......@@ -319,7 +319,7 @@ class Connection extends Component
$body = '';
$options = [
CURLOPT_USERAGENT => 'Yii Framework 2 ' . __CLASS__,
CURLOPT_USERAGENT => 'Yii Framework ' . Yii::getVersion() . __CLASS__,
CURLOPT_RETURNTRANSFER => false,
CURLOPT_HEADER => false,
// http://www.php.net/manual/en/function.curl-setopt.php#82418
......
......@@ -103,8 +103,9 @@ class Generator extends \yii\gii\Generator
'modelClass' => 'This is the ActiveRecord class associated with the table that CRUD will be built upon.
You should provide a fully qualified class name, e.g., <code>app\models\Post</code>.',
'controllerClass' => 'This is the name of the controller class to be generated. You should
provide a fully qualified namespaced class, .e.g, <code>app\controllers\PostController</code>.
The controller class name should follow the CamelCase scheme with an uppercase first letter',
provide a fully qualified namespaced class (e.g. <code>app\controllers\PostController</code>),
and class name should be in CamelCase with an uppercase first letter. Make sure the class
is using the same namespace as specified by your application\'s controllerNamespace property.',
'baseControllerClass' => 'This is the class that the new CRUD controller class will extend from.
You should provide a fully qualified class name, e.g., <code>yii\web\Controller</code>.',
'moduleID' => 'This is the ID of the module that the generated controller will belong to.
......
......@@ -30,7 +30,7 @@ echo Nav::widget([
'options' => ['class' => 'nav navbar-nav navbar-right'],
'items' => [
['label' => 'Home', 'url' => ['default/index']],
['label' => 'Help', 'url' => 'https://github.com/yiisoft/yii2/blob/master/docs/guide/gii.md'],
['label' => 'Help', 'url' => 'http://www.yiiframework.com/doc-2.0/guide-tool-gii.html'],
['label' => 'Application', 'url' => Yii::$app->homeUrl],
],
]);
......
......@@ -4,10 +4,16 @@ Yii Framework 2 Change Log
2.0.0 under development
-----------------------
- Bug #5252: Null values are not properly handled by `RangeValidator` (githubjeka, qiangxue)
- Bug #5260: `yii\i18n\Formatter::decimalSeparator` and `yii\i18n\Formatter::thousandSeparator` where not configurable when intl is not installed (execut, cebe)
- Bug #5314: Fixed typo in the implementation of `yii\web\Session::getHasSessionId()` (qiangxue)
- Bug #5323: Nested dropdown does not work for `yii\bootstrap\DropDown` (aryraditya)
- Bug #5336: `yii\bootstrap\DropDown` should register bootstrap plugin asset (zelenin)
- Bug: Date and time formatting now assumes UTC as the timezone for input dates unless a timezone is explicitly given (cebe)
- Enh #4040: Added `$viewFile` and `$params` to the `EVENT_BEFORE_RENDER` and `EVENT_AFTER_RENDER` events for `View` (qiangxue)
- Enh #4275: Added `removeChildren()` to `yii\rbac\ManagerInterface` and implementations (samdark)
- Enh: Added `yii\base\Application::loadedModules` (qiangxue)
- Chg #2037: Dropped the support for using `yii\base\Module` as concrete module classes (qiangxue)
2.0.0-rc September 27, 2014
......
......@@ -21,6 +21,9 @@ Upgrade from Yii 2.0 RC
* `yii\bootstrap\Collapse` is now encoding labels by default. `encode` item option and global `encodeLabels` property were
introduced to disable it. Keys are no longer used as labels. You need to remove keys and use `label` item option instead.
* The `yii\base\View::beforeRender()` and `yii\base\View::afterRender()` methods have two extra parameters `$viewFile`
and `$params`. If you are overriding these methods, you should adjust the method signature accordingly.
Upgrade from Yii 2.0 Beta
......@@ -193,12 +196,7 @@ new ones save the following code as `convert.php` that should be placed in the s
return [
'components' => [
'security' => [
'cryptBlockSize' => 16,
'cryptKeySize' => 24,
'derivationIterations' => 1000,
'deriveKeyStrategy' => 'hmac', // for PHP version < 5.5.0
//'deriveKeyStrategy' => 'pbkdf2', // for PHP version >= 5.5.0
'useDeriveKeyUniqueSalt' => false,
],
// ...
],
......
......@@ -350,9 +350,6 @@ class Module extends ServiceLocator
return $this->_modules[$id];
} elseif ($load) {
Yii::trace("Loading module: $id", __METHOD__);
if (is_array($this->_modules[$id]) && !isset($this->_modules[$id]['class'])) {
$this->_modules[$id]['class'] = 'yii\base\Module';
}
/* @var $module Module */
$module = Yii::createObject($this->_modules[$id], [$id, $this]);
$module->setInstance($module);
......
......@@ -233,7 +233,7 @@ class View extends Component
$output = '';
$this->_viewFiles[] = $viewFile;
if ($this->beforeRender()) {
if ($this->beforeRender($viewFile, $params)) {
Yii::trace("Rendering view file: $viewFile", __METHOD__);
$ext = pathinfo($viewFile, PATHINFO_EXTENSION);
if (isset($this->renderers[$ext])) {
......@@ -246,7 +246,7 @@ class View extends Component
} else {
$output = $this->renderPhpFile($viewFile, $params);
}
$this->afterRender($output);
$this->afterRender($viewFile, $params, $output);
}
array_pop($this->_viewFiles);
......@@ -267,11 +267,16 @@ class View extends Component
* This method is invoked right before [[renderFile()]] renders a view file.
* The default implementation will trigger the [[EVENT_BEFORE_RENDER]] event.
* If you override this method, make sure you call the parent implementation first.
* @param string $viewFile the view file to be rendered.
* @param array $params the parameter array passed to the [[render()]] method.
* @return boolean whether to continue rendering the view file.
*/
public function beforeRender()
public function beforeRender($viewFile, $params)
{
$event = new ViewEvent;
$event = new ViewEvent([
'viewFile' => $viewFile,
'params' => $params,
]);
$this->trigger(self::EVENT_BEFORE_RENDER, $event);
return $event->isValid;
......@@ -281,14 +286,19 @@ class View extends Component
* This method is invoked right after [[renderFile()]] renders a view file.
* The default implementation will trigger the [[EVENT_AFTER_RENDER]] event.
* If you override this method, make sure you call the parent implementation first.
* @param string $viewFile the view file being rendered.
* @param array $params the parameter array passed to the [[render()]] method.
* @param string $output the rendering result of the view file. Updates to this parameter
* will be passed back and returned by [[renderFile()]].
*/
public function afterRender(&$output)
public function afterRender($viewFile, $params, &$output)
{
if ($this->hasEventHandlers(self::EVENT_AFTER_RENDER)) {
$event = new ViewEvent;
$event->output = $output;
$event = new ViewEvent([
'viewFile' => $viewFile,
'params' => $params,
'output' => $output,
]);
$this->trigger(self::EVENT_AFTER_RENDER, $event);
$output = $event->output;
}
......
......@@ -16,6 +16,14 @@ namespace yii\base;
class ViewEvent extends Event
{
/**
* @var string the view file being rendered.
*/
public $viewFile;
/**
* @var array the parameter array passed to the [[View::render()]] method.
*/
public $params;
/**
* @var string the rendering result of [[View::renderFile()]].
* Event handlers may modify this property and the modified output will be
* returned by [[View::renderFile()]]. This property is only used
......
......@@ -160,7 +160,7 @@ class Application extends \yii\base\Application
try {
return (int)parent::runAction($route, $params);
} catch (InvalidRouteException $e) {
throw new Exception(Yii::t('yii', 'Unknown command "{command}".', ['command' => $route]), 0, $e);
throw new Exception("Unknown command \"$route\".", 0, $e);
}
}
......
......@@ -81,7 +81,7 @@ class Markdown extends \cebe\markdown\Parser
*/
protected function renderCode($block)
{
return Console::ansiFormat(implode("\n", $block['content']), [Console::BG_GREY]) . "\n";
return Console::ansiFormat(implode("\n", $block['content']), [Console::NEGATIVE]) . "\n";
}
/**
......
......@@ -51,9 +51,8 @@ class HelpController extends Controller
if ($command !== null) {
$result = Yii::$app->createController($command);
if ($result === false) {
throw new Exception(Yii::t('yii', 'No help for unknown command "{command}".', [
'command' => $this->ansiFormat($command, Console::FG_YELLOW),
]));
$name = $this->ansiFormat($command, Console::FG_YELLOW);
throw new Exception("No help for unknown command \"$name\".");
}
list($controller, $actionID) = $result;
......@@ -251,9 +250,8 @@ class HelpController extends Controller
{
$action = $controller->createAction($actionID);
if ($action === null) {
throw new Exception(Yii::t('yii', 'No help for unknown sub-command "{command}".', [
'command' => rtrim($controller->getUniqueId() . '/' . $actionID, '/'),
]));
$name = $this->ansiFormat(rtrim($controller->getUniqueId() . '/' . $actionID, '/'), Console::FG_YELLOW);
throw new Exception("No help for unknown sub-command \"$name\".");
}
$description = $controller->getActionHelp($action);
......
......@@ -116,6 +116,12 @@ interface QueryInterface
* `['in', 'id', [1, 2, 3]]` will generate `id IN (1, 2, 3)`.
* The method will properly quote the column name and escape values in the range.
*
* To create a composite `IN` condition you can use and array for the column name and value, where the values are indexed by the column name:
* `['in', ['id', 'name'], [['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']] ]`.
*
* You may also specify a sub-query that is used to get the values for the `IN`-condition:
* `['in', 'user_id', (new Query())->select('id')->from('users')->where(['active' => 1])]`
*
* - **not in**: similar to the `in` operator except that `IN` is replaced with `NOT IN` in the generated condition.
*
* - **like**: operand 1 should be a column or DB expression, and operand 2 be a string or an array representing
......@@ -137,6 +143,12 @@ interface QueryInterface
* - **or not like**: similar to the `not like` operator except that `OR` is used to concatenate
* the `NOT LIKE` predicates.
*
* - **exists**: operand 1 is a query object that used to build an `EXISTS` condition. For example
* `['exists', (new Query())->select('id')->from('users')->where(['active' => 1])]` will result in the following SQL expression:
* `EXISTS (SELECT "id" FROM "users" WHERE "active"=1)`.
*
* - **not exists**: similar to the `exists` operator except that `EXISTS` is replaced with `NOT EXISTS` in the generated condition.
*
* - Additionally you can specify arbitrary operators as follows: A condition of `['>=', 'id', 10]` will result in the
* following SQL expression: `id >= 10`.
*
......
......@@ -39,15 +39,17 @@ use yii\web\Response;
* return [
* 'corsFilter' => [
* 'class' => \yii\filters\Cors::className(),
* // restrict access to
* 'Origin' => ['http://www.myserver.com', 'https://www.myserver.com'],
* 'Access-Control-Request-Method' => ['POST', 'PUT'],
* // Allow only POST and PUT methods
* 'Access-Control-Request-Headers' => ['X-Wsse'],
* // Allow only headers 'X-Wsse'
* 'Access-Control-Allow-Credentials' => true,
* // Allow OPTIONS caching
* 'Access-Control-Max-Age' => 3600,
* 'cors' => [
* // restrict access to
* 'Origin' => ['http://www.myserver.com', 'https://www.myserver.com'],
* 'Access-Control-Request-Method' => ['POST', 'PUT'],
* // Allow only POST and PUT methods
* 'Access-Control-Request-Headers' => ['X-Wsse'],
* // Allow only headers 'X-Wsse'
* 'Access-Control-Allow-Credentials' => true,
* // Allow OPTIONS caching
* 'Access-Control-Max-Age' => 3600,
* ],
*
* ],
* ];
......
......@@ -727,6 +727,7 @@ class Formatter extends Component
$value = $this->normalizeNumericValue($value);
if ($this->_intlLoaded) {
$f = $this->createNumberFormatter(NumberFormatter::DECIMAL, null, $options, $textOptions);
$f->setAttribute(NumberFormatter::FRACTION_DIGITS, 0);
return $f->format($value, NumberFormatter::TYPE_INT64);
} else {
return number_format((int) $value, 0, $this->decimalSeparator, $this->thousandSeparator);
......
......@@ -66,7 +66,7 @@ class RangeValidator extends Validator
$in = true;
foreach ((array)$value as $v) {
foreach ((is_array($value) ? $value : [$value]) as $v) {
if (!in_array($v, $this->range, $this->strict)) {
$in = false;
break;
......
......@@ -206,7 +206,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
$request = Yii::$app->getRequest();
if (ini_get('session.use_cookies') && !empty($_COOKIE[$name])) {
$this->_hasSessionId = true;
} elseif (!ini_get('use_only_cookies') && ini_get('use_trans_sid')) {
} elseif (!ini_get('session.use_only_cookies') && ini_get('session.use_trans_sid')) {
$this->_hasSessionId = $request->get($name) !== null;
} else {
$this->_hasSessionId = false;
......
......@@ -171,8 +171,19 @@ class QueryBuilderTest extends DatabaseTestCase
// in
[ ['in', 'id', [1, 2, 3]], '"id" IN (:qp0, :qp1, :qp2)', [':qp0' => 1, ':qp1' => 2, ':qp2' => 3] ],
[ ['not in', 'id', [1, 2, 3]], '"id" NOT IN (:qp0, :qp1, :qp2)', [':qp0' => 1, ':qp1' => 2, ':qp2' => 3] ],
[ ['in', 'id', (new Query())->select('id')->from('users')->where(['active' => 1])], '("id") IN (SELECT "id" FROM "users" WHERE "active"=:qp0)', [':qp0' => 1] ],
[ ['not in', 'id', (new Query())->select('id')->from('users')->where(['active' => 1])], '("id") NOT IN (SELECT "id" FROM "users" WHERE "active"=:qp0)', [':qp0' => 1] ],
// TODO: exists and not exists
// composite in
[ ['in', ['id', 'name'], [['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']]], '("id", "name") IN ((:qp0, :qp1), (:qp2, :qp3))', [':qp0' => 1, ':qp1' => 'foo', ':qp2' => 2, ':qp3' => 'bar'] ],
[ ['not in', ['id', 'name'], [['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']]], '("id", "name") NOT IN ((:qp0, :qp1), (:qp2, :qp3))', [':qp0' => 1, ':qp1' => 'foo', ':qp2' => 2, ':qp3' => 'bar'] ],
[ ['in', ['id', 'name'], (new Query())->select(['id', 'name'])->from('users')->where(['active' => 1])], '("id", "name") IN (SELECT "id", "name" FROM "users" WHERE "active"=:qp0)', [':qp0' => 1] ],
[ ['not in', ['id', 'name'], (new Query())->select(['id', 'name'])->from('users')->where(['active' => 1])], '("id", "name") NOT IN (SELECT "id", "name" FROM "users" WHERE "active"=:qp0)', [':qp0' => 1] ],
// exists
[ ['exists', (new Query())->select('id')->from('users')->where(['active' => 1])], 'EXISTS (SELECT "id" FROM "users" WHERE "active"=:qp0)', [':qp0' => 1] ],
[ ['not exists', (new Query())->select('id')->from('users')->where(['active' => 1])], 'NOT EXISTS (SELECT "id" FROM "users" WHERE "active"=:qp0)', [':qp0' => 1] ],
// simple conditions
[ ['=', 'a', 'b'], '"a" = :qp0', [':qp0' => 'b'] ],
......@@ -229,8 +240,6 @@ class QueryBuilderTest extends DatabaseTestCase
[ ['in', 'id', []], '', [] ],
[ ['not in', 'id', []], '', [] ],
// TODO: exists and not exists
// simple conditions
[ ['=', 'a', ''], '', [] ],
[ ['>', 'a', ''], '', [] ],
......@@ -262,8 +271,8 @@ class QueryBuilderTest extends DatabaseTestCase
{
$query = (new Query())->where($condition);
list($sql, $params) = $this->getQueryBuilder()->build($query);
$this->assertEquals($expectedParams, $params);
$this->assertEquals('SELECT *' . (empty($expected) ? '' : ' WHERE ' . $expected), $sql);
$this->assertEquals($expectedParams, $params);
}
/**
......@@ -273,8 +282,8 @@ class QueryBuilderTest extends DatabaseTestCase
{
$query = (new Query())->filterWhere($condition);
list($sql, $params) = $this->getQueryBuilder()->build($query);
$this->assertEquals($expectedParams, $params);
$this->assertEquals('SELECT *' . (empty($expected) ? '' : ' WHERE ' . $expected), $sql);
$this->assertEquals($expectedParams, $params);
}
public function testAddDropPrimaryKey()
......@@ -295,30 +304,28 @@ class QueryBuilderTest extends DatabaseTestCase
$this->assertEquals(0, count($tableSchema->primaryKey));
}
/* qiangxue: the following tests are commented because they vary by different DB drivers. need a better test scheme.
public function testBuildWhereExists()
public function existsParamsProvider()
{
$expectedQuerySql = "SELECT `id` FROM `TotalExample` `t` WHERE EXISTS (SELECT `1` FROM `Website` `w`)";
$expectedQueryParams = null;
$subQuery = new Query();
$subQuery->select('1')
->from('Website w');
$query = new Query();
$query->select('id')
->from('TotalExample t')
->where(['exists', $subQuery]);
$conditions = [
['exists', "SELECT `id` FROM `TotalExample` `t` WHERE EXISTS (SELECT `1` FROM `Website` `w`)"],
['not exists', "SELECT `id` FROM `TotalExample` `t` WHERE NOT EXISTS (SELECT `1` FROM `Website` `w`)"]
];
list($actualQuerySql, $actualQueryParams) = $this->getQueryBuilder()->build($query);
$this->assertEquals($expectedQuerySql, $actualQuerySql);
$this->assertEquals($expectedQueryParams, $actualQueryParams);
// adjust dbms specific escaping
foreach($conditions as $i => $condition) {
if (!in_array($this->driverName, ['mssql', 'mysql', 'sqlite'])) {
$conditions[$i][1] = str_replace('`', '"', $condition[1]);
}
}
return $conditions;
}
public function testBuildWhereNotExists()
/**
* @dataProvider existsParamsProvider
*/
public function testBuildWhereExists($cond, $expectedQuerySql)
{
$expectedQuerySql = "SELECT `id` FROM `TotalExample` `t` WHERE NOT EXISTS (SELECT `1` FROM `Website` `w`)";
$expectedQueryParams = null;
$expectedQueryParams = [];
$subQuery = new Query();
$subQuery->select('1')
......@@ -327,16 +334,20 @@ class QueryBuilderTest extends DatabaseTestCase
$query = new Query();
$query->select('id')
->from('TotalExample t')
->where(['not exists', $subQuery]);
->where([$cond, $subQuery]);
list($actualQuerySql, $actualQueryParams) = $this->getQueryBuilder()->build($query);
$this->assertEquals($expectedQuerySql, $actualQuerySql);
$this->assertEquals($expectedQueryParams, $actualQueryParams);
}
public function testBuildWhereExistsWithParameters()
{
$expectedQuerySql = "SELECT `id` FROM `TotalExample` `t` WHERE (EXISTS (SELECT `1` FROM `Website` `w` WHERE (w.id = t.website_id) AND (w.merchant_id = :merchant_id))) AND (t.some_column = :some_value)";
if (!in_array($this->driverName, ['mssql', 'mysql', 'sqlite'])) {
$expectedQuerySql = str_replace('`', '"', $expectedQuerySql);
}
$expectedQueryParams = [':some_value' => "asd", ':merchant_id' => 6];
$subQuery = new Query();
......@@ -359,6 +370,9 @@ class QueryBuilderTest extends DatabaseTestCase
public function testBuildWhereExistsWithArrayParameters()
{
$expectedQuerySql = "SELECT `id` FROM `TotalExample` `t` WHERE (EXISTS (SELECT `1` FROM `Website` `w` WHERE (w.id = t.website_id) AND ((`w`.`merchant_id`=:qp0) AND (`w`.`user_id`=:qp1)))) AND (`t`.`some_column`=:qp2)";
if (!in_array($this->driverName, ['mssql', 'mysql', 'sqlite'])) {
$expectedQuerySql = str_replace('`', '"', $expectedQuerySql);
}
$expectedQueryParams = [':qp0' => 6, ':qp1' => 210, ':qp2' => 'asd'];
$subQuery = new Query();
......@@ -377,30 +391,32 @@ class QueryBuilderTest extends DatabaseTestCase
$this->assertEquals($expectedQuerySql, $actualQuerySql);
$this->assertEquals($expectedQueryParams, $queryParams);
}
*/
/*
This test contains three select queries connected with UNION and UNION ALL constructions.
It could be useful to use "phpunit --group=db --filter testBuildUnion" command for run it.
public function testBuildUnion()
{
$expectedQuerySql = "SELECT `id` FROM `TotalExample` `t1` WHERE (w > 0) AND (x < 2) UNION ( SELECT `id` FROM `TotalTotalExample` `t2` WHERE w > 5 ) UNION ALL ( SELECT `id` FROM `TotalTotalExample` `t3` WHERE w = 3 )";
$query = new Query();
$secondQuery = new Query();
$secondQuery->select('id')
->from('TotalTotalExample t2')
->where('w > 5');
$thirdQuery = new Query();
$thirdQuery->select('id')
->from('TotalTotalExample t3')
->where('w = 3');
$query->select('id')
->from('TotalExample t1')
->where(['and', 'w > 0', 'x < 2'])
->union($secondQuery)
->union($thirdQuery, TRUE);
list($actualQuerySql, $queryParams) = $this->getQueryBuilder()->build($query);
$this->assertEquals($expectedQuerySql, $actualQuerySql);
}*/
/**
* This test contains three select queries connected with UNION and UNION ALL constructions.
* It could be useful to use "phpunit --group=db --filter testBuildUnion" command for run it.
*/
public function testBuildUnion()
{
$expectedQuerySql = "(SELECT `id` FROM `TotalExample` `t1` WHERE (w > 0) AND (x < 2)) UNION ( SELECT `id` FROM `TotalTotalExample` `t2` WHERE w > 5 ) UNION ALL ( SELECT `id` FROM `TotalTotalExample` `t3` WHERE w = 3 )";
if (!in_array($this->driverName, ['mssql', 'mysql', 'sqlite'])) {
$expectedQuerySql = str_replace('`', '"', $expectedQuerySql);
}
$query = new Query();
$secondQuery = new Query();
$secondQuery->select('id')
->from('TotalTotalExample t2')
->where('w > 5');
$thirdQuery = new Query();
$thirdQuery->select('id')
->from('TotalTotalExample t3')
->where('w = 3');
$query->select('id')
->from('TotalExample t1')
->where(['and', 'w > 0', 'x < 2'])
->union($secondQuery)
->union($thirdQuery, TRUE);
list($actualQuerySql, $queryParams) = $this->getQueryBuilder()->build($query);
$this->assertEquals($expectedQuerySql, $actualQuerySql);
}
}
......@@ -2,7 +2,9 @@
namespace yiiunit\framework\i18n;
use NumberFormatter;
use yii\i18n\Formatter;
use Yii;
use yiiunit\TestCase;
use DateTime;
use DateInterval;
......@@ -575,9 +577,49 @@ class FormatterTest extends TestCase
// number format
/**
* Provides some configuration that should not affect Integer formatter
*/
public function differentConfigProvider()
{
// make this test not break when intl is not installed
if (!extension_loaded('intl')) {
return [];
}
public function testIntlAsInteger()
return [
[[
'numberFormatterOptions' => [
NumberFormatter::MIN_FRACTION_DIGITS => 2,
],
]],
[[
'numberFormatterOptions' => [
NumberFormatter::MAX_FRACTION_DIGITS => 2,
],
]],
[[
'numberFormatterOptions' => [
NumberFormatter::FRACTION_DIGITS => 2,
],
]],
[[
'numberFormatterOptions' => [
NumberFormatter::MIN_FRACTION_DIGITS => 2,
NumberFormatter::MAX_FRACTION_DIGITS => 4,
],
]],
];
}
/**
* @dataProvider differentConfigProvider
*/
public function testIntlAsInteger($config)
{
// configure formatter with different configs that should not affect integer format
Yii::configure($this->formatter, $config);
$this->testAsInteger();
}
......
......@@ -41,6 +41,17 @@ class RangeValidatorTest extends TestCase
$this->assertTrue($val->validate("5"));
}
public function testValidateValueEmpty()
{
$val = new RangeValidator(['range' => range(10, 20, 1), 'skipOnEmpty' => false]);
$this->assertFalse($val->validate(null)); //row RangeValidatorTest.php:101
$this->assertFalse($val->validate('0'));
$this->assertFalse($val->validate(0));
$this->assertFalse($val->validate(''));
$val->allowArray = true;
$this->assertTrue($val->validate([]));
}
public function testValidateArrayValue()
{
$val = new RangeValidator(['range' => range(1, 10, 1)]);
......
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