diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 00000000000..4c7c815c48c --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,46 @@ +build: false +version: dev-{build} +shallow_clone: true +clone_folder: C:\projects\yii2 + +environment: + matrix: + - php_ver: 7.2.4 + +matrix: + allow_failures: + - php_ver: 7.2.4 + +cache: + - '%APPDATA%\Composer' + - '%LOCALAPPDATA%\Composer' + - C:\tools\php -> .appveyor.yml + - C:\tools\composer.phar -> .appveyor.yml + +init: + - SET PATH=C:\tools\php;%PATH% + +install: + - ps: Set-Service wuauserv -StartupType Manual + - IF NOT EXIST C:\tools\php (choco install --yes --allow-empty-checksums php --version %php_ver% --params '/InstallDir:C:\tools\php') + - cd C:\tools\php + - copy php.ini-production php.ini + - echo date.timezone="UTC" >> php.ini + - echo memory_limit=512M >> php.ini + - echo extension_dir=ext >> php.ini + - echo extension=php_curl.dll >> php.ini + - echo extension=php_fileinfo.dll >> php.ini + - echo extension=php_gd2.dll >> php.ini + - echo extension=php_intl.dll >> php.ini + - echo extension=php_mbstring.dll >> php.ini + - echo extension=php_openssl.dll >> php.ini + - echo extension=php_pdo_sqlite.dll >> php.ini + - IF NOT EXIST C:\tools\composer.phar (cd C:\tools && appveyor DownloadFile https://getcomposer.org/download/1.4.1/composer.phar) + +before_test: + - cd C:\projects\yii2 + - php C:\tools\composer.phar update --no-interaction --no-progress --prefer-stable --no-ansi + +test_script: + - cd C:\projects\yii2 + - vendor\bin\phpunit --exclude-group mssql,mysql,pgsql,sqlite,db,oci,wincache,xcache,zenddata,cubrid diff --git a/.gitattributes b/.gitattributes index 4fee40f1f8d..08f809af71e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -24,6 +24,7 @@ # Ignore some meta files when creating an archive of this repository # We do not ignore any content, because this repo represents the # `yiisoft/yii2-dev` package, which is expected to ship all tests and docs. +/.appveyor.yml export-ignore /.github export-ignore /.editorconfig export-ignore /.gitattributes export-ignore diff --git a/.github/move.yml b/.github/move.yml new file mode 100644 index 00000000000..1589712a732 --- /dev/null +++ b/.github/move.yml @@ -0,0 +1,24 @@ +# Configuration for move-issues - https://github.com/dessant/move-issues + +# Delete the command comment when it contains no other content +deleteCommand: true + +# Close the source issue after moving +closeSourceIssue: true + +# Lock the source issue after moving +lockSourceIssue: false + +# Mention issue and comment authors +mentionAuthors: true + +# Preserve mentions in the issue content +keepContentMentions: false + +# Set custom aliases for targets +# aliases: +# r: repo +# or: owner/repo + +# Repository to extend settings from +# _extends: repo diff --git a/.gitignore b/.gitignore index 77c9164bcc4..f941e247228 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,9 @@ nbproject *.sublime-project *.sublime-workspace +# visual studio code project files +.vscode + # windows thumbnail cache Thumbs.db diff --git a/.travis.yml b/.travis.yml index f5f27c03ca3..4233dc4dbae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,7 @@ env: - TASK_TESTS_PHP=1 - TASK_TESTS_JS=0 - TASK_TESTS_COVERAGE=0 + - TRAVIS_SECOND_USER=travis_two services: @@ -60,6 +61,8 @@ addons: matrix: fast_finish: true include: + - php: 7.3 + - php: 7.2 # run tests coverage on PHP 7.1 @@ -90,8 +93,9 @@ matrix: - mysql - postgresql - # test against the latest HHVM version by using a newer image - - php: hhvm + # test against the latest pre 3.26 HHVM version by using a newer image. + # @see https://github.com/facebook/hhvm/issues/8192 + - php: hhvm-3.24 sudo: true addons: code_climate: @@ -120,6 +124,8 @@ matrix: allow_failures: - php: nightly + - php: hhvm-3.21 + - php: hhvm-3.24 install: - | @@ -147,6 +153,9 @@ install: travis_retry npm install fi + # Needed for FileCacheTest + - sudo useradd $TRAVIS_SECOND_USER --gid $(id -g) -M + before_script: # # Disable: @@ -170,6 +179,7 @@ before_script: php -r "echo INTL_ICU_DATA_VERSION . \"\n\";" psql --version mysql --version + sudo mysql_upgrade fi - | if [ $TASK_TESTS_JS == 1 ]; then @@ -196,7 +206,7 @@ before_script: # Disable DEPRECATE messages during PHPUnit initialization on PHP 7.2. To fix them, PHPUnit should be updated to 6.* # For Yii2 tests, messages will be enabled by tests/bootstrap.php - | - if [[ $TRAVIS_PHP_VERSION == 7.2 || $TRAVIS_PHP_VERSION = nightly ]]; then + if [[ $TRAVIS_PHP_VERSION == 7.2 || $TRAVIS_PHP_VERSION == 7.3 || $TRAVIS_PHP_VERSION = nightly ]]; then echo 'Disabled DEPRECATED notifications for PHP >= 7.2'; echo 'error_reporting = E_ALL & ~E_DEPRECATED' >> /tmp/php-config.ini; phpenv config-add /tmp/php-config.ini; diff --git a/LICENSE.md b/LICENSE.md index e98f03df869..ee872b9abf3 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,3 @@ -The Yii framework is free software. It is released under the terms of -the following BSD License. - Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com) All rights reserved. diff --git a/README.md b/README.md index 67996eb303e..d4844b98a2b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- + Yii Framework

@@ -11,34 +11,11 @@ The framework is easy to adjust to meet your needs, because Yii has been designe [![Latest Stable Version](https://img.shields.io/packagist/v/yiisoft/yii2.svg)](https://packagist.org/packages/yiisoft/yii2) [![Total Downloads](https://img.shields.io/packagist/dt/yiisoft/yii2.svg)](https://packagist.org/packages/yiisoft/yii2) -[![Build Status](https://img.shields.io/travis/yiisoft/yii2.svg)](http://travis-ci.org/yiisoft/yii2) +[![Build Status](https://img.shields.io/travis/yiisoft/yii2.svg)](https://travis-ci.org/yiisoft/yii2) [![Code Coverage](https://scrutinizer-ci.com/g/yiisoft/yii2/badges/coverage.png?s=31d80f1036099e9d6a3e4d7738f6b000b3c3d10e)](https://scrutinizer-ci.com/g/yiisoft/yii2/) [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/yiisoft/yii2/badges/quality-score.png?s=b1074a1ff6d0b214d54fa5ab7abbb90fc092471d)](https://scrutinizer-ci.com/g/yiisoft/yii2/) [![Code Climate](https://img.shields.io/codeclimate/github/yiisoft/yii2.svg)](https://codeclimate.com/github/yiisoft/yii2) -分支说明 -------- -* master:主分支 -* doc:文档翻译分支 -* api:api 翻译分支 - -## 官方新版本发布 -doc branch: -``` -git merge upstream/master -``` -api branch: -``` -git merge upstream/master -``` -master branch: -``` -git merge doc -git merge api -``` -> 注意:禁止提交 pull request 至 master 分支,文档修改请提交至 doc 分支,api 修改请提交至 api 分支。 - - Installation ------------ @@ -76,7 +53,7 @@ You may join us and: - [Report an issue](docs/internals/report-an-issue.md) - [Translate documentation or messages](docs/internals/translation-workflow.md) -- [Give us feedback or start a design discussion](http://www.yiiframework.com/forum/index.php/forum/42-general-discussions-for-yii-20/) +- [Give us feedback or start a design discussion](https://www.yiiframework.com/forum/index.php/forum/42-general-discussions-for-yii-20/) - [Contribute to the core code or fix bugs](docs/internals/git-workflow.md) ### Reporting Security issues @@ -112,5 +89,5 @@ If you are using Yii 2 as part of an OpenSource project, a way to acknowledge it If your code is hosted at GitHub, you can place the following in your README.md file to get the badge: ``` -[![Yii2](https://img.shields.io/badge/Powered_by-Yii_Framework-green.svg?style=flat)](http://www.yiiframework.com/) +[![Yii2](https://img.shields.io/badge/Powered_by-Yii_Framework-green.svg?style=flat)](https://www.yiiframework.com/) ``` diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 00000000000..59ea9ba77e6 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,32 @@ +Framework development for versions 3.0 and further moved to [Yii Framework Core repository](https://github.com/yiisoft/yii-core). + +Please see ROADMAP there: +https://github.com/yiisoft/yii-core/blob/master/ROADMAP.md + +There are no planned changes for Yii 2.0 cause while it is supported it is not developed anymore. +Bug and security fixes are expected. New features and enhancements are not accepted. +Pull requests and maintainers are very welcome. + +## Additional releases + +We can tag additional releases in case someone will take the role of release manager. Otherwise we'll focus on 3.0. + +## 2.0.17 (2nd quarter of 2019) + +- Bugfixes. +- Announce bugfixes EOL (a year more?). +- Security fixes only. + +## 2.0.16 (1st quarter of 2019) + +- Bugfixes. + +## 2.0.15 (2nd quarter of 2018) + +- Since this release main focus is bug fixing. +- No full-branch merges into 3.0. +- No enhancements are accepted. + +## 2.0.14 (1st quarter of 2018) + +Will be last release with features and enhancements the last one that will be merged into 3.0 directly. diff --git a/build/controllers/ReleaseController.php b/build/controllers/ReleaseController.php index 95f6f1f8601..75b1b6c9bb8 100644 --- a/build/controllers/ReleaseController.php +++ b/build/controllers/ReleaseController.php @@ -822,7 +822,7 @@ protected function closeChangelogs($what, $version) $v = str_replace('\\-', '[\\- ]', preg_quote($version, '/')); $headline = $version . ' ' . date('F d, Y'); $this->sed( - '/' . $v . ' under development\n(-+?)\n/', + '/' . $v . ' under development\R(-+?)\R/', $headline . "\n" . str_repeat('-', \strlen($headline)) . "\n", $this->getChangelogs($what) ); @@ -987,7 +987,7 @@ protected function composerSetStability($what, $version) protected function updateYiiVersion($frameworkPath, $version) { $this->sed( - '/function getVersion\(\)\n \{\n return \'(.+?)\';/', + '/function getVersion\(\)\R \{\R return \'(.+?)\';/', "function getVersion()\n {\n return '$version';", $frameworkPath . '/BaseYii.php'); } diff --git a/composer.json b/composer.json index 5b0ca429c6b..83de8783887 100644 --- a/composer.json +++ b/composer.json @@ -75,7 +75,7 @@ "yiisoft/yii2-composer": "~2.0.4", "ezyang/htmlpurifier": "~4.6", "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0", - "bower-asset/jquery": "3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", + "bower-asset/jquery": "3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", "bower-asset/inputmask": "~3.2.2 | ~3.3.5", "bower-asset/punycode": "1.3.*", "bower-asset/yii2-pjax": "~2.0.1" @@ -83,7 +83,8 @@ "require-dev": { "phpunit/phpunit": "4.8.34", "cebe/indent": "~1.0.2", - "friendsofphp/php-cs-fixer": "~2.2.3" + "friendsofphp/php-cs-fixer": "~2.2.3", + "johnkary/phpunit-speedtrap": "^1.0" }, "repositories": [ { diff --git a/composer.lock b/composer.lock index ccd7209dfa1..631f0e86a05 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c5363e83fd40667959bed938186dbdf2", + "content-hash": "20618e7e02e835f9f1ee41b339f2b61a", "packages": [ { "name": "bower-asset/inputmask", @@ -52,35 +52,23 @@ "version": "v1.3.2", "source": { "type": "git", - "url": "https://github.com/bestiejs/punycode.js.git", + "url": "git@github.com:bestiejs/punycode.js.git", "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/bestiejs/punycode.js/zipball/38c8d3131a82567bfef18da09f7f4db68c84f8a3", "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3", - "shasum": "" + "shasum": null }, - "type": "bower-asset-library", - "extra": { - "bower-asset-main": "punycode.js", - "bower-asset-ignore": [ - "coverage", - "tests", - ".*", - "component.json", - "Gruntfile.js", - "node_modules", - "package.json" - ] - } + "type": "bower-asset" }, { "name": "bower-asset/yii2-pjax", "version": "2.0.7.1", "source": { "type": "git", - "url": "https://github.com/yiisoft/jquery-pjax.git", + "url": "git@github.com:yiisoft/jquery-pjax.git", "reference": "aef7b953107264f00234902a3880eb50dafc48be" }, "dist": { @@ -698,6 +686,56 @@ ], "time": "2014-11-20T16:49:30+00:00" }, + { + "name": "johnkary/phpunit-speedtrap", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/johnkary/phpunit-speedtrap.git", + "reference": "76a26f8a903a9434608cdad2b41c40cd134ea326" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/johnkary/phpunit-speedtrap/zipball/76a26f8a903a9434608cdad2b41c40cd134ea326", + "reference": "76a26f8a903a9434608cdad2b41c40cd134ea326", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "JohnKary": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Kary", + "email": "john@johnkary.net" + } + ], + "description": "Find slow tests in your PHPUnit test suite", + "homepage": "https://github.com/johnkary/phpunit-speedtrap", + "keywords": [ + "phpunit", + "profile", + "slow" + ], + "time": "2015-09-13T19:01:00+00:00" + }, { "name": "paragonie/random_compat", "version": "v2.0.11", diff --git a/contrib/completion/bash/yii b/contrib/completion/bash/yii index c73d42f5de2..c5e78849e45 100644 --- a/contrib/completion/bash/yii +++ b/contrib/completion/bash/yii @@ -57,4 +57,4 @@ _yii() # register completion for the ./yii command # you may adjust this line if your command file is named differently -complete -F _yii ./yii yii +complete -o default -F _yii ./yii yii diff --git a/docs/guide-ar/README.md b/docs/guide-ar/README.md new file mode 100644 index 00000000000..11b9e4272cf --- /dev/null +++ b/docs/guide-ar/README.md @@ -0,0 +1,205 @@ + Yii 2.0 الدليل التقني الخاص ببيئة العمل +=============================== + +تم تحرير هذا الملف اعتمادا على [الشروط الخاصة بتوثيف ال Yii](http://www.yiiframework.com/doc/terms/). + +جميع الحقوق محفوظة + +2014 (c) Yii Software LLC. + + +المقدمة +------------ + +* [عن بيئة العمل Yii](intro-yii.md) +* [التحديث من الإصدار 1.1](../guide/intro-upgrade-from-v1.md) + + +البداية من هنا +--------------- + +* [ماذا يجب أن تعرف عن بيئة العمل](start-prerequisites.md) +* [تثبيت ال Yii](start-installation.md) +* [تشغيل التطبيقات - Running Applications](start-workflow.md) +* [قل مرحبا - المشروع الأول](start-hello.md) +* [التعامل مع ال forms](start-forms.md) +* [التعامل مع قواعد البيانات](start-databases.md) +* [إنشاء الشيفرة البرمجية من خلال ال gii](start-gii.md) +* [ماذا الآن - الخطوة القادمة](start-looking-ahead.md) + + +الهيكلية الخاصة بالتطبيق (Application Structure) +--------------------- + +* [نظرة عامة عن الهيكلية الخاصة بالتطبيق](../guide/structure-overview.md) +* [Entry Scripts](../guide/structure-entry-scripts.md) +* [التطبيقات](../guide/structure-applications.md) +* [مكونات التطبيقات](../guide/structure-application-components.md) +* [Controllers](../guide/structure-controllers.md) +* [Models](../guide/structure-models.md) +* [Views](../guide/structure-views.md) +* [Modules](../guide/structure-modules.md) +* [Filters](../guide/structure-filters.md) +* [Widgets](../guide/structure-widgets.md) +* [Assets](../guide/structure-assets.md) +* [Extensions](../guide/structure-extensions.md) + + +التعامل مع ال requests +----------------- + +* [نظرة عامة عن التعامل مع ال requests](../guide/runtime-overview.md) +* [Bootstrapping](../guide/runtime-bootstrapping.md) +* [Routing and URL Creation](../guide/runtime-routing.md) +* [Requests](../guide/runtime-requests.md) +* [Responses](../guide/runtime-responses.md) +* [Sessions and Cookies](../guide/runtime-sessions-cookies.md) +* [Handling Errors - التحكم بالأخطاء](../guide/runtime-handling-errors.md) +* [Logging - تسجيل الحركات](../guide/runtime-logging.md) + + +المفاهيم الرئيسية (Key Concepts) +------------ + +* [Components](../guide/concept-components.md) +* [Properties](../guide/concept-properties.md) +* [Events](../guide/concept-events.md) +* [Behaviors](../guide/concept-behaviors.md) +* [Configurations](../guide/concept-configurations.md) +* [Aliases](../guide/concept-aliases.md) +* [Class Autoloading](../guide/concept-autoloading.md) +* [Service Locator](../guide/concept-service-locator.md) +* [Dependency Injection Container](../guide/concept-di-container.md) + + +التعامل مع قواعد البيانات +---------------------- + +* [Database Access Objects](../guide/db-dao.md): Connecting to a database, basic queries, transactions, and schema manipulation +* [Query Builder](../guide/db-query-builder.md): Querying the database using a simple abstraction layer +* [Active Record](../guide/db-active-record.md): The Active Record ORM, retrieving and manipulating records, and defining relations +* [Migrations](../guide/db-migrations.md): Apply version control to your databases in a team development environment +* [Sphinx](https://www.yiiframework.com/extension/yiisoft/yii2-sphinx/doc/guide) +* [Redis](https://www.yiiframework.com/extension/yiisoft/yii2-redis/doc/guide) +* [MongoDB](https://www.yiiframework.com/extension/yiisoft/yii2-mongodb/doc/guide) +* [ElasticSearch](https://www.yiiframework.com/extension/yiisoft/yii2-elasticsearch/doc/guide) + + +الحصول على البيانات من خلال المستخدمين +----------------------- + +* [Creating Forms](../guide/input-forms.md) +* [Validating Input](../guide/input-validation.md) +* [Uploading Files](../guide/input-file-upload.md) +* [Collecting Tabular Input](../guide/input-tabular-input.md) +* [Getting Data for Multiple Models](../guide/input-multiple-models.md) +* [Extending ActiveForm on the Client Side](../guide/input-form-javascript.md) + + +عرض البيانات +--------------- + +* [Data Formatting](../guide/output-formatting.md) +* [Pagination](../guide/output-pagination.md) +* [Sorting](../guide/output-sorting.md) +* [Data Providers](../guide/output-data-providers.md) +* [Data Widgets](../guide/output-data-widgets.md) +* [Working with Client Scripts](../guide/output-client-scripts.md) +* [Theming](../guide/output-theming.md) + + +الامان والحماية +-------- + +* [Security Overview](../guide/security-overview.md) +* [Authentication](../guide/security-authentication.md) +* [Authorization](../guide/security-authorization.md) +* [Working with Passwords](../guide/security-passwords.md) +* [Cryptography](../guide/security-cryptography.md) +* [Auth Clients](https://www.yiiframework.com/extension/yiisoft/yii2-authclient/doc/guide) +* [Best Practices](../guide/security-best-practices.md) + + +Caching التخزين المؤقت +------- + +* [Caching Overview](../guide/caching-overview.md) +* [Data Caching](../guide/caching-data.md) +* [Fragment Caching](../guide/caching-fragment.md) +* [Page Caching](../guide/caching-page.md) +* [HTTP Caching](../guide/caching-http.md) + + +RESTful Web Services +-------------------- + +* [Quick Start](../guide/rest-quick-start.md) +* [Resources](../guide/rest-resources.md) +* [Controllers](../guide/rest-controllers.md) +* [Routing](../guide/rest-routing.md) +* [Response Formatting](../guide/rest-response-formatting.md) +* [Authentication](../guide/rest-authentication.md) +* [Rate Limiting](../guide/rest-rate-limiting.md) +* [Versioning](../guide/rest-versioning.md) +* [Error Handling](../guide/rest-error-handling.md) + + +الأدوات المساعدة أثناء تطوير التطبيقات +----------------- + +* [Debug Toolbar and Debugger](https://www.yiiframework.com/extension/yiisoft/yii2-debug/doc/guide) +* [Generating Code using Gii](https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide) +* [Generating API Documentation](https://www.yiiframework.com/extension/yiisoft/yii2-apidoc) + + +فحص واختبار التطبيقات +------- + +* [Testing Overview](../guide/test-overview.md) +* [Testing environment setup](../guide/test-environment-setup.md) +* [Unit Tests](../guide/test-unit.md) +* [Functional Tests](../guide/test-functional.md) +* [Acceptance Tests](../guide/test-acceptance.md) +* [Fixtures](../guide/test-fixtures.md) + + +مواضيع وعناوين مميزة +-------------- + +* [Advanced Project Template](https://www.yiiframework.com/extension/yiisoft/yii2-app-advanced/doc/guide) +* [Building Application from Scratch](../guide/tutorial-start-from-scratch.md) +* [Console Commands](../guide/tutorial-console.md) +* [Core Validators](../guide/tutorial-core-validators.md) +* [Docker](../guide/tutorial-docker.md) +* [Internationalization](../guide/tutorial-i18n.md) +* [Mailing](../guide/tutorial-mailing.md) +* [Performance Tuning](../guide/tutorial-performance-tuning.md) +* [Shared Hosting Environment](../guide/tutorial-shared-hosting.md) +* [Template Engines](../guide/tutorial-template-engines.md) +* [Working with Third-Party Code](../guide/tutorial-yii-integration.md) +* [Using Yii as a micro framework](../guide/tutorial-yii-as-micro-framework.md) + + +Widgets +------- + +* [GridView](https://www.yiiframework.com/doc-2.0/yii-grid-gridview.html) +* [ListView](https://www.yiiframework.com/doc-2.0/yii-widgets-listview.html) +* [DetailView](https://www.yiiframework.com/doc-2.0/yii-widgets-detailview.html) +* [ActiveForm](https://www.yiiframework.com/doc-2.0/guide-input-forms.html#activerecord-based-forms-activeform) +* [Pjax](https://www.yiiframework.com/doc-2.0/yii-widgets-pjax.html) +* [Menu](https://www.yiiframework.com/doc-2.0/yii-widgets-menu.html) +* [LinkPager](https://www.yiiframework.com/doc-2.0/yii-widgets-linkpager.html) +* [LinkSorter](https://www.yiiframework.com/doc-2.0/yii-widgets-linksorter.html) +* [Bootstrap Widgets](https://www.yiiframework.com/extension/yiisoft/yii2-bootstrap/doc/guide) +* [jQuery UI Widgets](https://www.yiiframework.com/extension/yiisoft/yii2-jui/doc/guide) + + +Helpers +------- + +* [Helpers Overview](../guide/helper-overview.md) +* [ArrayHelper](../guide/helper-array.md) +* [Html](../guide/helper-html.md) +* [Url](../guide/helper-url.md) + diff --git a/docs/guide-ar/intro-yii.md b/docs/guide-ar/intro-yii.md new file mode 100644 index 00000000000..7177d094b8a --- /dev/null +++ b/docs/guide-ar/intro-yii.md @@ -0,0 +1,57 @@ +#
ما هي بيئة العمل Yii
+ +

Yii هو إطار PHP عالي الأداء يعتمد على المكونات لتطوير تطبيقات الويب الحديثة بسرعة. +إن الاسم "Yii" (يُنطق بـ "يي" أو "[جي:]" يعني "بسيطًا وتطوريًا" باللغة الصينية. ومن الممكن ايضا + اعتباره اختصارًا لـ Yes It Is!

+ + +#
ما هي أفضل التطبيقات أو البرمجيات التي يمكن برمجتها وتتناسب مع ال Yii
+ +

+Yii هو إطار عام لبرمجة الويب ، مما يعني أنه يمكن استخدامه لتطوير كافة أنواع +تطبيقات الويب باستخدام PHP. وذلك بسبب البنية القائمة على البنية التركيبة لبيئة العمل وترابطها مع المكونات والتخزين المؤقت، وهو مناسب بشكل خاص لتطوير portals, forums, content management systems (CMS), e-commerce projects, RESTful Web services. وما إلى ذلك. +

+ + +#
كيف يمكن مقارنة بيئة العمل الخاصة بال Yii مع الأطر أو بيئات العمل الأخرى؟
+ +

+ إذا كنت بالفعل على دراية بإطار العمل الأخرى ، فيمكنك معرفة كيف تتم مقارنة ال Yii: + +

+

+ +

+ال Yii إطار عمل صمم من قبل فريق برمجي متكامل، فهو ليس مجرد عمل فردي ، بل يتكون من فريق تطوير أساسي وقوي(http://www.yiiframework.com/team/) ، بالإضافة إلى منتدى كبير +من المهنيين الذين يساهمون باستمرار في تطوير هذا الإطار. فريق المطورين الخاص بال Yii +يراقب عن كثب أحدث اتجاهات تطوير الويب وأفضل الممارسات والمميزات التي +وجدت في الأطر والمشاريع الأخرى. وتدرج بانتظام بإضافة أفضل الممارسات والميزات الى ال Yii عبر واجهات بسيطة وأنيقة. +

+ + + +#
الإصدارات الخاصة بال Yii
+ +

+ يتوفر لدى Yii حاليًا إصداران رئيسيان: 1.1 و 2.0. الإصدار 1.1 هو الجيل القديم وهو الآن في وضع الصيانة. الإصدار 2.0 هو إعادة كتابة وهيكلة كاملة لل Yii، تم اعتماد أحدث التقنيات والبروتوكولات فيها مثل including Composer, PSR, namespaces, traits والكثير من الأمور الأخرى، وفي هذه الإرشادات، سيكون الكلام كله موجها الى الإصدار الثاني من بيئة العمل ال Yii. +

+ +#
المتطلبات الأساسية للعمل على إطار ال Yii
+ +

+

+

+ +

+ ملاحظة: يمكن التحقق من توافق المتطلبات الخاصة بك مع ال yii من خلال الدخول الى الصفحة requirement الموجودة بال yii +

diff --git a/docs/guide-ar/start-databases.md b/docs/guide-ar/start-databases.md new file mode 100644 index 00000000000..3fc18f0bd5c --- /dev/null +++ b/docs/guide-ar/start-databases.md @@ -0,0 +1,290 @@ +#
التعامل مع قواعد البيانات
+ +

+ في هذا الجزء التعليمي ستتعلم آلية إنشاء صفحة جديدة تعرض بيانات يتم جلبها من قاعدة البيانات -في هذا المثال، البيانات تخص ال country-، هذه البيانات سيتم جلبها من جدول موجود في قاعدة البيانات يسمى ب country. لتحقيق هذا المهمة، ستقوم بعمل ال config الخاص بالإتصال بقاعدة بيانات، بالإضافة لإنشاء ال Active Record class، وتعريف ال action، وإنشاء view لهذه الصفحة. +

+ + +

+ في هذا الشرح ستتعلم كيف يمكنك القيام بما يلي: +

+ + + +

+ ملاحظة: من أجل الانتهاء من هذا الجزء التعليمي، يجب أن يكون لديك المعرفة الأساسية والخبرة باستخدام قواعد البيانات. وعلى وجه الخصوص، يجب أن تعرف كيفية إنشاء قواعد البيانات، وكيفية تنفيذ ال statements SQL باستخدام أي DB client tool. +

+ +##
إعداد قاعدة البيانات
+ +

+ في البداية، عليك إنشاء قاعدة بيانات تسمى ب yii2basic، والتي ستستخدم لجلب البيانات الخاصة بالتطبيق، ويمكنك إستخدام أي من ال SQLite, MySql, PostgreSQL, MSSQL or Oracle database, ال Yii بشكل افتراضي بدعم العديد من قواعد البيانات والتي يمكنك إستخدامها مباشرة في التطبيق الخاص بك، ولتبسيط الأمور، ال MySql هي التي سيتم إستخدامها في في هذا الشرح. +

+ +

+ معلومة: إذا كنت ترغب بالحصول على خيارات متقدمة مثل دعم ال JSON الموجود داخل MariaDB، فيمكنك من إستخدام أحد ال Extension المذكوره بالأسفل للقيام بهذه المهمة بدلا من الإستغناء عن ال MySql، فإستخدام MariaDB بدلا عن ال MySql لم يعد صحيحا تماما. +

+ +

+ بعد قيامك بإنشاء قاعدة البيانات، سنقوم بإنشاء جدول إسمه country، ومن ثم سنقوم بإدخال بعض البيانات كعينة للإختيار، وللقيام بذلك، قم بتنفيذ الأوامر التالية: +

+ +```sql +CREATE TABLE `country` ( + `code` CHAR(2) NOT NULL PRIMARY KEY, + `name` CHAR(52) NOT NULL, + `population` INT(11) NOT NULL DEFAULT '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO `country` VALUES ('AU','Australia',24016400); +INSERT INTO `country` VALUES ('BR','Brazil',205722000); +INSERT INTO `country` VALUES ('CA','Canada',35985751); +INSERT INTO `country` VALUES ('CN','China',1375210000); +INSERT INTO `country` VALUES ('DE','Germany',81459000); +INSERT INTO `country` VALUES ('FR','France',64513242); +INSERT INTO `country` VALUES ('GB','United Kingdom',65097000); +INSERT INTO `country` VALUES ('IN','India',1285400000); +INSERT INTO `country` VALUES ('RU','Russia',146519759); +INSERT INTO `country` VALUES ('US','United States',322976000); +``` + +

+ الآن، أصبح لديك قاعدة بيانات إسمها yii2basic، وتحوي بداخلها جدول بثلاث أعمدة يسمى ب country، وفيه 10 صفوف من البيانات. +

+ +##
إعدادات الإتصال الخاصة بقواعد البيانات - Configuring a DB Connection
+ +

+ قبل أن تكمل الشرح، تأكد من تثبيت ال PHP PDO وال PDO driver، بالنسبة لهذا المثال، فإننا سنستخدم ال driver الخاص بال MySql وهو ال pdo_mysql، وهذه هي المتطلبات الأساسية لبناء أي التطبيق اذا كان التطبيق يستخدم ال relational database. +

+ +

+ ملاحظة: يمكنك تقعيل ال PDO مباشرة من خلال الدخول الى php.ini ومن ثم حذف الفاصلة المنقوطة قبل السطر التالي: extension=php_pdo.dll + كما يمكنك تفعيل ال driver المطلوب عن طريق حذف الفاصلة المنقوطة قبل ال driver المقصود مثل: +extension=php_pdo_mysql.dll + ويمكنك الإطلاع على المزيد من هنا: +pdo installation +

+ +

+ بعد إتمام ما سبق، قم بفتح الملف config/db.php ومن ثم قم بتعديل ال parameters لتكون الإعدادات الخاصة بقاعدة البيانات صحيحة -الإعدادت الخاصة بك-، بشكل افتراضي، يحتوي الملف على ما يلي: +

+ + +```php + 'yii\db\Connection', + 'dsn' => 'mysql:host=localhost;dbname=yii2basic', + 'username' => 'root', + 'password' => '', + 'charset' => 'utf8', +]; +``` + +

+ يمثل ملف ال config/db.php أداة نموذجية تعتمد على الملفات للقيام بال configuration. يقوم ملف ال configuration بتحديد ال parameters المطلوبة لإنشاء وإعداد ال instance الخاص بال [[yii\db\Connection]]، ومن خلالها يمكنك إجراء عمليات الإستعلام على قاعدة البيانات. +

+ +

+ الإعدادات الخاصة بالإتصال بقاعدة البيانات والمذكورة في الملف أعلاه يمكن الوصول اليها من خلال التطبيق عن طريق تنفيذ الأمر التالي + Yii::$app->db +

+ +

+ معلومة: سيتم تضمين ملف ال config/db.php من خلال ال main application configuration والذي يتمثل بالملف config/web.php، والذي يقوم بدوره بتحديد كيف يمكن تهيئة ال instance الخاص بالتطبيق، لمزيد من المعلومات، يرجى الإطلاع على قسم ال Configurations. +

+ +

+ إذا كنت بحاجة إلى العمل مع إحدى قواعد البيانات الغير مدعومة بشكل إفتراضي من ال Yii، فيمكنك التحقق من الإضافات التالية: +

+ + + +##
إنشاء ال Active Record + +

+ لجلب البيانات وعرضها من جدول ال country، سنقوم بإضافة ال Active Record الى ال class المسمى ب country، والموجود في المسار models/Country.php. +

+ +```php + + يرث ال Country Class ال [[yii\db\ActiveRecord]]، ولذلك، أنت لست بحاجة لكتابة أي شيفرة برمجية بداخله، فقط الشيفرة التي تشاهدها بالأعلى. سيقوم ال Yii بشكل تلقائي بالحصول على إسم الجدول في قاعدة البيانات من خلال إسم ال Class. +

+ +

+معلومة: إذا لم يكن من الممكن إجراء مطابقة مباشرة بين اسم ال class واسم الجدول، فيمكنك تجاوز هذه المشكلة من خلال إستخدام الدالة [[yii\db\ActiveRecord::tableName()]] ، والتي ستقوم بعمل override على اسم الجدول. +

+ +

+ من خلال إستخدام ال Country class، يمكنك التحكم بكل سهولة بالبيانات الموجودة داخل جدول ال country، شاهد هذه الشيفرة البرمجية لتبسيط الفكرة: +

+ +```php +use app\models\Country; + +// get all rows from the country table and order them by "name" +$countries = Country::find()->orderBy('name')->all(); + +// get the row whose primary key is "US" +$country = Country::findOne('US'); + +// displays "United States" +echo $country->name; + +// modifies the country name to be "U.S.A." and save it to database +$country->name = 'U.S.A.'; +$country->save(); +``` + +

+ معلومة: يعتبر ال Active Record وسيلة قوية للوصول إلى بيانات قاعدة البيانات والتعامل معها بطريقة ال object oriented. + ستجد معلومات أكثر تفصيلاً في الجزء الخاص بال Active Record. بالإضافة الى ذلك، يمكنك التفاعل مباشرة مع قاعدة البيانات باستخدام lower-level data accessing والتي تسمى ب Database Access Objects. +

+ +##
إنشاء ال Action + +

+لعرض بيانات ال country للمستخدمين، يلزمك إنشاء action جديد، وبدلاً من وضع ال action الجديد في ال site controller كما فعلنا في المرات السابقة، سنقوم بإنشاء controller جديد، ومن ثم سنقوم بوضع ال action بداخله، والسبب المنطقي لهذا العمل أنك ستقوم بتجميع الشيفرة البرمجية المسؤولة عن أداء وظائف معينة في مكان واحد، وبهذا فإن جميع الإجرائات التي تخص ال country من المنطقي أن تكون موجودة داخل ال CountryController، والآن لنقم بإنشاء هذا ال controller الجديد، وال action الجديد وسيكون باسم index، كما هو موضح أدناه: +

+ +```php + 5, + 'totalCount' => $query->count(), + ]); + + $countries = $query->orderBy('name') + ->offset($pagination->offset) + ->limit($pagination->limit) + ->all(); + + return $this->render('index', [ + 'countries' => $countries, + 'pagination' => $pagination, + ]); + } +} +``` +

+ قم بحفظ الشيفرة البرمجية التي بالأعلى داخل هذا الملف controllers/CountryController.php +

+ +

+ يقوم ال index action باستخدام ال Country::find()، وهذه الدالة موجودة من ضمن ال active record، وتقوم هذه الدالة على بناء الإستعلام الخاص بقاعدة البيانات مما يسمح باسترجاع جميع البيانات الموجودة بداخل جدول ال country، ولتحديد الحد الأعلى المسموح إرجاعه في كل request، يمكنك إستخدام ال [[yii\data\Pagination]] object كوسيلة مساعدة، ويقدم هذا ال object غرضين أساسيين وهما: +

+ + + +

+ في نهاية الشيفرة البرمجية الموجودة في ال index action، نقوم باستدعاء صفحة ال view المسمية ب index، ومن ثم نقوم بإرسال معلومات ال country المنظمة على شكل صفحات (pagination) ومن ثم عرضها. +

+ + +##
إنشاء View
+ +

+ الآن، سنقوم بإنشاء صفحة ال view والتي ستقوم بعرض المعلومات الخاصة بال country والقادمة من ال index action، ولذلك توجه الى المسار views, ومن ثم قم بإنشاء مجلد جديد بداخله باسم country، هذا المجلد سيحوي جمع ال views التي سيتم إستدعائها من ال country controller>. الآن، قم بإنشاء الصفحة index.php بداخل المسار views/country، ومن ثم قم بكتابة هذه الشيفرة البرمجية بداخلها: +

+ +```php + +

Countries

+ + + $pagination]) ?> +``` + +

+ في هذه الصفحة، هناك جزئيين رئيسيين، الجزء الأول هو المسؤول عن طباعة المعلومات الخاصة بال country داخل قائمة من نوع ul، والجزء الثاني عبارة عن widget يستخدم المعلومات الخاصة بال pagination والتي تم إرسالها من ال action، ليقوم بعد ذلك بعرض قائمة من ال page buttons، والتي بدورها ستقوم بعمل تحديث للمعلومات الموجودة بالصفحة بنائا على الصفحة المطلوبة، هذا ال widget يسمى ب LinkPager -[[yii\widgets\LinkPager]]-. +

+ +##
لنجرب المثال
+ +

+ لتشاهد آلية العمل لهذا المثال، والنتائج المتعلقة به، يمكنك إستخدام المتصفح والدخول الى الرابط التالي: +

+ +``` +http://hostname/index.php?r=country%2Findex +``` + +![Country List](../guide/images/start-country-list.png) + +

+في البداية، ستشاهد البيانات الخاصة بخمسة دول، وأسفل هذه الدول، ستشاهد pager فيه 4 أزرار، اذا قمت بالضغط على الزر رقم 2، فإنك ستشاهد المعلومات الخاصة بخمسة دول أخرى، والتي تمثل صفوف أخرى من البيانات تم جلبها من قاعدة البيانات. +
+تابع بعناية أكبر وستجد أن عنوان ال URL في المتصفح قد تغير أيضًا: +

+ +``` +http://hostname/index.php?r=country%2Findex&page=2 +``` + +

+ بالخفاء، يقوم ال [[yii\data\Pagination|Pagination]] بتقديم الدعم اللازم لكل الوظائف المطلوب تنفيذها لعمل الترقيم الخاص بال pagination: +

+ + + +##
الخلاصة
+ +

+ في هذا الجزء من التوثيق، لقد تعلمنا كيف يمكننا التعامل مع قواعد البيانات، وكيف يمكننا جلب البيانات وعرضها وتجزئتها لصفحات من خلال إستخدام ال [[yii\data\Pagination]] وال [[yii\widgets\LinkPager]]. +

+ +

+ في الجزء القادم من هذا التوثيق، ستتعلم كيف يمكنك إستخدام إخدى الوسائل المميزة والموجودة في ال Yii لإنشاء الشيفرة البرمجية الخاصة بك، والتي يطلق عليها اسم Gii، هذه الأداة ستساعدك على إنشاء وتنفيذ الشيفرات البرمجية التي يكثر كتابتها وإستخدامها بشكل دوري، مثل مجموعة العمليات Create-Read-Update-Delete، والتي يتم اختصارها ب CRUD، هذه الأداة ستقوم بالتعامل مع البيانات الموجدة بقاعدة البيانات، وفي الحقيقة، الشيفرة البرمجية الذي قمت بكتابته بالأعلى، يمكنك إنشائه بسهولة من خلال ال Gii بنقرة زر، لذلك فلننطلق الى الجزء التالي بأسرع وقت. +

diff --git a/docs/guide-ar/start-forms.md b/docs/guide-ar/start-forms.md new file mode 100644 index 00000000000..ecbbda98e19 --- /dev/null +++ b/docs/guide-ar/start-forms.md @@ -0,0 +1,253 @@ +#
العمل مع ال Forms
+ +

+في هذا الموضوع سنتعلم كيفية إنشاء صفحة تحتوي على form للحصول على البيانات من خلال المستخدمين، وستعرض هذه الصفحة form يحتوي على حقل لإدخال الإسم وحقل إدخال للبريد الإلكتروني. +وبعد الحصول على المعلومات الخاصة بهذه الحقول من المستخدم، ستقوم الصفحة بطباعة القيم التي تم إدخالها. +

+ +

+ في هذا الشرح، ستقوم بإضافة action وصحفتين views، وستتعرف أيضا على طريقة إنشاء ال model. +

+ +

+من خلال هذا البرنامج التعليمي ، ستتعلم كيفية: +

+ + + +##
إنشاء ال Model
+ +

+ يتم تمثيل البيانات التي يتم طلبها من خلال المستخدم عن طريق ال EntryForm model class كما هو موضح أدناه، ويتم حفظ هذا الملف داخل المسار models، ويكون إسم ال model ومساره في مثالنا هذا هو models/EntryForm.php. يرجى الرجوع إلى صفحة ال Class Autoloading للحصول على مزيد من التفاصيل حول طريقة التعامل مع التسمية الخاصة بال class في Yii. +

+ +```php + + هذا ال class يرث ال [[yii\base\Model]], وهو base class تم تصميمه من خلال ال Yii, وبشكل عام وظيفته هي تثمثيل البيانات الخاصة بأي نموذج. +

+ +

+معلومة: يتم إستخدام ال [[yii\base\Model]] كأصل لل model class ولا يرتبط بجداول قواعد البيانات. ويستخدم ال [[yii\db\ActiveRecord]] بالشكل الإعتيادي ليكون هو الأصل الذي من خلاله يتم الإرتباط بجداول بقواعد البيانات. +

+ +

+ يحتوي class ال EntryForm على متغيرين إثنين من نوع Public، هما name و email، واللذان يستخدمان في تخزين البيانات التي أدخلها المستخدم. كما يحتوي أيضًا على method باسم rules()، والتي تُرجع مجموعة +الشروط الخاصة بالبيانات للتحقق من صحتها. والشيفرة البرمجية الموجودة داخل ال rules method تعني: +

+ + + +

+ إذا كان لديك object من ال EntryForm ويحتوي على البيانات التي أدخلها المستخدم، فيمكنك حينها إستدعاء الدالة [[yii\base\Model::validate()|validate()]] للتحقق من صحة البيانات. اذا فشلت عملية التحقق من صحة البيانات، فسيؤدي ذلك إلى تغيير قيمة ال [[yii\base\Model::hasErrors|hasErrors]] إلى true ، بالإضافة الى ذلك يمكنك التعرف الى الأخطاء المتعلقة بهذه البيانات من خلال الدالة [[yii\base\Model::getErrors|errors]]. +

+ +```php +name = 'Qiang'; +$model->email = 'bad'; +if ($model->validate()) { + // Good! +} else { + // Failure! + // Use $model->getErrors() +} +``` + + +##
إنشاء Action
+ +

+ الآن، ستحتاج إلى إنشاء action جديد في ال site controller وليكن إسمه entry، والذي سيقوم بدوره باستخدام ال model الجديد الذي قمنا بإنشائه. هذه العملية تم شرحها سابقا في الجزء التالي من التوثيق Saying Hello - قل مرحبا. +

+ +```php +load(Yii::$app->request->post()) && $model->validate()) { + // valid data received in $model + + // do something meaningful here about $model ... + + return $this->render('entry-confirm', ['model' => $model]); + } else { + // either the page is initially displayed or there is some validation error + return $this->render('entry', ['model' => $model]); + } + } +} +``` +

+ أولا، يقوم ال action بإنشاء object من ال EntryForm. ثم يحاول تعبئة البيانات لل object من خلال ال $ _POST، والتي يتم تقديمها في ال Yii من خلال ال [[yii\web\Request::post()]]. +إذا تم ملء ال object بنجاح (على سبيل المثال، إذا قام المستخدم بإدخال البيانات داخل ال form ومن ثم قام بإرسالها(submitted html form))، فسيتم استدعاء ال [[yii\base\Model::validate()|validate()]] من خلال ال action للتأكد من صلاحية القيم المدخلة. +

+ + +

+ معلومة: يمثل التعبير Yii::$app ال Application instance الذي يمكن الوصول اليه من خلال ال singleton
(singleton globally accessible). وهو أيضا service locator بحيث يوفر الدعم لل components مثل ال request, response, db..الخ، لدعم وظائف محددة. مثلا في المثال الموجود في الأعلى، فإن ال request هو component من ال application instance والذي يستخدم للوصول الى البيانات الموجودة داخل ال $_POST. +

+ +

+ إذا كان كل شيء على ما يرام، فسوف يقوم ال action بجلب ال view التالية: entry-confirm، وذلك لتأكيد أن العملية قد تمت بنجاح بالنسبة للمستخدم، أما إن كانت البيانات غير صحيحة، أو لم يتم إرسال أي بيانات، فإن ال view entry هي التي سيتم جلبها وعرضها للمستخدم، حيث يتم عرض ال Html form، مع أي رسائل تحذير بخصوص الأخطاء التي تم العثور عليها من عملية التحقق. +

+ +

+ملاحظة: في هذا المثال البسيط، نعرض صفحة التأكيد فقط عند إرسال البيانات بشكل صحيح. عند الممارسة العملية، يجب عليك استخدام [[yii\web\Controller::refresh()|refresh()]] أو [[yii\web\Controller::redirect()|redirect()]] لتجنب أي مشكلة تحصل عن طريق ال resubmission والتي تندرج تحت العنوان form resubmission problems. +

+ +##
إنشاء ال views
+ +

+ أخيرا، سنقوم بإنشاء صفحتين لل views الأولى بإسم entry-confirm والثانية entry. وهاتين الصفحتين سيتم جلبهم من خلال ال entry action. +

+ +

+ ال entry-confirm ستقوم بكل بساطة بعرض الإسم والبريد الإلكتروني الذي تم إدخالهم من قبل المستخدم. ويجب حفظ هذه الصفحة بالمسار التالي: views/site/entry-confirm.php +

+ +```php + +

You have entered the following information:

+ + +``` +

+ صفحة ال entry ستقوم بعرض ال HTML form. هذه الصفحة يجب أن يتم حفظها داخل المسار التالي: views/site/entry.php +

+ +```php + + + + field($model, 'name') ?> + + field($model, 'email') ?> + +
+ 'btn btn-primary']) ?> +
+ + +``` +

+ تستخدم ال view أسلوب مميز لبناء ال Forms، وذلك عن طريق ال widget الذي يسمى ب [[yii\widgets\ActiveForm|ActiveForm]]. إن الأسلوب المستخدم في هذا ال widget يقوم على إستخدام كل من الدالة begin() و end() لجلب ال opening وال closing form tags على التوالي (فتحة ال tag، ثم الإغلاق الخاص بهذا ال tag)، وبين الفتحة والإغلاق يمكنك إنشاء الحقول عن طريق إستخدام الدالة [[yii\widgets\ActiveForm::field()|field()]]. في هذا المثال كان الحقل الأول في ال form يشير الى name data، والثاني يشير الى ال email data، وبعد هذه الحقول ستجد الدالة المستخدمة لإنشاء ال Submit button وهي [[yii\helpers\Html::submitButton()]]. +

+ +##
لنجرب المثال
+ +

+ لتشاهد آلية العمل لهذا المثال، والنتائج المتعلقة به، يمكنك إستخدام المتصفح والدخول الى الرابط التالي: +

+ +``` +http://hostname/index.php?r=site%2Fentry +``` + +

+عند دخولك الى الرابط السابق، سترى صفحة تعرض Html form يحتوي على حقلين لإدخال المعلومات. أمام كل حقل إدخال ستجد label يشير إلى البيانات المطلوب إدخالها. إذا قمت بالنقر فوق الزر "submit" بدون +أي إدخال، أو إذا لم تقم بكتابة عنوان البريد الإلكتروني بشكل صحيح، فستظهر لك رسالة خطأ بجوار الحقل المقصود. +

+ +![Form with Validation Errors](../guide/images/start-form-validation.png) + +

+ بعد إدخالك لإسم وبريد الكتروني صحيح، وقيامك بالنقر على زر submit، فإنك ستشاهد صفحة جديدة تقوم بعرض البيانات التي قمت بإدخالها. +

+ +![Confirmation of Data Entry](../guide/images/start-entry-confirmation.png) + +##
كيف ظهر الخطأ؟ هل هو سحر؟!
+ +

+قد تتساءل كيف يعمل ال Html form بالخفاء، وقد يبدو ذلك سحرا للوهلة الأولى، فهو يعرض ال label لكل حقل إدخال، ويعرض رسائل الخطأ إذا لم تقم بإدخال البيانات بشكل صحيح، وكل ذلك دون الحاجة لإعادة تحميل الصفحة. +

+ +

+ إن السحر الموجود لدينا هنا، هو كيفية العمل الخاصة بالشيفرة البرمجية لل form، والتي تعمل بالخفاء، إن إجراء التحقق عن صحة البيانات يتم في البداية من جانب العميل -client side- وذلك باستخدام الجافا سكربت، ومن ثم -بعد تجاوز التحقق الخاص بالجافا سكربت- بتم تنفيذ التحقق من جانب ال server-side عبر ال PHP. ال [[yii\widgets\ActiveForm]] ذكية بما فيه الكفاية لاستخراج ال rule الخاصة بالتحقق والتي قمت بإنشائها وتعريفها داخل ال EntryForm، ومن ثم تحويل هذه القواعد إلى شيفرة برمجية بالجافا سكربت قابلة للتنفيذ، ومن ثم استخدام هذه الشيفرة من قبل الجافا سكربت لإجراء التحقق من صحة البيانات. في حال قمت بإيقاف الجافا سكربت في المتصفح الخاص بك، سوف يستمر إجراء التحقق من جانب الخادم -server side-، كما هو موضح في ال action المسمى actionEntry(). وهذا يضمن صحة البيانات في جميع الظروف. +

+ +

+ تحذير: التحقق من جانب العميل -client side- يوفر تجربة أفضل للمستخدم، لكن يجب الأخذ بعين الإعتبار أن التحقق من جانب الخادم -server- مطلوب دائمًا، سواء تم التحقق من جانب العميل أم لا. +

+ +

+ يتم إنشاء ال labels الخاصة بحقول الإدخال بواسطة الدالة field()، وذلك من خلال إستخدام أسماء ال property الموجودة داخل ال model. على سبيل المثال، سيتم إنشاء ال label التالي Name للproperty التالية: name. +

+ +

+ كما يمكنك تعديل ال label الإفتراضي لأي حقل من خلال الشيفرة البرمجية التالية: +

+ +```php +field($model, 'name')->label('Your Name') ?> +field($model, 'email')->label('Your Email') ?> +``` + +

+ معلومة: يوفر ال Yii العديد من ال widgets لمساعدتك في إنشاء views معقدة وديناميكية بسرعة. كما أنك ستتعلم في وقت لاحق كيف يمكنك إنشاء widget جديد، وستكتشف أن الموضوع سهل وبسيط، مما سيدفعك إلى كتابة الشيفرة البرمجية الخاصة بك داخل ال widget، والذي بدوره سيجعل من هذه الشيفرة قابلة للتطوير والإستخدام في أكثر من مكان في المستقبل. +

+ +##
الخلاصة
+ +

+ في هذا الجزء من التوثيق، تحدثنا عن كل جزء في ال MVC architectural pattern، لقد تعلمت الآن كيف يمكنك إنشاء model class ليقوم بتمثيل البيانات الخاصة بالمستخدمين، ومن ثم التحقق منها. +

+ +

+ لقد تعلمت أيضًا كيفية الحصول على البيانات من المستخدمين، وكيفية عرض البيانات مرة أخرى في المتصفح. هذه المهمة يمكن أن تأخذ الكثير من الوقت عند تطوير أي تطبيق، ولكن، يوفر ال Yii العديد من ال widgets القوية، والتي تجعل من هذه المهمة أمرا سهلا للغاية. +

+ +

+ في الجزء القادم من هذا التوثيق، ستتعلم كيف يمكنك التعامل مع قواعد البيانات، والتي سنحتاجها -غالبا- مع كل تطبيق ستعمل عليه تقريبا. +

diff --git a/docs/guide-ar/start-gii.md b/docs/guide-ar/start-gii.md new file mode 100644 index 00000000000..58d8fd74362 --- /dev/null +++ b/docs/guide-ar/start-gii.md @@ -0,0 +1,161 @@ +#
إنشاء الشيفرة البرمجية من خلال ال gii
+ +

+ في هذا الجزء التعليمي سنتعرف على آلية التعامل مع ال Gii، والذي يستخدم لإنتاج الشيفرة البرمجية الخاصة بمعظم الميزات والخصائص المشتركة في أغلب المواقع بشكل تلقائي، بالإضافة الى ذلك، فإن استخدام ال Gii لإنشاء الشيفرة البرمجية بشكل تلقائي يمثل مجموعة من المعلومات الصحيحة التي بتم إدخالها إعتمادا على التعليمات الموجودة في ال Gii Web Pages. +

+ +

+ من خلال هذا البرنامج التعليمي، ستتعلم كيفية: +

+ + + +##
البدء باستخدام ال Gii + +

+ يتم تقديم ال Gii داخل على ال Yii على أنه module، ويمكنك تفعيله من خلال الإعدادات الخاصة به والتي تجدها داخل ال application، وبالتحديد داخل ال property التالية [[yii\base\Application::modules|modules]]، واعتمادا على كيفية إنشائك للمشروع، فيمكنك إيجاد الشيفرة البرمجية التالية موجودة بشكل مسبق داخل ال config/web.php: +

+ +```php +$config = [ ... ]; + +if (YII_ENV_DEV) { + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = [ + 'class' => 'yii\gii\Module', + ]; +} +``` + +

+ في الإعدادت الموجودة في الأعلى، فإن التطبيق سيقوم بتضمين وتفعيل ال gii في حال كانت الحالة الخاصة بالتطبيق هي development enviroment، بالإضافة الى ذلك، فإنه يجب تضمين واستخدام ال module gii، والموجود ضمن ال class التالي [[yii\gii\Module]]. +

+ + +

+ اذا قمت بالتحقق من ال entry script وبالتحديد صفحة ال web/index.php في التطبيق الخاص بك، ستجد هذه الأسطر، والتي يجب أن تجعل من ال YII_ENV_DEV ذات قيمة true. +

+ +```php +defined('YII_ENV') or define('YII_ENV', 'dev'); +``` + +

+ كل الشكر لهذا السطر البرمجي، التطبيق الآن أصبح بحالة ال development mode، وأصبح لديك ال Gii enabled بالفعل، والآن، يمكنك الوصول الى ال Gii من خلال عنوان ال URL التالي: +

+ +``` +http://hostname/index.php?r=gii +``` + +

+ ملاحظة: إذا كنت تحاول الوصول إلى Gii من جهاز آخر غير ال localhost، فسيتم رفض الوصول افتراضيًا لأغراض أمنية، ولكن، يمكنك إعداد ال Gii لإضافة مجموعة من ال IP Addresses المسموح لها بالوصول وذلك من خلال: +

+ +```php +'gii' => [ + 'class' => 'yii\gii\Module', + 'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.178.20'] // عدل هذه حسب إحتياجاتك +], +``` + +![Gii](../guide/images/start-gii.png) + + +##
إنشاء ال Active Record Class من خلال ال Gii
+ +

+ لإستخدام ال Gii لإنشاء ال Active Record class, قم باختيار ال "Model Generator" (من خلال النقر على الرابط الموجود بالصفحة الرئيسية لل Gii)، ومن ثم قم بتعبئة ال form كما يلي: +

+ +
    +
  • إسم الجدول: country
  • +
  • Country :Model Class
  • +
+ +![Model Generator](../guide/images/start-gii-model.png) + +

+ والآن، قم بالنقر على الزر "Preview"، ستشاهد الآن models/Country.php قد تم إنشائها وإضافتها الى قائمة النتائج، اذا قمت بالنقر على إسم ال class، فإن المحتوى الخاص بهذا ال class سيتم عرضه. +

+ +

+ عند استخدام ال Gii، إذا كنت قد قمت بالفعل بإنشاء نفس الملف وستقوم بعمل overwriting عليه، فيمكنك النقر على زر diff الموجود بعد إسم ال class، لتشاهد الفرق بين الشيفرة البرمجية الحالية، والشيفرة البرمجية الجديدة. +

+ +![Model Generator Preview](../guide/images/start-gii-model-preview.png) + +

+ عند قيامك بعمل overwriting على ملف موجود، قم بالضغط على ال ckeckbox الموجودة بجانب كلمة overwrite، ومن ثم قم بالنقر على زر "Generate", اذا كان هذا الملف جديد، وغير موجود مسبقا، فيمكنك النقر مباشرة على "Generate"، بعد ذلك ستشاهد صفحة ال confirmation والتي تبين الشيفرات البرمجية التي تم إنشائها بنجاح. +

+ +

+ بعد فيامك بالنقر على زر Generate، فإنك ستشاهد صفحة ال confirmation page، والتي تقوم بدورها بتوضيح الشيفرات البرمجية التي تم إنشائها بنجاح، واذا كان الملف موجود، فإنك ستشاهد أيضا رسالة تعلمك بأن الملف قد تم تعديله وتمت إضافة الشيفرة الجديدة مكان القديمة. +

+ +##
إنشاء ال CRUD Code
+ +

+ ال CRUD هي اختصار ل Create, Read, Update, And Delete (إنشاء، وقرائة، وتحديث، وحذف)، والتي تمثل أكثر المهمات المطلوبة للتعامل مع البيانات على مواقع الويب. ولإنشاء ال CRUD باستخدام ال Gii، قم باختيار ال "CRUD Generator" (من خلال النقر على الرابط الموجود بالصفحة الرئيسية لل Gii)، وهنا وبالبنسبة للمثال الخاص بال "country"، يمكنك تعبئة ال from بما يلي: +

+ +* Model Class: `app\models\Country` +* Search Model Class: `app\models\CountrySearch` +* Controller Class: `app\controllers\CountryController` + +![CRUD Generator](../guide/images/start-gii-crud.png) + +

+ بعد ذلك، قم بالنقر على زر ال "Preivew"، وستشاهد قائمة بالملفات التي سيتم إنشائها كما في الصورة أدناه. +

+ +![CRUD Generator Preview](../guide/images/start-gii-crud-preview.png) + +

+ اذا قمت إنشاء الصفحتين controllers/CountryController.php و views/country/index.php عند حديثنا سابقا عند موضوع (التعامل مع قواعد البيانات)، فقم بالضغط على ال "overwrite" ليتم إستبدالهم. (الصفحات القديمة لا توجد فيها كل الخصائص التي سيتم إنتاجها من خلال ال Gii CRUD). +

+ +##
لنجرب المثال
+ +

+لتشاهد آلية العمل لهذا المثال، والنتائج المتعلقة به، يمكنك إستخدام المتصفح والدخول الى الرابط التالي: +

+ +``` +http://hostname/index.php?r=country%2Findex +``` + +

+ عند دخولك إلى الرابط أعلاه، ستشاهد مجموعة الدول التي تم إستدعائها من جدول ال country من قاعدة البيانات، ويمكنك التعامل مع هذا ال grid من حيث الترتيب أو التصفية بنائا على الشروط التي ستقوم بإدخالها في مربعات النص أعلى الأعمدة. +

+ +

+لكل دولة تم جلبها وعرضها داخل ال Grid، هناك مجموعة من الخيارات التي يمكنك التعامل معها بشكل إفتراضي، مثل ال view لعرض التفاصيل الخاصة بالدولة المختارة، أو تحديث المعلومات، الخاصة بالدولة، أو حذف هذه الدولة، بالإضافة إلى ذلك يمكنك النقر على "Create Country" الموجودة في أعلى ال Grid والتي ستأخذك بدورها الى صفحة تحتوي form لإنشاء ال country. +

+ +![Data Grid of Countries](../guide/images/start-gii-country-grid.png) + +![Updating a Country](../guide/images/start-gii-country-update.png) + +

+ فيما يلي قائمة بالملفات التي تم إنشاؤها من خلال ال Gii، في حالة رغبتك في التحقق من كيفية عمل هذه الميزات والإطلاع على الشيفرة البرمجية وتخصيصها حسب الرغبة: +

+ +* Controller: `controllers/CountryController.php` +* Models: `models/Country.php` and `models/CountrySearch.php` +* Views: `views/country/*.php` + +

+معلومة: تم تصميم ال Gii لتكون أداة إنشاء شيفرات برمجية قابلة للتخصيص بشكل كبير للغاية. اذا قمت باستخدامه بحكمة،فإنك ستقوم بتسريع وتيرة التطوير الخاصة بالتطبيق الخاص بك. لمزيد من التفاصيل، يرجى الذهاب إلى الجزء الخاص بال Gii. +

+ +##
الخلاصة
+ +

+في هذا الجزء من التوثيق، لقد تعلمنا آلية استخدام ال Gii لإنشاء الشيفرة البرمجية الخاصة بال CRUD، وتحدثنا عن الوظائف التي تقوم فيها، وكيف يمكننا من خلالها إتمام العمليات الخاصة بالبيانات من إدخال وتحديث وحذف وعرض للبيانات من قاعدة البيانات. +

diff --git a/docs/guide-ar/start-hello.md b/docs/guide-ar/start-hello.md new file mode 100644 index 00000000000..86bfbd236e6 --- /dev/null +++ b/docs/guide-ar/start-hello.md @@ -0,0 +1,149 @@ +#
قل مرحبا - Saying Hello
+ +

+ في هذا الموضوع سنتعرف على كيفية إنشاء صفحة "Hello" جديدة في التطبيق الذي قمت بتثبيته، ولتحقيق ذلك، يجب عليك القيام بإنشاء action و view لهذه الصفحة: +

+ +
    +
  • سيقوم التطبيق بإرسال ال request الخاص بالصفحة إلى ال action.
  • +
  • وسيقوم ال action بدوره في جلب ال view التي تعرض كلمة "Hello" إلى المستخدم النهائي.
  • +
+ +

+ من خلال هذا البرنامج التعليمي ، ستتعلم ثلاثة أشياء: +

+ +
    +
  1. كيفية إنشاء action ليقوم بإستقبال ال request ومن ثم الرد (respond) عليها.
  2. +
  3. كيفية إنشاء view وإضافة المحتوى الى ال respond.
  4. +
  5. و كيفية إنشاء التطبيق لل requests التي يوجهها لل actions.
  6. +
+ +##
إنشاء ال Action
+ +

+ لإنشاء صفحة "Hello"، ستقوم بإنشاء say action والذي بدوره سيقوم بقراءة ال message parameter من ال request، ومن ثم عرض ال message مرة أخرى إلى المستخدم. إذا كان ال request لا يحمل معه ال message parameter فإن ال action سيقوم بطباعة message إفتراضية وهي "Hello". +

+ +

+ معلومة: ال Actions هي الكائنات(objects) التي يمكن للمستخدمين من الوصول اليها وتنفيذ ما في بداخلها بشكل مباشر. يتم تجميع هذه ال Actions بواسطة ال controllers. ونتيجة لذلك فإن ال response الراجعة للمستخدم ستكون هي نتيجة التنفيذ الخاصة بال action. +

+ +

+ يجب تعريف ال actions داخل ال controller، ولتبسيط الفكرة، سنقوم بتعريف ال say action داخل أحد ال controller الموجود مسبقا وهو ال siteController. هذا ال controller ستجده داخل المسار controllers/siteController.php. ومن هنا سنبدأ بإضافة ال action الجديد: +

+ +```php +render('say', ['message' => $message]); + } +} +``` + +

+ في الشيفرة البرمجية السابقة ، تم تعريف ال say action من خلال إنشاء الدالة actionSay داخل الكلاس siteController. يستخدم ال Yii كلمة action ك prefix للدوال للتميز بين الدوال ال action و ال non-action في ال controller، كما يستخدم الإسم الخاص بال action مباشرة بعد ال prefix، ويتم عمل mapping بين ال action method name وال action id ليستطيع المستخدم من الوصول للدالة المنشئة من خلال ال action id. +

+ +

+ عندما يتعلق الأمر بتسمية ال action الخاصة بك، يجب عليك أن تفهم كيف يقوم ال Yii بالتعامل مع ال action id، ال action id يجب أن يكون دائما أحرف lower case، وإذا إحتوى ال action id على عدة كلمات فإن الفاصل بينهم سيكون الداش (dashes) مثل create-comment، ويتم ربط ال action id بال action method name من خلال حذف ال dashes من ال IDs، ويتم عمل capitalizing لأول خرف من كل كلمة، وإضافة ال prefix الى الناتج السابق من التحويل. مثال: ال action id المسمى ب create-comment سيتم تحويله الى ال action method name التالي: actionCreateComment. +

+ +

+ في المثال السابق، يقوم ال action method على إستقبال parameter يسمى ب $message، والذي يملك قيمة إفتراضية وهي "Hello" (وهي مشابة تماما لطريقة وضع القيم الإفتراضية لل argument في ال PHP). عندما يستقبل التطبيق ال request ويحدد أن ال action المطلوب للتعامل مع الطلب (request) هو say، فإن التطبيق سيقوم بإسناد القيمة الموجودة بال request الى ال parameter الموجود بال action بشرط أن يكون الإسم الموجود بال request هو نفسه الموجود في ال action. ولتبسيط الموضوع يمكن القول أن ال request اذا احتوى على كلمة message وقيمة هذا ال parameter هي "GoodBye"، فإن ال $message الموجودة في ال action ستصبح قيمتها "GoodBye". +

+ + +

+ من خلال ال action method، يتم استدعاء ال [[yii\web\Controller::render()|render()]] لتقديم +الملف الخاص بال view والمسمى هنا ب say. أيضا فإن ال message يتم تمرريرها الى ال view مما يسمح لك باستخدام هذا ال parameter داخل ال view. النتيجة المرجعة لل view تتم معالجتها وإرجاعها من خلال ال action method، وهذه النتائج سيتم إستقبالها من خلال المتصفح الخاص بالمستخدم ليتم عرضها وكأنها (جزء من صفحة Html كاملة). +

+ +##
إنشاء ال View
+ +

+ ال Views هي شيفرات برمجية كتبت ﻹنشاء المحتوى المناسب بنائا على ال response الراجع اليها من خلال ال action. + بالنسبة إلى مثال "Hello" ، الآن سنقوم بإنشاء view مسمى ب say، والذي سيقوم بدوره بطباعة ال message التي تم إستلامها من ال action، شاهد المثال: +

+ + +```php + + +``` + +

+ صفحة ال view say يجب أن يتم حفظها داخل المسار التالي: views/site/say.php. عندما يتم إستدعاء الدالة [[yii\web\Controller::render()|render()]] من قبل ال action، فإنه سينظر للمسار على الشكل التالي: views/ControllerID/ViewName.php، بحيث يكون في مثالنا السابق ال ContollerID هو ال site وال viewName هو say. +

+ +

+ ملاحظة: في الشيفرة البرمجية أعلاه، تكون ال message مضمنة داخل ال [[yii\helpers\Html::encode()]] قبل أن يتم طباعتها، هذا الأمر ضروري لأن ال parameter التي تأتي من المستخدم النهائي لا يجب الوثوق بها، فهي يمكن أن تحتوي على شيفرات برمجية تستغل الضعف الحاص بك بموضوع الأمان مثل vulnerable to XSS attack عن طريق دمج JS code مع ال parameter. +

+ +

+ وبطبيعة الحال، يمكنك وضع المزيد من المحتوى في صفحة ال say view. ويمكن أن يتكون هذا المحتوى من HTML tag و plain text وحتى PHP statements. +في الواقع، تعد ال say view مجرد شيفرة برمجية بلغة ال PHP والتي يتم تنفيذها بواسطة [[yii\web\Controller::render()|render()]]. +المحتوى الذي سيتم طباعته من خلال ال view سيتم إرجاعه الى التطبيق من خلال ال response، وسيقوم التطبيق بدوره بإخراج هذه النتيجة إلى المستخدم النهائي. +

+ + +##
تطبيق المثال
+------------- + +

+بعد إنشاء ال action وصفحة ال view، يمكنك الوصول إلى الصفحة الجديدة عن طريق عنوان URL التالي: +

+ +``` +http://hostname/index.php?r=site%2Fsay&message=Hello+World +``` + +![Hello World](../guide/images/start-hello-world.png) + +

+ سينتج عن هذا ال URL صفحة تعرض "Hello World". هذه الصفحة لديها نفس ال Header و ال Footer لصفحات التطبيق الأخرى. +

+ +

+ إذا قمت بحذف ال message parameter من ال URL ، فسترى الصفحة تعرض كلمة " Hello " فقط. ويرجع ذلك إلى أن "message" يتم تمريرها ك parameter إلى ال actionSay()، وعندما يتم حذفها، سيتم استخدام القيمة الافتراضية وهي "Hello" بدلاً من ذلك. +

+ +

+ معلومة: تتشارك الصفحة الجديدة مع الصفحات الأخرى بالتطبيق بنفس ال Header وال Footer وذلك بسبب الدالة [[yii\web\Controller::render() | render ()]] والتي ستقوم بشكل تلقائي بتضمين النتيجة الخاصة بصفحة ال view say مع صفحة ال Layout، والتي يمكنك أن تجدها داخل المسار التالي: views/layouts/main.php +

+ +

+ ال r الموجودة في ال URL أعلاه يتطلب الكثير من الشرح. ولكن باختصار يمكن القوم أنها اختصار ل route ، وهو معرف فريد من نوعه(unique ID) للتطبيق بحيث يقوم بالتأشير على ال action، والصيغة الخاصة بال route هي ControllerID/ActionID. عندما يتلقى التطبيق request، فإنه سيتم التحقق من r parameter، فيقوم باستخدام الجزء ControllerID لتحديد ال controller class المطلوب ليقوم بعمل instance منه، ومن ثم يقوم ال controller باستخدام ال "ActionID" لتحديد ال action المطلوب والذي سيقوم بالعمل الفعلي. + في المثال الخاص بنا، فإن ال route هو "site/say"، وهذا ال route يتم معالجته ليستدعي ال controller class المسمى ب SiteController و ال action المسمى ب actionSay داخل هذا ال controller، ونتيجة لذلك سيتم فعليا إستدعاء الدالة SiteController::actionSay() لتقوم بمعالجة ال request كما يلزم. +

+ +

+ معلومة: مثل ال actions، تحتوي ال controllers أيضًا على Uniquely IDs يتم تعريفها واستخدامها من خلال التطبيق. تستخدم ال Controllers IDs نفس قواعد التسمية الخاصة بال action IDs، ويتم ذلك من خلال حذف ال dashes و capitalizing أول حرف من كل كلمة، ثم إضافة كلمة Controller الى الإسم الناتج -وهنا الإختلاف عن ال action ID-. مثال: ال controller ID المسمى ب "post-comment" ستم معالجته ليصبح PostCommentController. +

+ + +##
الخلاصة
+ +

+ في هذا الموضوع، قمنا بالتعرف على ال controller وال view كأجزاء من MVC architectural pattern، كما قمنا بإنشاء action داخل controller موجود ليستقبل specific request ويتحكم فيه، وقمنا أيضا بإنشاء view لعرض المحتوى. في هذا المثال البسيط، لم نتطرق الى ال model، وقمنا فقط باستخدام ال data بشكل مباشر من خلال ال message parameter. +

+ +

+ كما تعرفنا أيضا على ال routes في ال Yii، والتي تعمل بدورها كجسر بين ال user request وال controller actions. +

+ +

+ في الموضوع القادم، ستتعلم كيف يمكنك إنشاء model وكيف يمكنك إنشاء صفحة جديدة تحتوي على Html form. +

diff --git a/docs/guide-ar/start-installation.md b/docs/guide-ar/start-installation.md new file mode 100644 index 00000000000..8a7dc2b14f0 --- /dev/null +++ b/docs/guide-ar/start-installation.md @@ -0,0 +1,301 @@ +#
تثبيت ال Yii
+ +

يمكنك تثبيت ال Yii بطريقتين ، الأولى باستخدام مدير الحزم Composer أو عن طريق تنزيل Archive File. الطريقة الأولى هي الطريقة المفضلة للعمل، ، لأنها تتيح لك تثبيت [extensions - ملحقات أو اضافات] جديدة، أو تحديث إطار العمل Yii ببساطة عن طريق تشغيل أمر واحد فقط. +

+ +

+ التثبيت الإفتراضي لل Yii ينتج عنه بنية تركيبة منظمة ومرتبة للمجلدات والملفات التي بداخلها، ويوفر هذا الكلام بعض المميزات التي يتم إضافتها وإنشائها بشكل تلقائي مثل صفحة تسجيل الدخول، ونموذج اتصل بنا...الخ، هذا الأمر سيشكل نقطة إنطلاق جيدة لبدء العمل على أي مشروع. +

+ +

+ في هذه الصفحة من التوثيق سنقوم بشرح ووصف كيف يمكن تثبيت إطار العمل Yii وبالتحديد Yii2 Basic Project Template. + هناك Template آخر موجود بإطار العمل Yii وهو Yii2 Advanced Project Template، وهو الأفضل للعمل وإنشاء المشاريع لفريق عمل برمجي، ولتطوير المشاريع متعددة الطبقات(multiple tires). +

+ +

+معلومة: قالب المشروع الأساسي (Basic) مناسب لتطوير 90% من تطبيقات الويب. ويختلف القالب المتقدم (Advanced Template) عن القالب الأساسي في كيفية تنظيم وهيكلة الشيفرة البرمجية. +اذا كنت جديدا في عالم تطوير تطبيقات الويب باستخدام ال Yii، فإننا نوصيك بقوة بأن تستخدم القالب الأساسي في بناء المشروع الخاص بك. +

+ + +##
تثبيت ال Yii من خلال (Composer)
+ +###
تثبيت ال Composer
+ +

+إن لم يكن لديك Composer مثبت مسبقا، فيمكنك السير بخطوات تثبيته من خلال الدخول الى هذا الرابط https://getcomposer.org/download/. +لتثبيت ال Composer في كل من نظامي Linux و Max OS X، يمكنك تنفيذ الأوامر التالية: +

+ +```bash +curl -sS https://getcomposer.org/installer | php +sudo mv composer.phar /usr/local/bin/composer +``` +

+ ولنظام ويندوز يمكنك تثبيت ال Composer-Setup.exe ومن ثم عمل run +

+ +

+يرجى الدخول الى Troubleshooting section of the Composer Documentation في حال واجهتك أي مشاكل متعلقة بال composer, وإذا كنت مستخدمًا جديدًا لل composer، ننصحك أيضًا بقراءة قسم الاستخدام الأساسي على الأقل من التوثيف الخاص بال composer. +

+ +

+ في هذا الدليل ، نفترض أنك قمت بتثبيت ال composer على مستوى جميع المشاريع (globally) بحيث تكون أوامر ال composer متاحة لجميع المشاريع من أي مكان. أما إذا كنت تستخدم ال composer.phar لمسار محدد فقط(local directory)، فيجب عليك ضبط الأومر وفقًا لذلك. + +إذا كان ال composer مثبتًا من قبل، فتأكد من استخدام إصدار حديث. يمكنك تحديث ال composer عن طريق تنفيذ الأمر التالي `composer self-update` +

+ +

+ ملاحظة مهمة: أثناء تثبيت ال Yii ، سيحتاج ال composer إلى طلب(request) الكثير من المعلومات من ال Github Api. يعتمد عدد الطلبات على عدد dependencies التي يمتلكها التطبيق الخاص بك، وقد يكون هذا العدد أكبر من الحد المسموح به من قبل ال Github Api (Github API rate limit). إذا وصلت الى الحد الأعلى المسموح به من الطلبات، فقد يطلب منك ال composer بيانات تسجيل الدخول إلى Github، وذلك للحصول على رمز (token) للدخول إلى Github Api. اذا كانت عمليات الإتصال سريعة، فقد تصل إلى هذا الحد(limit) قبل أن يتمكن ال composer من التعامل معه ، لذالك نوصي بتكوين رمز الدخول(access token) قبل تثبيت ال Yii. يرجى الرجوع إلى التوثيق الخاص بال Composer والإطلاع على التعليمات الخاصة Github API tokens للحصول على الإرشادات اللازمة للقيام بذلك. +

+ +###
تثبيت ال Yii
+ +

+ من خلال ال Composer، يمكنك الآن تثبيت ال Yii من خلال تنفيذ سطر الأوامر التالي داخل أي مسار يمكن الوصول اليه من قبل الويب +

+ +```bash +composer create-project --prefer-dist yiisoft/yii2-app-basic basic +``` +

+ سطر الأوامر السابق سيقوم بتثبيت أحدث نسخة مستقرة(stable) من إطار العمل Yii داخل مسار جديد اسمه basic، ويمكنك التعديل على سطر الأوامر السابق لتغيير اسم المشروع لأي اسم ترغب فيه. +

+ +

+معلومة: اذا واجهتك أي مشكلة عند تنفيذ السطر `composer create-project` فيمكنك الذهاب إلى قسم استكشاف الأخطاء في ال composer. +في معظم الأخطاء الشائعة، وعند حل المشكلة أو الخطأ، يمكنك إكمال التثبيت من خلال الدخول الى المسار `basic` ومن ثم تنفيذ الأمر التالي: `composer update`. +

+ +

+ تلميح: اذا كنت ترغب بتثبيت أحدث نسخة خاصة بالمطورين من ال Yii، فيمكنك ذلك من خلال إضافة الخيار stability وذلك من خلال سطر الأوامر التالي: +

+ +```bash + composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic +``` +

+ ملاحظة: نسخة المطورين من ال Yii يجب أن يتم إستخدامها للمواقع الإلكترونية التي لن تصدر كنسخة نهائية للمستخدم(Not for production) لأن ذلك يمكن أن يسبب بإيقاف المشروع أو الشيفرة البرمجية الخاصة بك. +

+ +###
تثبيت ال Yii من خلال ال Archive File
+-------------------------- + +

+يتضمن تثبيت Yii من ملف أرشيف ثلاث خطوات وهي: +

+
    +
  1. تثبت الملف من خلال الموقع الرسمي yiiframework.com.
  2. +
  3. قم بفك ضغط الملف الذي تم تنزيله إلى مجلد يمكن الوصول إليه عبر الويب.
  4. +
  5. قم بتعديل ملف `config / web.php` عن طريق إدخال secret key ل` cookieValidationKey` +(يتم ذلك تلقائيًا إذا قمت بتثبيت ال Yii باستخدام Composer):
  6. +
+ + ```php + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => 'enter your secret key here', + ``` + + +###
خيارات تثبيت أخرى
+-------------------------- + +

+توضح تعليمات التثبيت أعلاه كيفية تثبيت ال Yii ، والذي يقوم أيضًا بإنشاء تطبيق ويب أساسي(basic). +هذا النهج هو نقطة انطلاق جيدة لمعظم المشاريع، صغيرة كانت أو كبيرة. خصوصا اذا كنت قد بدأت تعلم ال Yii من وقت قريب. +

+لكن، هناك خيارات أخرى متاحة لتثبيت ال Yii وهي: +

+ +
    +
  • إذا كنت ترغب فقط في تثبيت ال core لإطار العمل Yii، وترغب ببناء المكونات الخاصة بإطار العمل كما ترغب أنت وبطريقتك أنت، يمكنك اتباع التعليمات كما هو موضح في هذه الصفحة Building Application from Scratch.
  • +
  • إذا كنت تريد البدء بتطبيق أكثر تعقيدًا وأكثر إحترافية، ويتناسب بشكل أفضل مع وجود فريق عمل تقني، +فأنت اذا سترغب بتثبيت ال Advanced Project Template +
  • +
+ + +###
تثبيت ال Assets
+-------------------------- + +

+ تعتمد ال Yii على حزم Bower و / أو NPM لتثبيت مكتبات ال (CSS و JavaScript). ويستخدم ال composer للحصول على هذه المكتبات ، مما يسمح بالحصول على إصدارات ال PHP و CSS / JavaScript في نفس الوقت. ويمكن تحقيق ذلك إما عن طريق استخدام asset-packagist.org أو من خلال ال composer asset plugin، يرجى الرجوع إلى Assets documentation لمزيد من التفاصيل. +

+قد ترغب في إدارة ال assets عبر ال native Bower / NPM أو استخدام ال CDN أو تجنب تثبيت ال assets بالكامل من حلال ال Composer ، ويمكن ذلك من خلال إضافة الأسطر التالية إلى "composer.json": +

+ +```json +"replace": { + "bower-asset/jquery": ">=1.11.0", + "bower-asset/inputmask": ">=3.2.0", + "bower-asset/punycode": ">=1.3.0", + "bower-asset/yii2-pjax": ">=2.0.0" +}, +``` + +

+ملاحظة: في حالة تجاوز تثبيت ال assets عبر ال Composer، فأنت المسؤول عن تثبيت ال assets وحل مشكلات التعارض بين الإصدارات والمكتبات المختلفة. وكن مستعدًا لعدم تناسق محتمل بين ملفات ال asstes والإضافات المختلفة. +

+ +###
التحقق من التثبيت
+-------------------------- + +

+ بعد الانتهاء من التثبيت، ستحتاج الى القيام بإعداد خادم الويب الخاص بك(your web server) (انظر القسم التالي) أو قم باستخدام built-in PHP web server عن طريق تنفيذ الأمر التالي داخل المسار web في المشروع الخاص بك: +

+ +```bash +php yii serve +``` + +

+ملاحظة: افتراضيًا ال HTTP-server يعمل على البورت 8080. ومع ذلك ، إذا كان هذا البورت قيد الاستخدام بالفعل أو كنت ترغب في تشغيل أكثر من تطبيق بهذه الطريقة، حينها سيلزمك تحديد البورت الذي يجب استخدامه. ما عليك سوى إضافة --port: +

+ +```bash +php yii serve --port=8888 +``` +

+ يمكنك استخدام الرابط الموجود في الأسفل للوصول الى تطبيق ال Yii الذي قمت بتثبيته وتنفيذ الأوامر السابقة عليه. +

+ +``` +http://localhost:8080/ +``` + +![Successful Installation of Yii](../guide/images/start-app-installed.png) + +

+ اذا كانت كل الإعدادات السابقة تعمل بشكل صحيح، فيجب أن ترى الصورة الموجودة بالأعلى "Congratulations!" على المتصفح. إذا لم يكن كذلك، يرجى التحقق مما إذا كان تثبيت الPHP الخاص بك متوافق مع متطلبات ال Yii. يمكنك التحقق من ذلك باستخدام أحد الأساليب التالية: +

+ +
    +
  • قم بنسخ الملف
    /requirements.php
    الى المسار
    /web/requirements.php
    بحيث يمكنك الوصول الى الصفحة من خلال الرابط التالي:
    http://localhost/requirements.php
  • +
  • قم بتنفيذ الأوامر التالية:
    +        cd basic
    +        php requirements.php
  • +
+ +

+ يجب عليك أن تقوم بتثبيت وإعداد ال PHP الخاص بك بحيث تلبي الحد الأدنى من متطلبات ال Yii. الأهم من ذلك يجب أن يكون الإصدار الخاص بال PHP أعلى أو يساوي 5.4. من الناحية المثالية أحدث إصدار يعمل مع ال Yii هو ال PHP 7. يجب عليك أيضًا تثبيت ال PDO PHP Extension. +

+ + +###
إعداد ال Web Servers
+----------------------- + +

+معلومة: يمكنك تخطي هذا الجزء الآن إذا كنت تختبر فقط إطار العمل Yii دون أي نية لنشر هذا التطبيق على الويب(بدون رفع التطبيق على production server). +

+ +

+ يجب أن يعمل التطبيق الذي تم تثبيته وفقًا للتعليمات المذكورة أعلاه مع أي من الخوادم ال Apache HTTP أو ال Nginx HTTP في كل من أنظمة التشغيل Windows, Mac OS X أو Linux ممن لديها إصدار أعلى أو يساوي PHP 5.4، كما أن ال Yii 2.0 متوافق مع ال Facebook HHVM، لكن، يجب أن تأخذ بعين الإعتبار أن ال HHVM يسلك في بعض الأحيان بطريقة مختلفة عن ال Native PHP، لذلك يجب أن تأخذ عناية إضافية عندما تعمل على ال HHVM. +

+ +

+ على ال production server، قد ترغب في إعداد خادم الويب الخاص بك بحيث يمكن الوصول إلى التطبيق +الخاص بك عبر ال URL التالي http: // www.example.com / index.php بدلاً من http: // www.example.com / basic / web / index.php. هذا الكلام يتطلب إنشاء إعداد يقوم بتوجيه ال document root الموجود على ال web server الى مجلد ال basic/web، كما قد ترغب أيضا بإخفاء ال index.php من ال URL كما هو موضح في ال Routing and URL Creation. في هذا الموضوع ستتعلم كيف يمكنك إعداد ال Apache أو ال Nginx server لتحقيق هذه الأهداف. +

+ +

+ معلومة: من خلال تعيين ال basic/web ك document root، فإنك بذلك تمنع أيضًا المستخدمين النهائيين من الوصول الى الشيفرة البرمجية الخاصة بالتطبيق الخاص بك، وتمنعهم من الوصول الى الملفات الحساسة والمهمة والمخزنة في sibling directories من basic/web، ويعبر رفض الوصول الى المجلدات الأخرى تحسينا أمنيا مهما، يساعد في الحفاظ على مستوى أعلى من الحماية. +

+ +

+معلومة: إذا كان سيتم تشغيل التطبيق الخاص بك في بيئة استضافة مشتركة(shared hosting) حيث ليس لديك الصلاحية لتعديل الإعدادات الخاصة بال web server، ستحتاج حينها الى تعديل في البنية الخاصة بالمشروع للحصول على أفضل أمان ممكن. يرجى الرجوع إلى Shared Hosting Environment لمزيد من المعلومات. +

+ +

+ معلومة: إذا كنت تقوم بتشغيل تطبيق ال Yii بوجود ال proxy، فقد تحتاج إلى إعداد التطبيق ليكون ضمن ال trusted proxies and header. +

+ +###
الإعدادات الموصى بها لل Apache
+----------------------- + +

+ استخدم الإعدادات التالية في ملف ال httpd.conf في Apache أو ضمن إعدادات ال virtual host. + ملاحظة: يجب عليك استبدال المسار التالي path / to / basic / web بالمسار الفعلي للتطبيق الخاص بك وصولا الى ال basic / web. +

+ +```apache +# Set document root to be "basic/web" +DocumentRoot "path/to/basic/web" + + + # use mod_rewrite for pretty URL support + 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 + RewriteRule . index.php + + # if $showScriptName is false in UrlManager, do not allow accessing URLs with script name + RewriteRule ^index.php/ - [L,R=404] + + # ...other settings... + +``` + + +###
الإعدادات الموصى بها لل Nginx
+----------------------- + +

+ لاستخدام Nginx، يجب تثبيت PHP على أنه FPM SAPI، ويمكنك استخدام إعدادات ال Nginx التالية، مع الإنتباه على استبدال المسار من path / to / basic / web الى المسار الفعلي وصولا إلى basic / web بالإضافة الى إستبدال mysite.test إلى ال hostname الخاص بالتطبيق. +

+ + +```nginx +server { + charset utf-8; + client_max_body_size 128M; + + listen 80; ## listen for ipv4 + #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 + + server_name mysite.test; + root /path/to/basic/web; + index index.php; + + access_log /path/to/basic/log/access.log; + error_log /path/to/basic/log/error.log; + + location / { + # Redirect everything that isn't a real file to index.php + try_files $uri $uri/ /index.php$is_args$args; + } + + # uncomment to avoid processing of calls to non-existing static files by Yii + #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ { + # try_files $uri =404; + #} + #error_page 404 /404.html; + + # deny accessing php files for the /assets directory + location ~ ^/assets/.*\.php$ { + deny all; + } + + location ~ \.php$ { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_pass 127.0.0.1:9000; + #fastcgi_pass unix:/var/run/php5-fpm.sock; + try_files $uri =404; + } + + location ~* /\. { + deny all; + } +} +``` +

+ عند استخدامك لهذا الإعداد، يجب عليك أيضًا تعيين cgi.fix_pathinfo = 0 في ملف php.ini + من أجل تجنب العديد من طلبات ال stat() الغير الضرورية للنظام. +

+ +

+ لاحظ أيضًا أنه عند تشغيل خادم HTTPS، تحتاج إلى إضافة fastcgi_param HTTPS on; +بحيث يمكنك إكتشاف إذا ما كان الاتصال آمنًا أم لا. +

diff --git a/docs/guide-ar/start-looking-ahead.md b/docs/guide-ar/start-looking-ahead.md new file mode 100644 index 00000000000..8fccb9caa74 --- /dev/null +++ b/docs/guide-ar/start-looking-ahead.md @@ -0,0 +1,36 @@ +#
ماذا الآن - الخطوة القادمة
+ +

+إذا قمت بقرائة الفصل الخاص ب "البداية من هنا"، فأنت الآن قادر على بناء تطبيق Yii متكامل، لقد تعلمت كيف يمكنك تنفيذ وإستخدام أكثر الخصائص والمميزات المشتركة، مثل جلب البيانات من قاعدة البيانات، وأخذ البيانات من المستخدمين، ومن ثم عرضها، كما تعلمت كيف يمكنك تقسيم البيانات الى صفحات، وقمنا باستخدام ال Gii وتعلمنا كيف يمكننا إنشاء شيفرة برمجية من خلاله بشكل تلقائي، ومن الممارسة تعلمنا أن إنشاء الشيفرة البرمجية من خلال ال Gii يجعل من عملية تطوير المواقع والوظائف المطلوبة أمرا بسيطا وسهلا للغابة، كل ما عليك القيام به هو تعبئة ال forms. +

+ +

+ في هذا الجزء من التوثيق سنعرض ملخص للمصادر المتاحة لل Yii، والتي ستساعدك في تحسين إنتاجيتك عند إستخدامك لبيئة العمل Yii. +

+ +
    +
  • + التوثيق +
      +
    • The Definitive Guide - الدليل الشامل: كما يشير الإسم، فإن هذا الدليل يحدد آلية عمل ال Yii بدقة عالية، ويوفر إرشادات حول كيفية إستخدام ال Yii، هذا الجزء الأكثر أهمية في ال Yii، والذي يجب عليك قرائته قبل كتابة أي Yii code (ملاحظة: جزء البداية من هنا، والذي قمنا بدراسته هو أحد هذه الأجزاء، ومن أهمها للبدء بإنشاء التطبيقات من خلال ال Yii).
    • +
    • The Class Reference - المرجع الخاص بال Class في هذا الجزء يتم تحديد الية إستخدام كل Class يقدمه ال Yii، في العادة يتم إستخدام هذا المرجع عند كتابة شيفرة برمجية وأنت ترغب في فهم آلية العمل ل Class معين، أو Method, او فهم Proporty معينة...الخ، من الأفضل إستخدام المرجع الخاص بال Class فقط عند فهم آلية العمل لل Yii.
    • +
    • The Wiki Articles - مقالات الويكي مقالات الويكي هي مجموعة من الخبرات العملية للمستخدمين، تمت كتابتها ونشرها على شكل مقالات لمشاركة الخبرات، ومعظم هذه الكتابات تكون مثل الوصفات الخاصة بالطبخ، موجودة لخدمة هدف معين، وحل مشكلة محددة باستخدام ال Yii، وبالرغم من أن هذه الكتابات قد لا تكون بجودة ودقة الدليل الشامل، الا أنها قد تغطي مواضيع أكثر، وتطرح أيضا حلولا مباشرة للإستخدام.
    • +
    • الكتب
    • +
    +
  • +
  • Extensions - الملحقات: تفتخر ال Yii بوجود مكتبة ضخمة من الملحقات التي تمت برمجتها وإضافتها من قبل المستخدمين المتطوعين الذين شاركوا أعمالهم وطورها لتجعل مهمة المطورين الآخرين أسهل وأسرع في تطوير التطبيفات المبنية بواسطة ال Yii.
  • +
  • + المجتمع + +
  • +
diff --git a/docs/guide-ar/start-prerequisites.md b/docs/guide-ar/start-prerequisites.md new file mode 100644 index 00000000000..bbafc6e4611 --- /dev/null +++ b/docs/guide-ar/start-prerequisites.md @@ -0,0 +1,25 @@ +#
ماذا يجب أن تعرف قبل البدء بال Yii
+ +

+ منحنى التعلم الخاص بال Yii ليس حادًا مثل أطر PHP الأخرى، ولكن لا يزال هناك بعض الأشياء التي يجب أن تتعلمها قبل البدء بـال Yii. +

+ +##
PHP
+ +

+ ال Yii هو إطار عمل PHP، لذا تأكد من قراءة وفهم المرجع الرسمي الخاص باللغة (http://php.net/manual/en/langref.php). عند البدء بتطوير المشاريع أو التطبيقات باستخدام ال Yii ، ستكتب التعليمات البرمجية بطريقة كائنية التوجه OOP، لذا تأكد من أنك على دراية بـمفاهيم ال OOP (https://secure.php.net/manual/en/language.oop5.basic.php) وكذلك ال namespaces (https://secure.php.net/manual/en/language.namespaces.php). +

+ +##
البرمجة كائنية التوجه object oriented programming
+ +

+ كمبرمج أو مطور يرغب بالعمل على ال Yii، يجب عليك أن تمتلك المعرفة الأساسية للبرمجة كائنية التوجه OOP. إذا لم تكن على دراية بها ، فيمكنك تعلم ذلك من خلال واحدة من هذه الدورات المنتشرة مثل (https://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762).
+ملاحظة: كلما زاد تعقيد التطبيق أو المشروع الذي تعمل عليه، كلما احتجت الى مستوى أعلى وإحترافي أكثر من مفاهيم ال OOP لحل وإدارة التعقديات التي ستترب على مثل هذه المشاريع. +

+ +##
Command line and composer
+ +

تستخدم ال Yii بشكل كبير de-facto standard PHP package manager، ال Composer (https://getcomposer.org/)، لذلك تأكد من قرائتك وفهمك لهذا الموضوع قبل أن تبدء. بالإضافة الى ذلك إذا لم تكن على دراية باستخدام سطر الأوامر (command line) ، فقد حان الوقت لبدء المحاولة. بمجرد تعلم الأساسيات ، لن ترغب في العمل بدون إستخدام سطر الأوامر.
+ال composer: ويترجم حرفيا الى كلمة "الملحن"، وهي عبارة عن أداة لإدارة المشاريع البرمجية والتي تسمح لك بتحديث وتنزيل المكتبات البرمجية المطلوبة للمشروع الخاص بك. +

+ diff --git a/docs/guide-ar/start-workflow.md b/docs/guide-ar/start-workflow.md new file mode 100644 index 00000000000..6bdd9f11e40 --- /dev/null +++ b/docs/guide-ar/start-workflow.md @@ -0,0 +1,115 @@ +#
تشغيل التطبيقات
+ +

+بعد تثبيت ال Yii، سيكون لديك تطبيق Yii جاهز للعمل عليه ويمكن الوصول إليه عبر +الرابط التالي: http://hostname/basic/web/index.php أو http://hostname/index.php إعتمادا على الإعدادات +الخاصة بك (إعدادت ال web server). في هذا الجزء سنستعرض الوظائف ال built-in الموجودة في التطبيق الإفتراضي لإطار العمل Yii، وكيف يقوم بتنظيم الشيفرة البرمجية، وكيف يعالج (handling) هذا التطبيق الطلبات (requests) بشكل عام. +

+ +

+ معلومة: من أجل تبسيط الطرح، ومن خلال هذا البرنامج التعليمي " Getting Started - البداية من هنا"، من المفترض أنك قمت بتعيين basic/web ك document root لل Web server، وقد قمت أيضا بإعداد ال Url الذي يسمح لك بالوصول الى التطبيق المثبت من خلاله ليكون على الشكل التالي: http://hostname/index.php أو ما شابه ذلك. +اذا لم تقم بذلك، ولتلبية إحتياجاتك في هذا البرنامج التعليمي، يرجى ضبط ال Url كما هو موضح في هذه الصفحة. +يمكنك معرفة الضبط الخاص بال Web server من هنا: تثبيت ال Yii +

+ +

+ملاحظة: بخلاف إطار العمل نفسه(Yii framework)، بعد تثبيت ال template الخاص بالمشروع، يكون كل شيء في هذا التطبيق يخصك أنت، بحيث تملك الحرية في إضافة أو حذف أو تعديل كل ما تحتاج اليه. +

+ + +##
خصائص / وظائف التطبيق المثبت - Functionality
+ +

+ يحتوي ال Basic ِApplication Template الذي قمنا بتثبيته على أربع صفحات: +

+ +
    +
  • الصفحة الرئيسية(Homepage): يتم عرض هذه الصفحة من خلال الرابط التالي http://hostname/index.php
  • +
  • صفحة من نحن(About)
  • +
  • صفحة اتصل بنا (Contact): في هذه الصفحة يتم عرض form يسمح للأعشاء بالإتصال بك من خلال البريد الإلكتروني.
  • +
  • صفحة تسجيل الدخول (Login): في هذه الصفحة يتم عرض form يسمح للأعضاء بالحصول على الإذن لإستخدام الخصائص التي لا يجوز لغيرهم من الوصول اليها، قم بتجربة تسجيل الدخول من خلال استخدام admin/admin ولاحظ أن كلمة "Login" ستختفي من القائمة الرئيسية وستظهر محلها الكلمة "Logout"
  • +
+ +

+هذه الصفحات تشترك بامتلاكها common header and footer -الترويسة أعلى الصفحة، والذيل أسفل الصفحة-. ويحتوي ال header على القائمة الرئيسية (main menu) والتي بدورها تسمح لك بالتنقل بين الصفحات المختلفة. +

+ +

+ أيضا، يجب عليك أن تنظر الى ال toolbar الموجود في أسفل نافذة المتصفح. ال debugger tool هذه تعتبر كأداة مفيدة مقدمة من ال Yii لتسجيل وعرض الكثير من المعلومات وتصحيح الأخطاء، مثل log messages, response statuses, the database queries run وما إلى ذلك. +

+ +

+ بالإضافة إلى ال web application، يوجد هناك "console script" يسمى ب yii، والذي ستجده في المسار الرئيسي للتطبيق. هذا السكربت يمكن استخدامه لتشغيل المهام التي تعمل في الخفاء (background) أو لتنفيذ مهام الصيانة (ال maintenance).
ستجد الوصف الخاص بهذا السكربت + داخل هذه الصفحة Console Application Section. +

+ + + +##
هيكلية التطبيق - Application Structure + +

+ أكثر المسارات والملفات أهمية الموجودة داخل التطبيق (بافتراض أن ال application's root directory هو basic) هي: +

+ +``` +basic/ application base path + composer.json used by Composer, describes package information + config/ contains application and other configurations + console.php the console application configuration + web.php the Web application configuration + commands/ contains console command classes + controllers/ contains controller classes + models/ contains model classes + runtime/ contains files generated by Yii during runtime, such as logs and cache files + vendor/ contains the installed Composer packages, including the Yii framework itself + views/ contains view files + web/ application Web root, contains Web accessible files + assets/ contains published asset files (javascript and css) by Yii + index.php the entry (or bootstrap) script for the application + yii the Yii console command execution script +``` + +

+بشكل عام، يمكن تقسيم الملفات داخل التطبيق إلى نوعين: الاول تجده تحت المسار التالي: basic/web +وبنائا على ذلك، فإنه من الممكن الوصول إلى النوع الأول مباشرة عبر ال HTTP (أي من خلال المتصفح) ، بينما لا يمكن أن يكون ذلك للنوع الثاني. +

+ +

+ يعتمد ال Yii على إستخدام ال MVC، وال MVC هو أحد ال Architectural Pattern، وهي اختصار ل model-view-controller، +هذا الأسلوب ينعكس في تنظيم المسارات الخاصة بالملفات كما في الشكل أعلاه. يحتوي المسار models على جميع الكلاس (model classes) ، ويحتوي مسار ال views على جميع الصفحات التي ستستخدم في العرض (view scripts)، ويحتوي مسار الcontrollers على + جميع (controller classes) +

+ +

+ يوضح المخطط التالي ال static structure للتطبيق. +

+ +![Static Structure of Application](../guide/images/application-structure.png) + +

+ يحتوي كل تطبيق على نص برمجي يستخدم للدخول الى التطبيق (كبوابة بعدها يظهر التطبيق للناظر)، ويسمى هذا الجزء بال entry script، وهو يمثل الصفحة web/index.php، ويعد هذا المدخل النص البرمجي الوحيد الذي يمكن الوصول إليه من خلال ال PHP في التطبيق، ويعمل هذا ال entry script على أخذ ال request ومن ثم إنشاء instance خاص بالتطبيق ليستطيع التعامل معه (التعامل مع التطبيق ومكوناته). + يقوم التطبيق على معالجة ال request بمساعدة من ال components، ومن ثم بقوم التطبيق بإرسال ال request الى عناصر ال MVC، كما يتم استخدام ال Widgets في ال views للمساعدة في إنشاء العناصر المعقدة والمتغيرة (Complex & Dynamic user interface) لواجهة المستخدم. +

+ + +##
دورة الحياة الخاصة بال request + +

+يوضح المخطط التالي كيفية معالجة التطبيق ل request معين. +

+ +![Request Lifecycle](../guide/images/request-lifecycle.png) + +
    +
  1. يقوم المستخدم بعمل request لل entry script web/index.php.
  2. +
  3. يقوم ال entry script على جلب الإعدادات الخاصة بالتطبيق ومن ثم إنشاء ال instance الخاص بالتطبيق ليستطيع التحكم ب request وإدارتها.
  4. +
  5. يقوم التطبيق بمعالجة ال requested route بمساعدة من ال request application component.
  6. +
  7. يقوم التطبيق على إنشاء instance من ال controller للتحكم بال request.
  8. +
  9. يقوم ال controller على إنشاء action instance مع مجموعة من الفلاتر(المرشحات) الخاصة بهذا ال action.
  10. +
  11. في حالة فشل أي فلتر، يتم إلغاء الإجراء.
  12. +
  13. في حال نجاح جميع الفلاتر ، يتم تنفيذ الإجراء.
  14. +
  15. يقوم ال action بجلب بعض البيانات الخاصة بال models, وفي الغالب ستكون من قاعدة البيانات إن أمكن ذلك.
  16. +
  17. سيقوم ال action بجلب ال view ليقوم بتقديم البيانات التي تم جلبها لل view.
  18. +
  19. عملية الجلب السابقة ستقوم على إرجاع النتائج الى response application component
  20. +
  21. بعد ذلك سيقوم ال response component بإرسال النتيجة النهائية الى المتصفح الخاص بالمستخدم.
  22. +
diff --git a/docs/guide-es/README.md b/docs/guide-es/README.md index 5929f389057..568694cde5a 100644 --- a/docs/guide-es/README.md +++ b/docs/guide-es/README.md @@ -18,6 +18,7 @@ Introducción Primeros pasos -------------- +* [Qué necesita saber](start-prerequisites.md) * [Instalar Yii](start-installation.md) * [Funcionamiento de aplicaciones](start-workflow.md) * [Hola a todos](start-hello.md) diff --git a/docs/guide-es/intro-yii.md b/docs/guide-es/intro-yii.md index 495aba0eb4c..d3a4e89e327 100644 --- a/docs/guide-es/intro-yii.md +++ b/docs/guide-es/intro-yii.md @@ -2,8 +2,8 @@ ============ Yii es un framework de PHP de alto rendimiento, basado en componentes para desarrollar aplicaciones web -modernas en poco tiempo. El nombre Yii significa "simple y evolutivo" en chino. También se puede considerar como un acrónimo -de _**Yes It Is**_ (que en inglés significa _**Sí, eso es**_)! +modernas en poco tiempo. El nombre Yii significa "simple y evolutivo" en chino. También se puede considerar como el acrónimo +de _**Yes It Is**_ (que en inglés significa _**Sí, lo es**_)! ¿En qué es mejor Yii? @@ -11,21 +11,29 @@ de _**Yes It Is**_ (que en inglés significa _**Sí, eso es**_)! Yii es un framework genérico de programación web, lo que significa que se puede utilizar para desarrollar todo tipo de aplicaciones web en PHP. Debido a su arquitectura basada en componentes y a su sofisticada compatibilidad de caché, es especialmente apropiado para el desarrollo -de aplicaciones de gran envergadura, como portales, foros, sistemas de gestión de contenidos (CMS), proyectos de comercio electrónico, -servicios web compatibles con la arquitectura REST y muchas más. +de aplicaciones de gran envergadura, como páginas web, foros, sistemas de gestión de contenidos (CMS), proyectos de comercio electrónico, +servicios web compatibles con la arquitectura REST y muchos más. + ¿Cómo se compara Yii con otros frameworks? -------------------------------------- -Si estás familiarizado con otros framework, puedes apreciar como se compara Yii con ellos: - -- Como la mayoría de los framework de PHP, Yii implementa el patrón de diseño MVC (Modelo-Vista-Controlador) y promueve la organización de código basada en este patrón. -- La filosofía de Yii consiste en escribir el código de manera simple y elegante, sin sobrediseñar nunca por el mero hecho de seguir un patrón de diseño determinado. -- Yii es un framework completo que provee muchas características probadas y listas para usar, como los constructores de consultas y la clase ActiveRecord para las bases de datos relacionales y NoSQL, la compatibilidad con la arquitectura REST para desarrollar API, la compatibilidad de caché en varios niveles y muchas más. -- Yii es extremadamente extensible. Puedes personalizar o reemplazar prácticamente cualquier pieza de código de base, como se puede también aprovechar su sólida arquitectura de extensiones para utilizar o desarrollar extensiones distribuibles. +Si estás ya familiarizado con otros framework, puedes apreciar como se compara Yii con ellos: + +- Como la mayoría de los framework de PHP, Yii implementa el patrón de diseño MVC (Modelo-Vista-Controlador) y + promueve la organización de código basada en este patrón. +- La filosofía de Yii consiste en escribir el código de manera simple y elegante, sin sobrediseñar nunca por el + mero hecho de seguir un patrón de diseño determinado. +- Yii es un framework completo (full stack) que provee muchas características probadas y listas para usar, como los +constructores de consultas y la clase ActiveRecord para las bases de datos relacionales y NoSQL, +la compatibilidad con la arquitectura REST para desarrollar API, la compatibilidad de caché en varios niveles +y muchas más. +- Yii es extremadamente extensible. Puedes personalizar o reemplazar prácticamente cualquier pieza de código de base, +como se puede también aprovechar su sólida arquitectura de extensiones para utilizar o desarrollar extensiones distribuibles. - El alto rendimiento es siempre la meta principal de Yii. -Yii no es un proyecto de un sola persona, detrás de Yii hay un [sólido equipo de desarrollo][about_yii], así como una gran comunidad en la que numerosos profesionales contribuyen constantemente a su desarrollo. +Yii no es un proyecto de un sola persona, detrás de Yii hay un [sólido equipo de desarrollo](http://www.yiiframework.com/team/), +así como una gran comunidad en la que numerosos profesionales contribuyen constantemente a su desarrollo. El equipo de desarrollo de Yii se mantiene atento a las últimas tendencias de desarrollo web, así como a las mejores prácticas y características de otros frameworks y proyectos. Las buenas prácticas y características más relevantes de otros proyectos se incorporan regularmente a la base del framework y se exponen a través de interfaces simples y elegantes. @@ -40,11 +48,11 @@ La versión 2.0 representa la actual generación del framework y su desarrollo r Esta guía está basada principalmente en la versión 2.0. del framework. -Requisitos ------------ +Requisitos y Prerequisitos +-------------------------- -Yii 2.0 requiere PHP 5.4.0 o una versión posterior. Se pueden encontrar requisitos más detallados de características individuales -ejecutando el script de comprobación incluido en cada release de Yii. +Yii 2.0 requiere PHP 5.4.0 o una versión posterior y corre de mejor manera en la última versión de PHP 7. Se pueden encontrar requisitos más detallados de características individuales +ejecutando el script de comprobación incluido en cada lanzamiento de Yii. Para utilizar Yii se requieren conocimientos básicos de programación orientada a objetos (POO), porque el framework Yii se basa íntegramente en esta tecnología. Yii 2.0 hace uso también de las últimas características de PHP, como [namespaces](http://www.php.net/manual/es/language.namespaces.php) diff --git a/docs/guide-es/output-data-providers.md b/docs/guide-es/output-data-providers.md new file mode 100644 index 00000000000..0802ee0aa34 --- /dev/null +++ b/docs/guide-es/output-data-providers.md @@ -0,0 +1,421 @@ +Proveedores de datos +==================== + +En las secciones sobre [paginación](output-pagination.md) y [ordenación](output-sorting.md) se +describe como permitir a los usuarios finales elegir que se muestre una página de datos en +particular, y ordenar los datos por algunas columnas. Como la tarea de paginar y ordenar datos +es muy común, Yii proporciona un conjunto de clases *proveedoras de datos* para encapsularla. + +Un proveedor de datos es una clase que implementa la interfaz [[yii\data\DataProviderInterface]]. +Básicamente se encarga de obtener datos paginados y ordenados. Normalmente se usa junto con +[_widgets_ de datos](output-data-widgets.md) para que los usuarios finales puedan paginar y +ordenar datos de forma interactiva. + +Yii incluye las siguientes clases proveedoras de datos: + +* [[yii\data\ActiveDataProvider]]: usa [[yii\db\Query]] o [[yii\db\ActiveQuery]] para consultar datos de bases de datos y devolverlos como _arrays_ o instancias [Active Record](db-active-record.md). +* [[yii\data\SqlDataProvider]]: ejecuta una sentencia SQL y devuelve los datos de la base de datos como _arrays_. +* [[yii\data\ArrayDataProvider]]: toma un _array_ grande y devuelve una rodaja de él basándose en las especificaciones de paginación y ordenación. + +El uso de todos estos proveedores de datos comparte el siguiente patrón común: + +```php +// Crear el proveedor de datos configurando sus propiedades de paginación y ordenación +$provider = new XyzDataProvider([ + 'pagination' => [...], + 'sort' => [...], +]); + +// Obtener los datos paginados y ordenados +$models = $provider->getModels(); + +// Obtener el número de elementos de la página actual +$count = $provider->getCount(); + +// Obtener el número total de elementos entre todas las páginas +$totalCount = $provider->getTotalCount(); +``` + +Se puede especificar los comportamientos de paginación y ordenación de un proveedor de datos +configurando sus propiedades [[yii\data\BaseDataProvider::pagination|pagination]] y +[[yii\data\BaseDataProvider::sort|sort]], que corresponden a las configuraciones para +[[yii\data\Pagination]] y [[yii\data\Sort]] respectivamente. También se pueden configurar a +`false` para inhabilitar las funciones de paginación y/u ordenación. + +Los [_widgets_ de datos](output-data-widgets.md), como [[yii\grid\GridView]], tienen una +propiedad llamada `dataProvider` que puede tomar una instancia de un proveedor de datos y +mostrar los datos que proporciona. Por ejemplo, + +```php +echo yii\grid\GridView::widget([ + 'dataProvider' => $dataProvider, +]); +``` + +Estos proveedores de datos varían principalmente en la manera en que se especifica la fuente de +datos. En las siguientes secciones se explica el uso detallado de cada uno de estos proveedores +de datos. + + +## Proveedor de datos activo + +Para usar [[yii\data\ActiveDataProvider]], hay que configurar su propiedad +[[yii\data\ActiveDataProvider::query|query]]. +Puede tomar un objeto [[yii\db\Query] o [[yii\db\ActiveQuery]]. En el primer caso, los datos +devueltos serán _arrays_. En el segundo, los datos devueltos pueden ser _arrays_ o instancias de +[Active Record](db-active-record.md). Por ejemplo: + + +```php +use yii\data\ActiveDataProvider; + +$query = Post::find()->where(['state_id' => 1]); + +$provider = new ActiveDataProvider([ + 'query' => $query, + 'pagination' => [ + 'pageSize' => 10, + ], + 'sort' => [ + 'defaultOrder' => [ + 'created_at' => SORT_DESC, + 'title' => SORT_ASC, + ] + ], +]); + +// Devuelve un array de objetos Post +$posts = $provider->getModels(); +``` + +En el ejemplo anterior, si `$query` se crea el siguiente código, el proveedor de datos +devolverá _arrays_ en bruto. + +```php +use yii\db\Query; + +$query = (new Query())->from('post')->where(['state' => 1]); +``` + +> Note: Si una consulta ya tiene la cláusula `orderBy`, las nuevas instrucciones de ordenación + dadas por los usuarios finales (mediante la configuración de `sort`) se añadirán a la cláusula + `orderBy` previa. Las cláusulas `limit` y `offset` que pueda haber se sobrescribirán por la + petición de paginación de los usuarios finales (mediante la configuración de `pagination`). + +Por omisión, [[yii\data\ActiveDataProvider]] usa el componente `db` de la aplicación como +conexión con la base de datos. Se puede indicar una conexión con base de datos diferente +configurando la propiedad [[yii\data\ActiveDataProvider::db]]. + + +## Proveedor de datos SQL + +[[yii\data\SqlDataProvider]] funciona con una sentencia SQL en bruto, que se usa para obtener +los datos requeridos. +Basándose en las especificaciones de [[yii\data\SqlDataProvider::sort|sort]] y +[[yii\data\SqlDataProvider::pagination|pagination]], el proveedor ajustará las cláusulas +`ORDER BY` y `LIMIT` de la sentencia SQL acordemente para obtener sólo la página de datos +solicitados en el orden deseado. + +Para usar [[yii\data\SqlDataProvider]], hay que especificar las propiedades +[[yii\data\SqlDataProvider::sql|sql]] y [[yii\data\SqlDataProvider::totalCount|totalCount]]. +Por ejemplo: + +```php +use yii\data\SqlDataProvider; + +$count = Yii::$app->db->createCommand(' + SELECT COUNT(*) FROM post WHERE status=:status +', [':status' => 1])->queryScalar(); + +$provider = new SqlDataProvider([ + 'sql' => 'SELECT * FROM post WHERE status=:status', + 'params' => [':status' => 1], + 'totalCount' => $count, + 'pagination' => [ + 'pageSize' => 10, + ], + 'sort' => [ + 'attributes' => [ + 'title', + 'view_count', + 'created_at', + ], + ], +]); + +// Devuelve un array de filas de datos +$models = $provider->getModels(); +``` + +> Info: La propiedad [[yii\data\SqlDataProvider::totalCount|totalCount]] se requiere sólo si se + necesita paginar los datos. Esto es porque el proveedor modificará la sentencia SQL + especificada vía [[yii\data\SqlDataProvider::sql|sql]] para que devuelva sólo la pagina de + datos solicitada. El proveedor sigue necesitando saber el número total de elementos de datos + para calcular correctamente el número de páginas. + + +## Proveedor de datos de _arrays_ + +Se recomienda usar [[yii\data\ArrayDataProvider]] cuando se trabaja con un _array_ grande. +El proveedor permite devolver una página de los datos del _array_ ordenados por una o varias +columnas. Para usar [[yii\data\ArrayDataProvider]], hay que especificar la propiedad +[[yii\data\ArrayDataProvider::allModels|allModels]] como el _array_ grande. Los elementos +del _array_ grande pueden ser _arrays_ asociativos (por ejemplo resultados de consultas de +[DAO](db-dao.md) u objetos (por ejemplo instancias de [Active Record](db-active-record.md). +Por ejemplo: + +```php +use yii\data\ArrayDataProvider; + +$data = [ + ['id' => 1, 'name' => 'name 1', ...], + ['id' => 2, 'name' => 'name 2', ...], + ... + ['id' => 100, 'name' => 'name 100', ...], +]; + +$provider = new ArrayDataProvider([ + 'allModels' => $data, + 'pagination' => [ + 'pageSize' => 10, + ], + 'sort' => [ + 'attributes' => ['id', 'name'], + ], +]); + +// Obtener las filas de la página solicitada +$rows = $provider->getModels(); +``` + +> Note: En comparación con [Active Data Provider](#active-data-provider) y + [SQL Data Provider](#sql-data-provider), Array Data Provider es menos eficiente porque + requiere cargar *todos* los datos en memoria. + + +## Trabajar con las claves de los datos + +Al utilizar los elementos de datos devueltos por un proveedor de datos, con frecuencia +necesita identificar cada elemento de datos con una clave única. +Por ejemplo, si los elementos de datos representan información de los clientes, puede querer +usar el ID de cliente como la clave de cada conjunto de datos de un cliente. +Los proveedores de datos pueden devolver una lista de estas claves correspondientes a los +elementos de datos devueltos por [[yii\data\DataProviderInterface::getModels()]]. +Por ejemplo: + +```php +use yii\data\ActiveDataProvider; + +$query = Post::find()->where(['status' => 1]); + +$provider = new ActiveDataProvider([ + 'query' => $query, +]); + +// Devuelve un array de objetos Post +$posts = $provider->getModels(); + +// Devuelve los valores de las claves primarias correspondientes a $posts +$ids = $provider->getKeys(); +``` + +En el ejemplo superior, como se le proporciona a [[yii\data\ActiveDataProvider]] un objeto +[[yii\db\ActiveQuery]], es lo suficientemente inteligente como para devolver los valores de +las claves primarias como las claves. También puede indicar explícitamente cómo se deben +calcular los valores de la clave configurando [[yii\data\ActiveDataProvider::key]] con un +nombre de columna o un invocable que calcule los valores de la clave. Por ejemplo: + +```php +// Utiliza la columna «slug» como valores de la clave +$provider = new ActiveDataProvider([ + 'query' => Post::find(), + 'key' => 'slug', +]); + +// Utiliza el resultado de md5(id) como valores de la clave +$provider = new ActiveDataProvider([ + 'query' => Post::find(), + 'key' => function ($model) { + return md5($model->id); + } +]); +``` + + +## Creación de un proveedor de datos personalizado + +Para crear su propio proveedor de datos personalizado, debe implementar +[[yii\data\DataProviderInterface]]. +Una manera más fácil es extender [[yii\data\BaseDataProvider]], que le permite centrarse +en la lógica central del proveedor de datos. En particular, esencialmente necesita +implementar los siguientes métodos: + +- [[yii\data\BaseDataProvider::prepareModels()|prepareModels()]]: prepara los modelos + de datos que estarán disponibles en la página actual y los devuelve como un _array_. +- [[yii\data\BaseDataProvider::prepareKeys()|prepareKeys()]]: acepta un _array_ de + modelos de datos disponibles actualmente y devuelve las claves asociadas a ellos. +- [[yii\data\BaseDataProvider::prepareTotalCount()|prepareTotalCount]]: devuelve un valor + que indica el número total de modelos de datos en el proveedor de datos. + +Debajo se muestra un ejemplo de un proveedor de datos que lee datos CSV eficientemente: + +```php +fileObject = new SplFileObject($this->filename); + } + + /** + * {@inheritdoc} + */ + protected function prepareModels() + { + $models = []; + $pagination = $this->getPagination(); + + if ($pagination === false) { + // En caso de que no haya paginación, leer todas las líneas + while (!$this->fileObject->eof()) { + $models[] = $this->fileObject->fgetcsv(); + $this->fileObject->next(); + } + } else { + // En caso de que haya paginación, leer sólo una única página + $pagination->totalCount = $this->getTotalCount(); + $this->fileObject->seek($pagination->getOffset()); + $limit = $pagination->getLimit(); + + for ($count = 0; $count < $limit; ++$count) { + $models[] = $this->fileObject->fgetcsv(); + $this->fileObject->next(); + } + } + + return $models; + } + + /** + * {@inheritdoc} + */ + protected function prepareKeys($models) + { + if ($this->key !== null) { + $keys = []; + + foreach ($models as $model) { + if (is_string($this->key)) { + $keys[] = $model[$this->key]; + } else { + $keys[] = call_user_func($this->key, $model); + } + } + + return $keys; + } + + return array_keys($models); + } + + /** + * {@inheritdoc} + */ + protected function prepareTotalCount() + { + $count = 0; + + while (!$this->fileObject->eof()) { + $this->fileObject->next(); + ++$count; + } + + return $count; + } +} +``` + +## Filtrar proveedores de datos usando filtros de datos + +Si bien puede construir condiciones para un proveedor de datos activo manualmente tal +y como se describe en las secciones [Filtering Data](output-data-widgets.md#filtering-data) +y [Separate Filter Form](output-data-widgets.md#separate-filter-form) de la guía de +_widgets_ de datos, Yii tiene filtros de datos que son muy útiles si necesita +condiciones de filtro flexibles. Los filtros de datos se pueden usar así: + +```php +$filter = new ActiveDataFilter([ + 'searchModel' => 'app\models\PostSearch' +]); + +$filterCondition = null; + +// Puede cargar los filtros de datos de cualquier fuente. +// Por ejemplo, si prefiere JSON en el cuerpo de la petición, +// use Yii::$app->request->getBodyParams() aquí abajo: +if ($filter->load(\Yii::$app->request->get())) { + $filterCondition = $filter->build(); + if ($filterCondition === false) { + // Serializer recibiría errores + return $filter; + } +} + +$query = Post::find(); +if ($filterCondition !== null) { + $query->andWhere($filterCondition); +} + +return new ActiveDataProvider([ + 'query' => $query, +]); +``` + +El propósito del modelo `PostSearch` es definir por qué propiedades y valores se permite filtrar: + +```php +use yii\base\Model; + +class PostSearch extends Model +{ + public $id; + public $title; + + public function rules() + { + return [ + ['id', 'integer'], + ['title', 'string', 'min' => 2, 'max' => 200], + ]; + } +} +``` + +Los filtros de datos son bastante flexibles. Puede personalizar cómo se construyen +las condiciones y qué operadores se permiten. +Para más detalles consulte la documentación de la API en [[\yii\data\DataFilter]]. diff --git a/docs/guide-es/output-data-widgets.md b/docs/guide-es/output-data-widgets.md new file mode 100644 index 00000000000..06db9fe4b69 --- /dev/null +++ b/docs/guide-es/output-data-widgets.md @@ -0,0 +1,245 @@ +Widgets de datos +================ + +Yii proporciona un conjunto de [widgets](structure-widgets.md) que se pueden usar para mostrar datos. +Mientras que el _widget_ [DetailView](#detail-view) se puede usar para mostrar los datos de un único +registro, [ListView](#list-view) y [GridView](#grid-view) se pueden usar para mostrar una lista o +tabla de registros de datos proporcionando funcionalidades como paginación, ordenación y filtro. + + +DetailView +---------- + +El _widget_ [[yii\widgets\DetailView|DetailView]] muestra los detalles de un único +[[yii\widgets\DetailView::$model|modelo]] de datos. + +Se recomienda su uso para mostrar un modelo en un formato estándar (por ejemplo, cada atributo del +modelo se muestra como una fila en una tabla). El modelo puede ser tanto una instancia o subclase +de [[\yii\base\Model]] como un [active record](db-active-record.md) o un _array_ asociativo. + +DetailView usa la propiedad [[yii\widgets\DetailView::$attributes|$attributes]] para determinar +qué atributos del modelo se deben mostrar y cómo se deben formatear. +En la [sección sobre formateadores](output-formatting.html) se pueden ver las opciones de formato +disponibles. + +Un uso típico de DetailView sería así: + +```php +echo DetailView::widget([ + 'model' => $model, + 'attributes' => [ + 'title', // atributo title (en texto plano) + 'description:html', // atributo description formateado como HTML + [ // nombre del propietario del modelo + 'label' => 'Owner', + 'value' => $model->owner->name, + 'contentOptions' => ['class' => 'bg-red'], // atributos HTML para personalizar el valor + 'captionOptions' => ['tooltip' => 'Tooltip'], // atributos HTML para personalizar la etiqueta + ], + 'created_at:datetime', // fecha de creación formateada como datetime + ], +]); +``` + +Recuerde que a diferencia de [[yii\widgets\GridView|GridView]], que procesa un conjunto de modelos, +[[yii\widgets\DetailView|DetailView]] sólo procesa uno. Así que la mayoría de las veces no hay +necesidad de usar funciones anónimas ya que `$model` es el único modelo a mostrar y está disponible +en la vista como una variable. + +Sin embargo, en algunos casos el uso de una función anónima puede ser útil. Por ejemplo cuando +`visible` está especificado y se desea impedir el cálculo de `value` en case de que evalúe a `false`: + +```php +echo DetailView::widget([ + 'model' => $model, + 'attributes' => [ + [ + 'attribute' => 'owner', + 'value' => function ($model) { + return $model->owner->name; + }, + 'visible' => \Yii::$app->user->can('posts.owner.view'), + ], + ], +]); +``` + + +ListView +-------- + +El _widget_ [[yii\widgets\ListView|ListView]] se usa para mostrar datos de un +[proveedor de datos](output-data-providers.md). +Cada modelo de datos se representa usando el [[yii\widgets\ListView::$itemView|fichero de vista]] +indicado. +Como proporciona de serie funcionalidades tales como paginación, ordenación y filtro, +es útil tanto para mostrar información al usuario final como para crear una interfaz +de usuario de gestión de datos. + +Un uso típico es el siguiente: + +```php +use yii\widgets\ListView; +use yii\data\ActiveDataProvider; + +$dataProvider = new ActiveDataProvider([ + 'query' => Post::find(), + 'pagination' => [ + 'pageSize' => 20, + ], +]); + +echo ListView::widget([ + 'dataProvider' => $dataProvider, + 'itemView' => '_post', +]); +``` + +El fichero de vista `_post` podría contener lo siguiente: + +```php + +
+

title) ?>

+ + text) ?> +
+``` + +En el fichero de vista anterior, el modelo de datos actual está disponible como `$model`. +Además están disponibles las siguientes variables: + +- `$key`: mixto, el valor de la clave asociada a este elemento de datos. +- `$index`: entero, el índice empezando por cero del elemento de datos en el array de elementos devuelto por el proveedor de datos. +- `$widget`: ListView, esta instancia del _widget_. + +Si se necesita pasar datos adicionales a cada vista, se puede usar la propiedad +[[yii\widgets\ListView::$viewParams|$viewParams]] para pasar parejas clave-valor como las siguientes: + +```php +echo ListView::widget([ + 'dataProvider' => $dataProvider, + 'itemView' => '_post', + 'viewParams' => [ + 'fullView' => true, + 'context' => 'main-page', + // ... + ], +]); +``` + +Entonces éstas también estarán disponibles en la vista como variables. + + +GridView +-------- + +La cuadrícula de datos o [[yii\grid\GridView|GridView]] es uno de los _widgets_ de Yii +más potentes. Es extremadamente útil si necesita construir rápidamente la sección de +administración del sistema. Recibe los datos de un [proveedor de datos](output-data-providers.md) +y representa cada fila usando un conjunto de [[yii\grid\GridView::columns|columnas]] +que presentan los datos en forma de tabla. + +Cada fila de la tabla representa los datos de un único elemento de datos, y una columna +normalmente representa un atributo del elemento (algunas columnas pueden corresponder a +expresiones complejas de los atributos o a un texto estático). + +El mínimo código necesario para usar GridView es como sigue: + +```php +use yii\grid\GridView; +use yii\data\ActiveDataProvider; + +$dataProvider = new ActiveDataProvider([ + 'query' => Post::find(), + 'pagination' => [ + 'pageSize' => 20, + ], +]); +echo GridView::widget([ + 'dataProvider' => $dataProvider, +]); +``` + +El código anterior primero crea un proveedor de datos y a continuación usa GridView +para mostrar cada atributo en cada fila tomados del proveedor de datos. La tabla +mostrada está equipada de serie con las funcionalidades de ordenación y paginación. + + +### Columnas de la cuadrícula + +Las columnas de la tabla se configuran en términos de clase [[yii\grid\Column]], que +se configuran en la propiedad [[yii\grid\GridView::columns|columns]] de la configuración +del GridView. +Dependiendo del tipo y ajustes de las columnas éstas pueden presentar los datos de +diferentes maneras. +La clase predefinida es [[yii\grid\DataColumn]], que representa un atributo del modelo +por el que se puede ordenar y filtrar. + + +```php +echo GridView::widget([ + 'dataProvider' => $dataProvider, + 'columns' => [ + ['class' => 'yii\grid\SerialColumn'], + // Columnas sencillas definidas por los datos contenidos en $dataProvider. + // Se usarán los datos de la columna del modelo. + 'id', + 'username', + // Un ejemplo más complejo. + [ + 'class' => 'yii\grid\DataColumn', // Se puede omitir, ya que es la predefinida. + 'value' => function ($data) { + return $data->name; // $data['name'] para datos de un array, por ejemplo al usar SqlDataProvider. + }, + ], + ], +]); +``` + +Observe que si no se especifica la parte [[yii\grid\GridView::columns|columns]] de la +configuración, Yii intenta mostrar todas las columnas posibles del modelo del proveedor +de datos. + + +### Clases de columna + +Las columnas de la cuadrícula se pueden personalizar usando diferentes clases de columna: + +```php +echo GridView::widget([ + 'dataProvider' => $dataProvider, + 'columns' => [ + [ + 'class' => 'yii\grid\SerialColumn', // <-- aquí + // puede configurar propiedades adicionales aquí + ], +``` + +Además de las clases de columna proporcionadas por Yii que se revisarán más abajo, +puede crear sus propias clases de columna. + +Cada clase de columna extiende [[yii\grid\Column]] de modo que hay algunas opciones +comunes que puede establecer al configurar las columnas de una cuadrícula. + +- [[yii\grid\Column::header|header]] permite establecer el contenida para la fila cabecera +- [[yii\grid\Column::footer|footer]] permite establece el contenido de la fila al pie +- [[yii\grid\Column::visible|visible]] define si la columna debería ser visible. +- [[yii\grid\Column::content|content]] le permite pasar una función PHP válida que devuelva datos para una fila. El formato es el siguiente: + + ```php + function ($model, $key, $index, $column) { + return 'una cadena'; + } + ``` + +Puede indicar varias opciones HTML del contenedor pasando _arrays_ a: + +- [[yii\grid\Column::headerOptions|headerOptions]] +- [[yii\grid\Column::footerOptions|footerOptions]] +- [[yii\grid\Column::filterOptions|filterOptions]] +- [[yii\grid\Column::contentOptions|contentOptions]] + diff --git a/docs/guide-es/rest-routing.md b/docs/guide-es/rest-routing.md index 974d7956cbd..dcb6bddfd3f 100644 --- a/docs/guide-es/rest-routing.md +++ b/docs/guide-es/rest-routing.md @@ -40,16 +40,16 @@ Por ejemplo, el código anterior es equivalente a las siguientes reglas: Y los siguientes puntos finales del API son mantenidos por esta regla: * `GET /users`: lista de todos los usuarios página a página; -* `HEAD /users`: muestra ĺa información resumén del usuario listado; +* `HEAD /users`: muestra ĺa información resumen del usuario listado; * `POST /users`: crea un nuevo usuario; * `GET /users/123`: devuelve los detalles del usuario 123; -* `HEAD /users/123`: muestra la información resúmen del usuario 123; +* `HEAD /users/123`: muestra la información resumen del usuario 123; * `PATCH /users/123` y `PUT /users/123`: actualizan al usuario 123; * `DELETE /users/123`: borra el usuario 123; * `OPTIONS /users`: muestra los verbos soportados de acuerdo al punto final `/users`; * `OPTIONS /users/123`: muestra los verbos soportados de acuerdo al punto final `/users/123`. -Puedes configurar las opciones `only` y `except` para explícitamente listar cuáles acciones a soportar o cuáles +Puedes configurar las opciones `only` y `except` para explícitamente listar cuáles acciones soportar o cuáles deshabilitar, respectivamente. Por ejemplo, ```php @@ -60,8 +60,8 @@ deshabilitar, respectivamente. Por ejemplo, ], ``` -También puedes configurar las propiedades `patterns` o `extraPatterns` para redifinir patrones existentes o añadir nuevos soportados por esta regla. -Por ejemplo, para soportar una nueva acción `search` por el punto final `GET /users/search`, configura la opción `extraPatterns` como sigue, +También puedes configurar las propiedades `patterns` o `extraPatterns` para redefinir patrones existentes o añadir nuevos soportados por esta regla. +Por ejemplo, para soportar una nueva acción `search` para el punto final `GET /users/search`, configura la opción `extraPatterns` como sigue, ```php [ @@ -81,7 +81,7 @@ Puedes desactivar este comportamiento definiendo la propiedad [[yii\rest\UrlRule reglas especiales de pluralización. Por ejemplo, la palabra `box` (caja) será pluralizada como `boxes` en vez de `boxs`. En caso de que la pluralización automática no encaje en tus requerimientos, puedes además configurar la propiedad -[[yii\rest\UrlRule::controller]] para especificar exlpícitamente cómo mapear un nombre utilizado en un punto final URL +[[yii\rest\UrlRule::controller]] para especificar explícitamente cómo mapear un nombre utilizado en un punto final URL a un ID de controlador. Por ejemplo, el siguiente código mapea el nombre `u` al ID del controlador `user`. ```php diff --git a/docs/guide-es/start-installation.md b/docs/guide-es/start-installation.md index 70a57e4f974..ad0aa47c807 100644 --- a/docs/guide-es/start-installation.md +++ b/docs/guide-es/start-installation.md @@ -18,7 +18,7 @@ en el entorno de un equipo de desarrollo. utilizar el Template de Proyecto Básico por su simplicidad pero funcionalidad suficiente. -Installing via Composer +Instalando via Composer ------------------------------- Si aún no tienes Composer instalado, puedes hacerlo siguiendo las instrucciones que se encuentran en diff --git a/docs/guide-es/start-prerequisites.md b/docs/guide-es/start-prerequisites.md new file mode 100644 index 00000000000..fdbccc18bc7 --- /dev/null +++ b/docs/guide-es/start-prerequisites.md @@ -0,0 +1,29 @@ +# Qué necesita saber + +La curva de aprendizaje de Yii no es tan empinada como en otros _frameworks_ en PHP, +pero todavía hay algunas cosas que debería aprender antes de empezar con Yii. + +## PHP + +Yii es un _framework_ (base estructurada de desarrollo) en PHP, así que asegúrese de +[leer y comprender la referencia del lenguaje](http://php.net/manual/es/langref.php). +Al desarrollar con Yii deberá escribir código de manera orientada a objetos, así que +asegúrese de estar familiarizado con +[clases y objetos](https://secure.php.net/manual/es/language.oop5.basic.php) así como con +[espacios de nombres](https://secure.php.net/manual/es/language.namespaces.php). + +## Programación orientada a objetos + +Se requiere una comprensión básica de la programación orientada a objetos. Si no está +familiarizado con ella, diríjase a alguno d elos muchos tutoriales disponibles, como +[el de tuts+](https://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762). + +Observe que cuanto más complicada sea su aplicación, más conceptos avanzados de la +POO deberá aprender para gestionar con éxito esa complejidad. + +## Línea de órdenes y composer + +Yii usa profusamente el gestor de paquetes _de facto_ de PHP, [Composer](https://getcomposer.org/), +así que asegúrese de leer y comprender su [guía](https://getcomposer.org/doc/01-basic-usage.md). +Si no está familiarizado con el uso de la línea de órdenes, es hora de empezar a probarla. +Una vez que aprenda los fundamentos, nunca querrá trabajar sin ella. diff --git a/docs/guide-es/structure-widgets.md b/docs/guide-es/structure-widgets.md index f5a408730fb..7a7327d3a28 100644 --- a/docs/guide-es/structure-widgets.md +++ b/docs/guide-es/structure-widgets.md @@ -1,10 +1,11 @@ Widgets ======= -Los Widgets son bloques de código reutilizables utilizados en las [vistas](structure-views.md) para crear elementos de -interfaz de usuario complejos y configurables de forma orientada a objetos. Por ejemplo, widget DatePicker puede -generar un DatePicker de lujo que permita a los usuarios seleccionar una fecha. Todo lo que se tiene que hacer es -insertar el siguiente código en una vista. +Los _widgets_ son bloques de código reutilizables que se usan en las [vistas](structure-views.md) +para crear elementos de interfaz de usuario complejos y configurables, de forma orientada a objetos. +Por ejemplo, un _widget_ de selección de fecha puede generar un selector de fechas bonito que +permita a los usuarios seleccionar una fecha. Todo lo que hay que hacer es insertar el siguiente +código en una vista: ```php 'date']) ?> ``` -Hay un buen número de widgets incluidos en Yii, tales como [[yii\widgets\ActiveForm|active form]], -[[yii\widgets\Menu|menu]], [Widgets de jQuery UI](widget-jui.md), [widgets de Twitter Bootstrap](widget-bootstrap.md). -En adelante, introduciremos las nociones básicas acerca de los widgets. Por favor, refiérase a la documentación de la -API de clases si quiere aprender más acerca de el uso de un widget en particular. +Yii incluye un buen número de _widgets_, tales como +[[yii\widgets\ActiveForm|formulario activo]], +[[yii\widgets\Menu|menú]], +[_widgets_ de jQuery UI](https://www.yiiframework.com/extension/yiisoft/yii2-jui), y +[_widgets_ de Twitter Bootstrap](https://www.yiiframework.com/extension/yiisoft/yii2-bootstrap). +A continuación presentaremos las nociones básicas de de los _widgets_. Por favor, refiérase a la +documentación de la API de clases si quiere aprender más acerca del uso de un _widget_ en particular. -## Uso de los Widgets -Los Widgets son usados principalmente en las [vistas](structure-views.md). Se puede llamar al método -[[yii\base\Widget::widget()]] para usar un widget en una vista. El método obtiene un array de -[configuración](concept-configurations.md) para inicializar el widget y retorna la representación resultante del -widget. Por ejemplo, el siguiente código inserta un widget DatePicker que esta configurado para usar el idioma Ruso y -mantener la entrada en atributo 'form_date' del '$model'. +## Uso de los _widgets_ + +Los _widgets_ se usan principalmente en las [vistas](structure-views.md). Se puede llamar al método +[[yii\base\Widget::widget()]] para usar un _widget_ en una vista. El método toma un _array_ de +[configuración](concept-configurations.md) para inicializar el _widget_ y devuelve la representación +resultante del _widget_. Por ejemplo, el siguiente código inserta un _widget_ de selección de fecha +configurado para usar el idioma ruso y guardar la selección en el atributo `from_date` de `$model`. ```php $model, 'attribute' => 'from_date', 'language' => 'ru', - 'clientOptions' => [ - 'dateFormat' => 'yy-mm-dd', - ], + 'dateFormat' => 'php:Y-m-d', ]) ?> ``` -Algunos widgets pueden coger un bloque de contenido que debería encontrarse entre la invocación de -[[yii\base\Widget::begin()]] y [[yii\base\Widget::end()]]. Por ejemplo, el siguiente código usa el widget -[[yii\widgets\ActiveForm]] para generar un formulario de inicio de sesión. El widget generará las etiquetas '
' -de apertura y cierre donde sean llamados 'begin()' y 'end()', respectivamente. Cualquier cosa que este en medio será -representado como tal. +Algunos _widgets_ pueden coger un bloque de contenido que debería encontrarse entre la invocación de +[[yii\base\Widget::begin()]] y [[yii\base\Widget::end()]]. Por ejemplo, el siguiente código usa el +_widget_ [[yii\widgets\ActiveForm]] para generar un formulario de inicio de sesión. El _widget_ +generará las etiquetas `` de apertura y cierre donde se llame a `begin()` y `end()` +respectivamente. Cualquier cosa que este en medio se representará tal cual. ```php ``` -Hay que tener en cuenta que a diferencia de [[yii\base\Widget::widget()]] que devuelve la representación resultante -del widget, el método [[yii\base\Widget::begin()]] devuelve una instancia del widget que se puede usar para generar el -contenido del widget. +Hay que tener en cuenta que, a diferencia de [[yii\base\Widget::widget()]] que devuelve la +representación resultante del _widget_, el método [[yii\base\Widget::begin()]] devuelve una +instancia del _widget_, que se puede usar para generar el contenido del _widget_. + +> Nota: Algunos _widgets_ utilizan un [búfer de salida](http://php.net/manual/es/book.outcontrol.php) +> para ajustar el contenido rodeado al invocar [[yii\base\Widget::end()]]. Por este motivo se espera +> que las llamadas a [[yii\base\Widget::begin()]] y [[yii\base\Widget::end()]] tengan lugar en el +> mismo fichero de vista. +> No seguir esta regla puede desembocar en una salida distinta a la esperada. -## Creación Widgets -Para crear un widget, se debe extender a [[yii\base\Widget]] y sobrescribir los métodos [[yii\base\Widget::init()]] -y/o [[yii\base\Widget::run()]]. Normalmente el método 'init()' debería contener el código que estandariza las -propiedades del widget, mientras que el método 'run()' debería contener el código que genere la representación -resultante del widget. La representación resultante puede ser "pintada" directamente o devuelta como una cadena por el -método 'run()'. +### Configuración de las variables globales predefinidas -En el siguiente ejemplo, 'HelloWidget' codifica en HTML y muestra el contenido asignado a su propiedad 'message'. Si -la propiedad no está establecida, mostrará "Hello World" por defecto. +Las variables globales predefinidas de un _widget_ se pueden configurar por medio del contenedor +de inyección de dependencias: + +```php +\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]); +``` + +Consulte la [sección "Uso práctico" de la Guía del contenedor de inyección de dependencias](concept-di-container.md#practical-usage) para más detalles. + + +## Creación de _widgets_ + +Para crear un _widget_, extienda la clase [[yii\base\Widget]] y sobrescriba los métodos +[[yii\base\Widget::init()]] y/o [[yii\base\Widget::run()]]. Normalmente el método `init()` debería +contener el código que inicializa las propiedades del _widget_, mientras que el método `run()` +debería contener el código que genera la representación resultante del _widget_. La representación +resultante del método `run()` puede pasarse directamente a `echo` o devolverse como una cadena. + +En el siguiente ejemplo, `HelloWidget` codifica en HTML y muestra el contenido asignado a su +propiedad `message`. Si la propiedad no está establecida, mostrará «Hello World» por omisión. ```php namespace app\components; @@ -105,7 +127,7 @@ class HelloWidget extends Widget } ``` -Para usar este widget, simplemente inserte el siguiente código en una vista: +Para usar este _widget_, simplemente inserte el siguiente código en una vista: ```php 'Good morning']) ?> ``` -Abajo se muestra una variante de 'HelloWidget' obtiene el contenido entre las llamadas 'begin()' y 'end()', lo -codifica en HTML y posteriormente lo muestra. +Abajo se muestra una variante de `HelloWidget` que toma el contenido insertado entre las llamadas a +`begin()` y `end()`, lo codifica en HTML y posteriormente lo muestra. ```php namespace app\components; @@ -139,14 +161,15 @@ class HelloWidget extends Widget } ``` -Como se puede observar, el búfer de salida PHP es iniciado en 'init()' por tanto cualquier salida entre las llamadas -de 'init()' y 'run()' puede ser capturada, procesada y devuelta en 'run()'. +Como se puede observar, el búfer de salida de PHP es iniciado en `init()` para que toda salida +entre las llamadas de `init()` y `run()` puede ser capturada, procesada y devuelta en `run()`. -> Info: Cuando se llama a [[yii\base\Widget::begin()]], se creará una nueva instancia del widget y el método 'init()' - será llamado al final del constructor del widget. Cuando se llama [[yii\base\Widget::end()]], el método 'run()' será - llamado el resultado que devuelva será escrito por 'end()'. +> Info: Cuando llame a [[yii\base\Widget::begin()]], se creará una nueva instancia del _widget_ y se +> llamará a su método `init()` al final del constructor del _widget_. Cuando llame a +> [[yii\base\Widget::end()]], se invocará el método `run()` y el resultado que devuelva será pasado +> a `echo` por `end()`. -El siguiente código muestra como usar esta nueva variante de 'HelloWidget': +El siguiente código muestra cómo usar esta nueva variante de `HelloWidget`: ```php - content that may contain 's + contenido que puede contener s ``` -A veces, un widget puede necesitar representar una gran cantidad de contenido. Mientras que se puede incrustar el -contenido dentro del método 'run()', ponerlo dentro de una [vista](structure-views.md) y llamar -[[yii\base\Widget::render()]] para representarla, es un mejor enfoque. Por ejemplo: +A veces, un _widget_ puede necesitar representar un gran bloque de contenido. Aunque que se +podría incrustar el contenido dentro del método `run()`, es preferible ponerlo dentro de una +[vista](structure-views.md) y llamar al método [[yii\base\Widget::render()]] para representarlo. +Por ejemplo: ```php public function run() @@ -170,24 +194,27 @@ public function run() } ``` -Por defecto, las vistas para un widget deberían encontrarse en ficheros dentro del directorio 'WidgetPath/views', -donde 'WidgetPath' representa el directorio que contiene el fichero de clase del widget. Por lo tanto, el anterior -ejemplo representará el fichero de la vista `@app/components/views/hello.php`, asumiendo que la clase del widget se -encuentre en `@app/components`. Se puede sobrescribir el método [[yii\base\Widget::getViewPath()]] para personalizar -el directorio que contenga los ficheros de la vista del widget. +Por omisión, las vistas para un _widget_ deberían encontrarse en ficheros dentro del directorio +`WidgetPath/views`, donde `WidgetPath` representa el directorio que contiene el fichero de clase +del _widget_. Por lo tanto, el ejemplo anterior representará el fichero de vista +`@app/components/views/hello.php`, suponiendo que la clase del _widget_ se encuentre en +`@app/components`. Se puede sobrescribir el método [[yii\base\Widget::getViewPath()]] para +personalizar el directorio que contiene los ficheros de vista del _widget_. + -## Mejores Prácticas +## Buenas prácticas -Los widgets son una manera orientada a objetos de reutilizar código de las vistas. +Los _widgets_ son una manera orientada a objetos de reutilizar código de las vistas. -Cuando se crean widgets, se debería continuar manteniendo el patrón MVC. En general, se debería mantener la lógica en -las clases del widget y mantener la presentación en las [vistas](structure-views.md). +Al crear _widgets_, debería continuar suguiendo el patrón MVC. En general, se debería mantener la +lógica en las clases del widget y la presentación en las [vistas](structure-views.md). -Los widgets deberían ser diseñados para ser autónomos. Es decir, cuando se usa un widget, se debería poder poner en -una vista sin hacer nada más. Esto puede resultar complicado si un widget requiere recursos externos, tales como CSS, -JavaScript, imágenes, etc. Afortunadamente Yii proporciona soporte para -[asset bundles](structure-asset-bundles.md) que pueden ser utilizados para resolver el problema. +Los _widgets_ deberían diseñarse para ser autosuficientes. Es decir, cuando se use un _widget_, se +debería poder ponerlo en una vista sin hacer nada más. Esto puede resultar complicado si un +_widget_ requiere recursos externos, tales como CSS, JavaScript, imágenes, etc. Afortunadamente +Yii proporciona soporte para [paquetes de recursos](structure-asset-bundles.md) (_asset bundles_) +que se pueden utilizar para resolver este problema. -Cuando un widget sólo contiene código de vista, este es muy similar a una [vista](structure-views.md). De hecho, en -este caso, su única diferencia es que un widget es una clase redistribuible, mientras que una vista es sólo un script -PHP llano que prefiere mantenerse dentro de su aplicación. +Cuando un _widget_ sólo contiene código de vista, es muy similar a una [vista](structure-views.md). +De hecho, en este caso, su única diferencia es que un _widget_ es una clase redistribuible, mientras +que una vista es sólo un simple script PHP que prefiere mantener dentro de su aplicación. diff --git a/docs/guide-es/test-acceptance.md b/docs/guide-es/test-acceptance.md new file mode 100644 index 00000000000..8df65e44dbc --- /dev/null +++ b/docs/guide-es/test-acceptance.md @@ -0,0 +1,20 @@ +Tests de aceptación +=================== + +Un test de aceptación verifica escenarios desde la perspectiva de un usuario. +Se accede a la aplicación testeada por medio de PhpBrowser o de un navegador de verdad. +En ambos casos los navegadores se comunican vía HTTP así que la aplicación debe ser +servida por un servidor web. + +Los tests de aceptación se implementan con ayuda del _framework_ Codeception, que tiene +una buena documentación: + +- [Codeception para el _framework_ Yii](http://codeception.com/for/yii) +- [Tests funcionales de Codeception](http://codeception.com/docs/04-FunctionalTests) + +## Ejecución de tests en las plantillas básica y avanzada + +Si ha empezado con la plantilla avanzada, consulte la [guía de testeo](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/start-testing.md) +para más detalles sobre la ejecución de tests. + +Si ha empezado con la plantilla básica, consulte la [sección sobre testeo de su README](https://github.com/yiisoft/yii2-app-basic/blob/master/README.md#testing). diff --git a/docs/guide-es/test-environment-setup.md b/docs/guide-es/test-environment-setup.md index 631f96a9ee6..e016112b858 100644 --- a/docs/guide-es/test-environment-setup.md +++ b/docs/guide-es/test-environment-setup.md @@ -1,49 +1,23 @@ -Preparación del entorno de test -=============================== +Preparación del entorno de pruebas +================================== -> Note: Esta sección se encuentra en desarrollo. +Yii 2 ha mantenido oficialmente integración con el _framework_ de testeo [`Codeception`](https://github.com/Codeception/Codeception), +que le permite crear los siguientes tipos de tests: -Yii 2 ha mantenido integración oficial con el framework de testing [`Codeception`](https://github.com/Codeception/Codeception), -que te permite crear los siguientes tipos de tests: +- [Unitari](test-unit.md) - verifica que una unidad simple de código funciona como se espera; +- [Funcional](test-functional.md) - verifica escenarios desde la perspectiva de un usuario a través de la emulación de un navegador; +- [De aceptación](test-acceptance.md) - verifica escenarios desde la perspectiva de un usuario en un navegador. -- [Test de unidad](test-unit.md) - verifica que una unidad simple de código funciona como se espera; -- [Test funcional](test-functional.md) - verifica escenarios desde la perspectiva de un usuario a través de la emulación de un navegador; -- [Test de aceptación](test-acceptance.md) - verifica escenarios desde la perspectiva de un usuario en un navegador. +Yii provee grupos de pruebas listos para utilizar para los tres tipos de test, tanto en la plantilla de proyecto +[`yii2-basic`](https://github.com/yiisoft/yii2-app-basic) como en +[`yii2-advanced`](https://github.com/yiisoft/yii2-app-advanced). -Yii provee grupos de pruebas listos para utilizar en ambos -[`yii2-basic`](https://github.com/yiisoft/yii2-app-basic) y -[`yii2-advanced`](https://github.com/yiisoft/yii2-app-advanced) templates de proyectos. - -Para poder ejecutar estos tests es necesario instalar [Codeception](https://github.com/Codeception/Codeception). -Puedes instalarlo tanto localmente - únicamente para un proyecto en particular, o globalmente - para tu máquina de desarrollo. - -Para la instalación local utiliza los siguientes comandos: - -``` -composer require "codeception/codeception=2.1.*" -composer require "codeception/specify=*" -composer require "codeception/verify=*" -``` - -Para la instalación global necesitarás la directiva `global`: +Codeception viene preinstalado tanto en la plantilla de proyecto básica como en la avanzada. +En caso de que no use una de estas plantillas, puede instalar Codeception ejecutando +las siguientes órdenes de consola: ``` -composer global require "codeception/codeception=2.1.*" -composer global require "codeception/specify=*" -composer global require "codeception/verify=*" +composer require codeception/codeception +composer require codeception/specify +composer require codeception/verify ``` - -En caso de que nunca hayas utilizado Composer para paquetes globales, ejecuta `composer global status`. Esto debería mostrar la salida: - -``` -Changed current directory to -``` - -Entonces agrega `/vendor/bin` a tu variable de entorno `PATH`. Ahora podrás utilizar el `codecept` en la línea -de comandos a nivel global. - -> Note: la instalación global te permite usar Codeception para todos los proyectos en los que trabajes en tu máquina de desarrollo y - te permite ejecutar el comando `codecept` globalmente sin especificar su ruta. De todos modos, ese acercamiento podría ser inapropiado, - por ejemplo, si 2 proyectos diferentes requieren diferentes versiones de Codeception instaladas. - Por simplicidad, todos los comandos relacionados a tests en esta guía están escritos asumiendo que Codeception - ha sido instalado en forma global. diff --git a/docs/guide-es/test-functional.md b/docs/guide-es/test-functional.md index ee53ebc9d12..b48238cb2cd 100644 --- a/docs/guide-es/test-functional.md +++ b/docs/guide-es/test-functional.md @@ -1,11 +1,25 @@ -Tests Funcionales +Tests funcionales ================= -> Note: Esta sección se encuentra en desarrollo. +Los tests funcionales verifican escenarios desde la perspectiva de un usuario. +Son similares a los [tests de aceptación](test-acceptance.md) pero en lugar de +comunicarse vía HTTP rellena el entorno como parámetros POST y GET y después ejecuta +una instancia de la aplicación directamente desde el código. -- [Tests Funcionales de Codeception](http://codeception.com/docs/04-FunctionalTests) +Los tests funcionales son generalmente más rápidos que los tests de aceptación y +proporcionan _stack traces_ detalladas en los fallos. +Como regla general, debería preferirlos salvo que tenga una configuración de servidor +web especial o una interfaz de usuario compleja en Javascript. -Ejecutar test funcionales de templates básicos y avanzados ----------------------------------------------------------- +Las pruebas funcionales se implementan con ayuda del _framework_ Codeception, que tiene +una buena documentación: -Por favor consulta las instrucciones provistas en `apps/advanced/tests/README.md` y `apps/basic/tests/README.md`. +- [Codeception para el _framework_ Yii](http://codeception.com/for/yii) +- [Tests funcionales de Codeception](http://codeception.com/docs/04-FunctionalTests) + +## Ejecución de tests en las plantillas básica y avanzada + +Si ha empezado con la plantilla avanzada, consulte la [guía de testeo](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/start-testing.md) +para más detalles sobre la ejecución de tests. + +Si ha empezado con la plantilla básica, consulte la [sección sobre testeo de su README](https://github.com/yiisoft/yii2-app-basic/blob/master/README.md#testing). diff --git a/docs/guide-es/test-overview.md b/docs/guide-es/test-overview.md new file mode 100644 index 00000000000..35b7008191e --- /dev/null +++ b/docs/guide-es/test-overview.md @@ -0,0 +1,80 @@ +Tests +===== + +Las pruebas son una parte importante del desarrollo de software. Seamos conscientes +de ello o no, ralizamos pruebas contínuamente. +Por ejemplo, cuando escribimos una clase en PHP, podemos depurarla paso a paso o +simplemente usar declaraciones `echo` o `die` para verificar que la implementación +funciona conforme a nuestro plan inicial. En el caso de una aplicación web, introducimos +algunos datos de prueba en los formularios para asegurarnos de que la página interactúa +con nosotros como esperábamos. + +El proceso de testeo se puede automatizar para que cada vez que necesitemos verificar +algo, solamente necesitemos invocar el código que lo hace por nosotros. El código que +verifica que el restulado coincide con lo que habíamos planeado se llama *test* y el proceso +de su creación y posterior ejecución es conocido como *testeo automatizado*, que es el +principal tema de estos capítulos sobre testeo. + + +## Desarrollo con tests + +El Desarrollo Dirigido por Pruebas (_Test-Driven Development_ o TDD) y el Desarrollo +Dirigido por Corpotamientos (_Behavior-Driven Development_ o BDD) son enfoques para +desarrollar software, en los que se describe el comportamiento de un trozo de código +o de toda la funcionalidad como un conjunto de escenarios o pruebas antes de escribir +el código real y sólo entonces crear la implementación que permite pasar esos tests +verificando que se ha logrado el comportamiento pretendido. + +El proceso de desarrollo de una funcionalidad es el siguiente: + +- Crear un nuevo test que describe una funcionalidad a implementar. +- Ejecutar el nuevo test y asegurarse de que falla. Esto es lo esperado, dado que todavía no hay ninguna implementación. +- Escribir un código sencillo para superar el nuevo test. +- Ejecutar todos los tests y asegurarse de que se pasan todos. +- Mejorar el código y asegurarse de que los tests siguen superándose. + +Una vez hecho, se repite el proceso de neuvo para otra funcionalidad o mejora. +Si se va a cambiar la funcionalidad existente, también hay que cambiar los tests. + +> Tip: Si siente que está perdiendo tiempo haciendo un montón de iteraciones pequeñas +> y simples, intente cubrir más por cada escenario de test, de modo que haga más cosas antes +> de ejecutar los tests de nuevo. Si está depurando demasiado, intente hacer lo contrario. + +La razón para crear los tests antes de hacer ninguna implementación es que eso nos permite +centrarnos en lo que queremos alcanzar y sumergirnos totalmente en «cómo hacerlo» después. +Normalmente conduce a mejores abstracciones y a un más fácil mantenimiento de los tests +cuando toque hacer ajustes a las funcionalidades o componentes menos acoplados. + +Para resumir, las ventajas de este enfoque son las siguientes: + +- Le mantiene centrado en una sola cosa en cada momento, lo que resulta en una mejor planificación e implementación. +- Resulta en más funcionalidades cubiertas por tests, y en mayor detalle. Es decir, si se superan los tests, lo más problable es que no haya nada roto. + +A largo plazo normalmente tiene como efecto un buen ahorro de tiempo. + +## Qué y cómo probar + +Aunque el enfoque de primero los tests descrito arriba tiene sentido para el largo plazo +y proyectos relativamente complejos, sería excesivo para proyectos más simples. +Hay algunas indicaciones de cuándo es apropiado: + +- El proyecto ya es grande y complejo. +- Los requisitos del proyecto están empezando a hacerse complejos. El proyecto crece constantemente. +- El proyecto pretende a ser a largo plazo. +- El coste de fallar es demasiado alto. + +No hay nada malo en crear tests que cubran el comportamiento de una implementación existente. + +- Es un proyecto legado que se va a renovar gradualmente. +- Le han dado un proyecto sobre el que trabajar y no tiene tests. + +En algunos casos cualquier forma de testo automatizado sería exagerada: + +- El proyecto es sencillo y no se va a volver más complejo. +- Es un proyecto puntual en el que no se seguirá trabajando. + +De todas formas, si dispone de tiempo, es bueno automatizar las pruebas también en esos casos. + +## Más lecturas + +- Test Driven Development: By Example / Kent Beck. ISBN: 0321146530. diff --git a/docs/guide-es/test-unit.md b/docs/guide-es/test-unit.md index 5cb43fef748..c6b47adfc61 100644 --- a/docs/guide-es/test-unit.md +++ b/docs/guide-es/test-unit.md @@ -1,25 +1,25 @@ -Tests de Unidad -=============== +Pruebas unitarias +================= -> Note: Esta sección se encuentra en desarrollo. +Un test unitario se encarga de verificar que una unidad simple de código funcione como se espera. +Esto decir, dados diferentes parámetros de entrada, el test verifica que el método +de la clase devuelve el resultado esperado. +Normalmente los tests unitarios son desarrollados por la persona que escribe las clases testeadas. -Un test de unidad se encarga de verificar que una unidad simple de código funcione como se espera. En la programación orientada a objetos, -la unidad de código más básica es una clase. Por lo tanto, un test de unidad necesita verificar que cada método de la interfaz de la clase funciona apropiadamente. -Esto quiere decir que, dando diferentes parámetros de entrada, el test verifica que el método devuelve el resultado esperado. -Los tests de unidad son normalmente desarrollados por la persona que escribe las clases siendo testeadas. +Los tests unitarios en Yii están construidos en base a PHPUnit y, opcionalmente, Codeception, por lo que se recomienda consultar su respectiva documentación: -Los tests de unidad en Yii están construidos en base a PHPUnit y opcionalmente, Codeception, por lo que se recomineda consultar su respectiva documentación: +- [Codeception para el _framework_ Yii](http://codeception.com/for/yii) +- [Tests unitarios con Codeception](http://codeception.com/docs/05-UnitTests) +- [Documentación de PHPUnit, empezando por el capítulo 2](http://phpunit.de/manual/current/en/writing-tests-for-phpunit.html) -- [Documentación de PHPUnit comienza en el capítulo 2](http://phpunit.de/manual/current/en/writing-tests-for-phpunit.html). -- [Tests de Unidad con Codeception](http://codeception.com/docs/05-UnitTests). +## Ejecución de tests en las plantillas básica y avanzada -Ejecutar test de unidad de templates básicos y avanzados --------------------------------------------------------- +Si ha empezado con la plantilla avanzada, consulte la [guía de testeo](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/start-testing.md) +para más detalles sobre la ejecución de tests. -Por favor consulta las instrucciones provistas en `apps/advanced/tests/README.md` y `apps/basic/tests/README.md`. +Si ha empezado con la plantilla básica, consulte la [sección sobre testeo de su README](https://github.com/yiisoft/yii2-app-basic/blob/master/README.md#testing). -Test de unidad del Framework ----------------------------- +##Tests unitarios del framework -Si quieres ejecutar tests de unidad para Yii en sí, consulta -"[Comenzando a desarrollar con Yii 2](https://github.com/yiisoft/yii2/blob/master/docs/internals/getting-started.md)". +Si desea ejecutar tests unitarios para el framework Yii en sí, consulte +«[Comenzando con el desarrollo de Yii 2](https://github.com/yiisoft/yii2/blob/master/docs/internals/getting-started.md)». diff --git a/docs/guide-es/translators.json b/docs/guide-es/translators.json index e5431ad8eac..ab94ea2b107 100644 --- a/docs/guide-es/translators.json +++ b/docs/guide-es/translators.json @@ -1,6 +1,7 @@ [ "Antonio Ramirez", "Daniel Gómez Pan", + "Enrique Matías Sánchez (Quique)", "'larnu'", "Luciano Baraglia" -] \ No newline at end of file +] diff --git a/docs/guide-fr/concept-aliases.md b/docs/guide-fr/concept-aliases.md index 745390ac4d6..2d5f22a9f1b 100644 --- a/docs/guide-fr/concept-aliases.md +++ b/docs/guide-fr/concept-aliases.md @@ -16,6 +16,10 @@ Yii::setAlias('@foo', '/path/to/foo'); // un alias pour une URL Yii::setAlias('@bar', 'http://www.example.com/'); + + +// un alias de fichier concrêt qui contient une classe \foo\Bar +Yii::setAlias('@foo/Bar.php', '/definitely/not/foo/Bar.php'); ``` > Note: le chemin de fichier ou l'URL pour qui un alias est créé peut *ne pas* nécessairement faire référence à un fichier ou une ressource existante. diff --git a/docs/guide-fr/concept-autoloading.md b/docs/guide-fr/concept-autoloading.md index 708fec14cfd..a33280ff834 100644 --- a/docs/guide-fr/concept-autoloading.md +++ b/docs/guide-fr/concept-autoloading.md @@ -25,6 +25,10 @@ Lorsque vous utilisez le [modèle de projet *basic*](start-installation.md), vou Dans le [modèle de projet avancé](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/README.md), chaque niveau possède son propre alias. Par exemple, le niveau « interface utilisateur » a l'alias `@frontend`, tandis que le niveau « interface d'administration » a l'alias `@backend`. En conséquence, vous pouvez mettre les classes de l'interface utilisateur sous l'espace de noms `frontend`, tandis que les classes de l'interface d'administration sont sous l'espace de noms `backend`. Cela permet à ces classes d'être chargées automatiquement par le chargeur automatique de Yii. +Pour ajouter un espace de noms personnalisé au chargeur automatique, vous devez définir un alias pour le dossier de base de l'espace de noms en utilisant [[Yii::setAlias()]]. +Par exemple, pour charger des classes de l'espace de noms `foo` qui se trouvent dans le dossier `path/to/foo`, vous appelez `Yii::setAlias('@foo', 'path/to/foo')`. + + Table de mise en correspondance des classes ------------------------------------------- diff --git a/docs/guide-fr/concept-components.md b/docs/guide-fr/concept-components.md index fe3db445b1d..9fb1ff0d26e 100644 --- a/docs/guide-fr/concept-components.md +++ b/docs/guide-fr/concept-components.md @@ -8,7 +8,7 @@ ou de ses classes filles. Les trois fonctionnalités principales fournies par le * [Les événements](concept-events.md) ; * [Les comportements](concept-behaviors.md). -Séparément et en combinaisons, ces fonctionnalités rendent les classes de Yii beaucoup plus personnalisables et faciles à utiliser. Par exemple, l'[[yii\jui\DatePicker|objet graphique de sélection de date]] inclus, un composant d'interface utilisateur, peut être utilisé dans une [vue](structure-view.md) pour générer un sélecteur de date interactif : +Séparément et en combinaisons, ces fonctionnalités rendent les classes de Yii beaucoup plus personnalisables et faciles à utiliser. Par exemple, l'[[yii\jui\DatePicker|objet graphique de sélection de date]] inclus, un composant d'interface utilisateur, peut être utilisé dans une [vue](structure-views.md) pour générer un sélecteur de date interactif : ```php use yii\jui\DatePicker; @@ -27,7 +27,7 @@ Tandis que les composants sont très puissants, ils sont un peu plus lourds que Lorsque votre classe étend la classe [[yii\base\Component]] ou [[yii\base\BaseObject]], il est recommandé que suiviez ces conventions : -- Si vous redéfinissez le constructeur, spécifiez un paramètre `$config` en tant que *dernier* paramètre du constructeur est passez le au constructeur du parent. +- Si vous redéfinissez le constructeur, spécifiez un paramètre `$config` en tant que *dernier* paramètre du constructeur et passez le au constructeur du parent. - Appelez toujours le constructeur du parent *à la fin* de votre constructeur redéfini. - Si vous redéfinissez la méthode [[yii\base\BaseObject::init()]], assurez-vous que vous appelez la méthode `init()` mise en œuvre par le parent *au début* de votre méthodes `init()`. diff --git a/docs/guide-fr/concept-configurations.md b/docs/guide-fr/concept-configurations.md index baa5500024c..92192ec0f59 100644 --- a/docs/guide-fr/concept-configurations.md +++ b/docs/guide-fr/concept-configurations.md @@ -114,6 +114,27 @@ La configuration n'a pas de clé `class`. Cela tient au fait qu'elle est utilis Plus de détails sur la configuration de la propriété `components` d'une application sont donnés dans la section [Applications](structure-applications.md) et dans la section [Localisateur de services](concept-service-locator.md). +Depuis la version 2.0.11, la configuration de l'application prend en charge la configuration du [Conteneur d'injection de dépendances](concept-di-container.md) +via la propriété `container`. Par exemple : + +```php +$config = [ + 'id' => 'basic', + 'basePath' => dirname(__DIR__), + 'extensions' => require __DIR__ . '/../vendor/yiisoft/extensions.php', + 'container' => [ + 'definitions' => [ + 'yii\widgets\LinkPager' => ['maxButtonCount' => 5] + ], + 'singletons' => [ + // Configuration du singleton Dependency Injection Container + ] + ] +]; +``` + +Pour en savoir plus sur les valeurs possibles des tableaux de configuration de `definitions` et `singletons` et avoir des exemples de la vie réelle, reportez-vous à la sous-section [Utilisation pratique avancée](concept-di-container.md#advanced-practical-usage) de l'article +[Conteneur d'injection de dépendances](concept-di-container.md). ### Configurations des objets graphiques @@ -190,7 +211,7 @@ $config = require 'path/to/web.php'; La méthode [[Yii::createObject()]] est implémentée sur la base du [conteneur d'injection de dépendances](concept-di-container.md). Cela vous permet de spécifier un jeu de configurations dites *configurations par défaut* qui seront appliquées à TOUTES les instances des classes spécifiées lors de leur création en utilisant [[Yii::createObject()]]. Les configurations par défaut peuvent être spécifiées en appelant `Yii::$container->set()` dans le code d'[amorçage](runtime-bootstrapping.md). -Par exemple, si vous voulez personnaliser l'objet graphique [[yii\widgets\LinkPager]] de façon à ce que TOUS les pagineurs affichent au plus 5 boutons de page (la valeur par défaut est 10), vous pouvez utiliser le code suivant pour atteindre ce but : +Par exemple, si vous voulez personnaliser l'objet graphique [[yii\widgets\LinkPager]] de façon à ce que TOUS les fonctions de mise en page (pagers) affichent au plus 5 boutons de page (la valeur par défaut est 10), vous pouvez utiliser le code suivant pour atteindre ce but : ```php \Yii::$container->set('yii\widgets\LinkPager', [ diff --git a/docs/guide-fr/concept-di-container.md b/docs/guide-fr/concept-di-container.md index 0aeb060bb93..883699d2640 100644 --- a/docs/guide-fr/concept-di-container.md +++ b/docs/guide-fr/concept-di-container.md @@ -92,7 +92,7 @@ $container->get('Foo', [], [ ]); ``` -> Info: la méthode [[yii\di\Container::get()]] accepte un tableau de configuration qui peut être appliqué à l'objet en création comme troisième paramètre. Si la classe implémente l'interface [[yii\base\Configurable]] (p. ex. [[yii\base\BaseObject]]), le tableau de configuration est passé en tant que dernier paramètre du constructeur de la classe ; autrement le tableau de configuration serait appliqué *après* la création de l'objet. +> Info: la méthode [[yii\di\Container::get()]] accepte un tableau de configurations qui peut être appliqué à l'objet en création comme troisième paramètre. Si la classe implémente l'interface [[yii\base\Configurable]] (p. ex. [[yii\base\BaseObject]]), le tableau de configuration est passé en tant que dernier paramètre du constructeur de la classe ; autrement le tableau de configuration serait appliqué *après* la création de l'objet. ### Injection par une méthode de rappel PHP @@ -198,7 +198,8 @@ Résolution des dépendances Une fois que vous avez enregistré des dépendances, vous pouvez utiliser le conteneur d'injection de dépendances pour créer de nouveau objets, et le conteneur résout automatiquement les dépendances en les instanciant et en les injectant dans les nouveaux objets. Le résolution des dépendances est récursive, ce qui signifie que si une dépendance a d'autres dépendances, ces dépendances sont aussi résolue automatiquement. -Vous pouvez utiliser [[yii\di\Container::get()]] pour créer de nouveaux objets. La méthode accepte un nom de dépendance qui peut être un nom de classe, un nom d'interface ou un nom d'alias. Le nom de dépendance, peut être, ou ne pas être, enregistré via `set()` ou `setSingleton()`. En option, vous pouvez fournir une liste de paramètre du constructeur de la classe et une [configuration](concept-configurations.md) pour configurer l'objet nouvellement créé. Par exemple : +Vous pouvez utiliser [[yii\di\Container::get()]] soit pour créer, soit pour obtenir une instance d'un objet. La méthode accepte un nom de dépendance qui peut être un nom de classe, un nom d'interface ou un nom d'alias. Le nom de dépendance, peut être enregistré [[yii\di\Container::set()|set()]] +ou [[yii\di\Container::setSingleton()|setSingleton()]]. En option, vous pouvez fournir une liste de paramètres du constructeur de la classe et une [configuration](concept-configurations.md) pour configurer l'objet nouvellement créé. Par exemple : ```php // "db" est un nom d'alias enregistré préalablement @@ -272,9 +273,9 @@ $lister = new UserLister($finder); Utilisation pratique -------------------- -Yii crée un conteneur d'injection de dépendances lorsque vous incluez le fichier `Yii.php` dans le [script d'entrée](structure-entry-scripts.md) de votre application. Le conteneur d'injection de dépendances est accessible via [[Yii::$container]]. Lorsque vous appelez [[Yii::createObject()]], la méthode appelle en réalité la méthode [[yii\di\Container::get()|get()]] du conteneur pour créer le nouvel objet. Comme c'est dit plus haut, le conteneur d'injection de dépendances résout automatiquement les dépendances (s'il en existe) et les injecte dans l'objet créé. Parce que Yii utilise [[Yii::createObject()]] dans la plus grande partie du code de son noyau pour créer de nouveaux objets, cela signifie que vous pouvez personnaliser ces objets globalement en utilisant [[Yii::$container]]. +Yii crée un conteneur d'injection de dépendances lorsque vous incluez le fichier `Yii.php` dans le [script d'entrée](structure-entry-scripts.md) de votre application. Le conteneur d'injection de dépendances est accessible via [[Yii::$container]]. Lorsque vous appelez [[Yii::createObject()]], la méthode appelle en réalité la méthode [[yii\di\Container::get()|get()]] du conteneur pour créer le nouvel objet. Comme c'est dit plus haut, le conteneur d'injection de dépendances résout automatiquement les dépendances (s'il en existe) et les injecte dans l'objet obtenu. Parce que Yii utilise [[Yii::createObject()]] dans la plus grande partie du code de son noyau pour créer de nouveaux objets, cela signifie que vous pouvez personnaliser ces objets globalement en utilisant [[Yii::$container]]. -Par exemple, vous pouvez personnaliser globalement le nombre de boutons de pagination par défaut de l'objet graphique [[yii\widgets\LinkPager]] : +Par exemple, personnalisons globalement le nombre de boutons de pagination par défaut de l'objet graphique [[yii\widgets\LinkPager]] : ```php \Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]); @@ -321,6 +322,132 @@ Si vous accédez au contrôleur à partir du navigateur, vous verrez un message Maintenant, si vous accédez à nouveau au contrôleur, une instance de `app\components\BookingService` est créée et injectée en tant que troisième paramètre du constructeur. +Utilisation pratique avancée +--------------- + +Supposons que nous travaillions sur l'API de l'application et ayons :S + +- la classe `app\components\Request` qui étende `yii\web\Request` et fournisse une fonctionnalité additionnelle, +- la classe `app\components\Response` qui étende `yii\web\Response` et devrait avoir une propriété `format` définie à `json` à la création, +- des classes `app\storage\FileStorage` et `app\storage\DocumentsReader` qui mettent en œuvre une certaine logique pour travailler sur des documents qui seraient situés dans un dossier : + + + ```php + class FileStorage + { + public function __construct($root) { + // whatever + } + } + + class DocumentsReader + { + public function __construct(FileStorage $fs) { + // whatever + } + } + ``` + +Il est possible de configurer de multiples définitions à la fois, en passant un tableau de configurations à la méthode +[[yii\di\Container::setDefinitions()|setDefinitions()]] ou à la méthode [[yii\di\Container::setSingletons()|setSingletons()]]. +En itérant sur le tableau de configuration, les méthodes appellent [[yii\di\Container::set()|set()]] +ou [[yii\di\Container::setSingleton()|setSingleton()]] respectivement pour chacun des items. + +Le format du tableau de configurations est : + + - `key`: nom de classe, nom d'interface ou alias. La clé est passée à la méthode + [[yii\di\Container::set()|set()]] comme premier argument `$class`. + - `value`: la définition associée à `$class`. Les valeurs possibles sont décrites dans la documentation [[yii\di\Container::set()|set()]] + du paramètre `$definition`. Est passé à la méthode [[set()]] comme deuxième argument `$definition`. + +Par exemple, configurons notre conteneur pour répondre aux exigences mentionnées précédemment : + +```php +$container->setDefinitions([ + 'yii\web\Request' => 'app\components\Request', + 'yii\web\Response' => [ + 'class' => 'app\components\Response', + 'format' => 'json' + ], + 'app\storage\DocumentsReader' => function ($container, $params, $config) { + $fs = new app\storage\FileStorage('/var/tempfiles'); + return new app\storage\DocumentsReader($fs); + } +]); + +$reader = $container->get('app\storage\DocumentsReader'); +// Crée un objet DocumentReader avec ses dépendances tel que décrit dans la configuration. +``` + +> Tip: le conteneur peut être configuré dans le style déclaratif en utilisant la configuration de l'application depuis la version 2.0.11. +Consultez la sous-section [Configurations des applications](concept-configurations.md#application-configurations) de l'article du guide [Configurations](concept-configurations.md). + +Tout fonctionne, mais au cas où, nous devons créer une classe `DocumentWriter`, nous devons copier-coller la ligne qui crée un objet `FileStorage`, ce qui n'est pas la manière la plus élégante, c'est évident. + + +Comme cela est décrit à la sous-section [Résolution des dépendances](#resolving-dependencies) subsection, [[yii\di\Container::set()|set()]] +et [[yii\di\Container::setSingleton()|setSingleton()]] peuvent facultativement des paramètres du constructeur de dépendances en tant que troisième argument. Pour définir les paramètres du constructeur, vous pouvez utiliser le format de tableau de configuration suivant : + + - `key`: nom de classe, nom d'interface ou alias. La clé est passée à la méthode + [[yii\di\Container::set()|set()]] comme premier argument `$class`. + - `value`: un tableau de deux éléments. Le premier élément est passé à la méthode [[yii\di\Container::set()|set()]] comme deuxième argument `$definition`, le second — comme `$params`. + +Modifions notre exemple : + +```php +$container->setDefinitions([ + 'tempFileStorage' => [ // we've created an alias for convenience + ['class' => 'app\storage\FileStorage'], + ['/var/tempfiles'] // pourrait être extrait de certains fichiers de configuration + ], + 'app\storage\DocumentsReader' => [ + ['class' => 'app\storage\DocumentsReader'], + [Instance::of('tempFileStorage')] + ], + 'app\storage\DocumentsWriter' => [ + ['class' => 'app\storage\DocumentsWriter'], + [Instance::of('tempFileStorage')] + ] +]); + +$reader = $container->get('app\storage\DocumentsReader); +// Se comporte exactement comme l'exemple précédent +``` + +Vous noterez la notation `Instance::of('tempFileStorage')`. cela siginifie que le [[yii\di\Container|Container]] fournit implicitement une dépendance enregistrée avec le nom de `tempFileStorage` et la passe en tant que premier argument du constructeur +of `app\storage\DocumentsWriter`. + +> Note: [[yii\di\Container::setDefinitions()|setDefinitions()]] and [[yii\di\Container::setSingletons()|setSingletons()]] + methods are available since version 2.0.11. + +Une autre étape de l'optimisation de la configuration est d'enregistrer certaines dépendances sous forme de singletons. +Une dépendance enregistrée via [[yii\di\Container::set()|set()]] est instanciée à chaque fois qu'on en a besoin. +Certaines classes ne changent pas l'état au moment de l'exécution, par conséquent elles peuvent être enregistrées sous forme de singletons afin d'augmenter la performance de l'application. + +Un bon exemple serait la classe `app\storage\FileStorage`, qui effectue certaines opérations sur le système de fichiers avec une API simple (p. ex. `$fs->read()`, `$fs->write()`). Ces opération ne changent pas l'état interne de la classe, c'est pourquoi nous pouvons créer son instance une seule fois et l'utiliser de multiples fois. + +```php +$container->setSingletons([ + 'tempFileStorage' => [ + ['class' => 'app\storage\FileStorage'], + ['/var/tempfiles'] + ], +]); + +$container->setDefinitions([ + 'app\storage\DocumentsReader' => [ + ['class' => 'app\storage\DocumentsReader'], + [Instance::of('tempFileStorage')] + ], + 'app\storage\DocumentsWriter' => [ + ['class' => 'app\storage\DocumentsWriter'], + [Instance::of('tempFileStorage')] + ] +]); + +$reader = $container->get('app\storage\DocumentsReader'); +``` + À quel moment enregistrer les dépendances ----------------------------------------- diff --git a/docs/guide-fr/concept-events.md b/docs/guide-fr/concept-events.md index 3d3afcc2d57..d4508d9e5a4 100644 --- a/docs/guide-fr/concept-events.md +++ b/docs/guide-fr/concept-events.md @@ -3,7 +3,7 @@ Les événement vous permettent d'injecter du code personnalisé dans le code existant à des points précis de son exécution. Vous pouvez attacher du code personnalisé à un événement de façon à ce que, lorsque l'événement est déclenché, le code s'exécute automatiquement. Par exemple, un objet serveur de courriel peut déclencher un événement `messageSent` (message envoyé) quand il réussit à envoyer un message. Si vous voulez conserver une trace des messages dont l'envoi a réussi, vous pouvez simplement attacher le code de conservation de la trace à l'événement `messageSent`. -Yii introduit une classe de base appelée [[yii\base\Component]] pour prendre en charge les événements. Si une classe a besoin de déclencher des événements, elle doit êtendre la classe [[yii\base\Component]], ou une de ses classes filles. +Yii introduit une classe de base appelée [[yii\base\Component]] pour prendre en charge les événements. Si une classe a besoin de déclencher des événements, elle doit étendre la classe [[yii\base\Component]], ou une de ses classes filles. Gestionnaires d'événements @@ -12,7 +12,7 @@ Gestionnaires d'événements Un gestionnaire d'événement est une [fonction de rappel PHP](http://www.php.net/manual/en/language.types.callable.php) qui est exécutée lorsque l'événement à laquelle elle est attachée est déclenché. Vous pouvez utiliser n'importe laquelle des fonctions de rappel suivantes : - une fonction PHP globale spécifiée sous forme de chaîne de caractères (sans les parenthèses) p. ex., `'trim'` ; -- une méthode d'objet spécifiée sous forme de tableau constitué d'un nom d'objet et d'un nom de méthode sous forme de chaîne de caractères (sans les parentèses), p. ex., `[$object, 'methodName']`; +- une méthode d'objet spécifiée sous forme de tableau constitué d'un nom d'objet et d'un nom de méthode sous forme de chaîne de caractères (sans les parenthèses), p. ex., `[$object, 'methodName']`; - une méthode d'une classe statique spécifiée sous forme de tableau constitué d'un nom de classe et d'un nom de méthode sous forme de chaîne de caractères (sans les parenthèses), p. ex., `['ClassName', 'methodName']`; - une fonction anonyme p. ex., `function ($event) { ... }`. @@ -37,7 +37,7 @@ Attacher des gestionnaires d'événements on(Foo::EVENT_HELLO, 'function_name'); @@ -57,7 +57,7 @@ $foo->on(Foo::EVENT_HELLO, function ($event) { Vous pouvez aussi attacher des gestionnaires d'événements via les [configurations](concept-configurations.md). Pour plus de détails, reportez-vous à la section [Configurations](concept-configurations.md#configuration-format). -Losque vous attachez un gestionnaire d'événement, vous pouvez fournir des données additionnelles telles que le troisième paramètre de [[yii\base\Component::on()]]. Les données sont rendues disponibles au gestionnaire lorsque l'événement est déclenché et que le gestionnaire est appelé. Par exemple : +Lorsque vous attachez un gestionnaire d'événement, vous pouvez fournir des données additionnelles telles que le troisième paramètre de [[yii\base\Component::on()]]. Les données sont rendues disponibles au gestionnaire lorsque l'événement est déclenché et que le gestionnaire est appelé. Par exemple : ```php // Le code suivant affiche "abc" lorsque l'événement est déclenché @@ -72,7 +72,7 @@ function function_name($event) { Ordre des gestionnaires d'événements ------------------------------------ -Vous pouvez attacher un ou plusieurs gestionnaires à un seul événement. Lorsqu'un événement est déclenché, les gestionnaires attachés sont appelés dans l'ordre dans lequel ils ont été attachés à l'événement. Si un gestionnaire a besoin d'arrêter l'appel des gestionnaires qui viennent après lui, il doit définir la propriété [[yii\base\Event::handled (géré)]] du paramètre `$event` parameter à `true`: +Vous pouvez attacher un ou plusieurs gestionnaires à un seul événement. Lorsqu'un événement est déclenché, les gestionnaires attachés sont appelés dans l'ordre dans lequel ils ont été attachés à l'événement. Si un gestionnaire a besoin d'arrêter l'appel des gestionnaires qui viennent après lui, il doit définir la propriété [[yii\base\Event::handled (géré)]] du paramètre `$event` à `true`: ```php $foo->on(Foo::EVENT_HELLO, function ($event) { @@ -111,7 +111,7 @@ class Foo extends Component ``` Avec le code précédent, tout appel à `bar()` déclenche un événement nommé `hello`. -> Tip: il est recommandé d'utiliser des constantes de classe pour représenter les noms d'événement. Dans l'exemple qui précède, la constante `EVENT_HELLO` représente l'événement `hello`. Cette approche procure trois avantages. Primo, elle évite les erreurs de frappe. Secondo, elle permet aux événements d'être reconnus par le mécanisme d'auto-complètement des EDI. Tertio, vous pouvez dire quels événements sont pris en charge par une classe en vérifiant la déclaration de ses constantes. +> Tip: il est recommandé d'utiliser des constantes de classe pour représenter les noms d'événement. Dans l'exemple qui précède, la constante `EVENT_HELLO` représente l'événement `hello`. Cette approche procure trois avantages. Primo, elle évite les erreurs de frappe. Secundo, elle permet aux événements d'être reconnus par le mécanisme d'auto-complètement des EDI. Tertio, vous pouvez dire quels événements sont pris en charge par une classe en vérifiant la déclaration de ses constantes. Parfois, lors du déclenchement d'un événement, vous désirez passer des informations additionnelles aux gestionnaires de cet événement. Par exemple, un serveur de courriels peut souhaiter passer les informations sur le message aux gestionnaires de l'événement `messageSent` pour que ces derniers soient informés de certaines particularités des messages envoyés. Pour ce faire, vous pouvez fournir un objet événement comme deuxième paramètre de la méthode [[yii\base\Component::trigger()]]. L'objet événement doit simplement être une instance de la classe [[yii\base\Event]] ou d'une de ses classes filles. Par exemple : @@ -163,7 +163,7 @@ $foo->off(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']); $foo->off(Foo::EVENT_HELLO, $anonymousFunction); ``` -Notez qu'en général, vous ne devez pas essayer de détacher une fonction anonyme sauf si vous l'avez stokée quelque part lorsque vous l'avez attachée à un événement. Dans l'exemple ci-dessus, on suppose que la fonctions anonyme est stockée dans une variable nommée `$anonymousFunction`. +Notez qu'en général, vous ne devez pas essayer de détacher une fonction anonyme sauf si vous l'avez stockée quelque part lorsque vous l'avez attachée à un événement. Dans l'exemple ci-dessus, on suppose que la fonctions anonyme est stockée dans une variable nommée `$anonymousFunction`. Pour détacher *tous* les gestionnaires d'un événement, appelez simplement la méthode [[yii\base\Component::off()]] sans le deuxième paramètre : @@ -192,7 +192,7 @@ Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function Le gestionnaire d'événement est invoqué à chaque fois qu'une instance de la classe [[yii\db\ActiveRecord|ActiveRecord]], ou d'une de ses classes filles, déclenche l'événement [[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]]. Dans le gestionnaire, vous pouvez obtenir l'objet qui a déclenché l'événement via `$event->sender`. -Losqu'un objet déclenche un événement, il commence par appeler les gestionnaires attachés au niveau de l'instance, puis les gestionnaires attachés au niveau de la classe. +Lorsqu'un objet déclenche un événement, il commence par appeler les gestionnaires attachés au niveau de l'instance, puis les gestionnaires attachés au niveau de la classe. Vous pouvez déclencher un événement au *niveau de la classe* en appelant la méthode statique [[yii\base\Event::trigger()]]. Un événement déclenché au niveau de la classe n'est associé à aucun objet en particulier. En conséquence, il provoque l'appel des gestionnaires attachés au niveau de la classe seulement. Par exemple : @@ -259,7 +259,7 @@ class Developer extends Component implements DanceEventInterface } ``` -Pour gérer l'évenement `EVENT_DANCE` déclenché par n'importe laquelle de ces classes, appelez [[yii\base\Event::on()|Event::on()]] et passez-lui le nom de l'interface comme premier argument : +Pour gérer l'événement `EVENT_DANCE` déclenché par n'importe laquelle de ces classes, appelez [[yii\base\Event::on()|Event::on()]] et passez-lui le nom de l'interface comme premier argument : ```php Event::on('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) { @@ -317,3 +317,70 @@ Yii::$app->trigger('bar', new Event(['sender' => new Foo])); Un avantage de l'utilisation d'événement globaux est que vous n'avez pas besoin d'un objet lorsque vous attachez un gestionnaire à l'événement qui est déclenché par l'objet. Au lieu de cela, vous attachez le gestionnaire et déclenchez l'événement via le singleton (p. ex. l'instance d'application). Néanmoins, parce que l'espace de noms des événements globaux est partagé par toutes les parties, vous devez nommer les événements globaux avec prudence, par exemple en introduisant une sorte d'espace de noms (p. ex. "frontend.mail.sent", "backend.mail.sent"). + +Événements génériques +--------------------- + +Depuis la version 2.0.14, vous pouvez définir un gestionnaire d'événement pour de multiples événement correspondant à un motif générique. +Par exemple: + +```php +use Yii; + +$foo = new Foo(); + +$foo->on('foo.event.*', function ($event) { + // déclenché pour tout événement dont le nom commence par 'foo.event.' + Yii::debug('trigger event: ' . $event->name); +}); +``` + +Les motifs génériques peuvent être utilisés pour des événements au niveau de la classe. Par exemple : + +```php +use yii\base\Event; +use Yii; + +Event::on('app\models\*', 'before*', function ($event) { + // déclenché pour toute classe de l'espace de noms 'app\models' pour tout événement dont le nom commence par 'before' + Yii::debug('trigger event: ' . $event->name . ' for class: ' . get_class($event->sender)); +}); +``` + +Cela vous permet d'attraper tous les événement de l'application par un unique gestionnaire en utilisant le code suivant : + +```php +use yii\base\Event; +use Yii; + +Event::on('*', '*', function ($event) { + // déclenché pour tout événement de n'importe quelle classe + Yii::debug('trigger event: ' . $event->name); +}); +``` + +> Note: l'utilisation de motifs génériques pour la définition des gestionnaires d'événement peut réduire la performance de l'application . Il vaut mieux l'éviter si possible. + +Afin de détacher un gestionnaire d'événement spécifié par un motif générique, vous devez répéter le même motif en invoquant +[[yii\base\Component::off()]] ou [[yii\base\Event::off()]]. Soyez conscient que le passage d'un motif générique lors du détachement d'un gestionnaire d'événement ne détache que le gestionnaire attaché avec ce motif, tandis que les gestionnaires attachés par des noms réguliers d'événement resteront attachés même si leur nom correspond au motif. Par exemple : + +```php +use Yii; + +$foo = new Foo(); + +// attache un gestionnaire de façon régulière +$foo->on('event.hello', function ($event) { + echo 'direct-handler' +}); + +// attache un gestionnaire par un motif générique +$foo->on('*', function ($event) { + echo 'wildcard-handler' +}); + +// ne détache que le gestionnaire attaché par le motif générique +$foo->off('*'); + +$foo->trigger('event.hello'); // outputs: 'direct-handler' +``` diff --git a/docs/guide-fr/concept-properties.md b/docs/guide-fr/concept-properties.md index 897dd662aef..1c171bfef9d 100644 --- a/docs/guide-fr/concept-properties.md +++ b/docs/guide-fr/concept-properties.md @@ -7,7 +7,7 @@ En PHP, les variables membres des classes sont aussi appelées *propriétés*. C $object->label = trim($label); ``` -Le revers du code ci-dessus est que vous devez appeler `trim()` partout ou vous voulez définir la propriété `label`. Si, plus tard, la propriété `label` devient sujette à de nouvelles exigences, telles que la première lettre doit être une capitale, vous auriez à modifier toutes les parties de code qui assigne une valeur à la propriété `label`. La répétition de code conduit à des bogues, et c'est une pratique courant de l'éviter autant que faire se peut. +Le revers du code ci-dessus est que vous devez appeler `trim()` partout ou vous voulez définir la propriété `label`. Si, plus tard, la propriété `label` devient sujette à de nouvelles exigences, telles que la première lettre doit être une capitale, vous auriez à modifier toutes les parties de code qui assignent une valeur à la propriété `label`. La répétition de code conduit à des bogues, et c'est une pratique courante de l'éviter autant que faire se peut. Pour résoudre ce problème, Yii introduit une classe de base nommée [[yii\base\BaseObject]] qui prend en charge la définition de propriétés sur la base de méthodes d'obtention (*getter*) et de méthode d'assignation (*setters*). Si une classe a besoin de cette fonctionnalité, il suffit qu'elle étende la classe[[yii\base\BaseObject]], ou une de ses classes filles. @@ -52,9 +52,9 @@ Une propriété définie par une méthode d'obtention (*getter*) sans méthode d Il existe plusieurs règles spéciales pour les propriétés définies via des méthodes d'obtention et d'assignation, ainsi que certaines limitations sur elles. -* Le nom de telles propriétés sont *insensibles à la casse*. Par exempe, `$object->label` et `$object->Label` sont identiques. Cela est dû au fait que le nom des méthodes dans PHP est insensible à la casse. -* Si le nom d'uen telle propriété est identique à celui d'une variable membre de la classe, la dernier prévaut. Par exemple, si la classe ci-dessus `Foo` possède une variable mommée `label`, alors l'assignation `$object->label = 'abc'` affecte la *variable membre* `label` ; cette ligne ne fait pas appel à la méthode d'assignation `setLabel()`. -* Ces propriétés en prennent pas en charge la visibilité. Cela ne fait aucune différence pour les méthodes d'obtention et d'assignation qui définissent une propriété, que cette propriété soit publique, protégée ou privée. +* Le nom de telles propriétés sont *insensibles à la casse*. Par exemple, `$object->label` et `$object->Label` sont identiques. Cela est dû au fait que le nom des méthodes dans PHP est insensible à la casse. +* Si le nom d'une telle propriété est identique à celui d'une variable membre de la classe, le dernier prévaut. Par exemple, si la classe ci-dessus `Foo` possède une variable momée `label`, alors l'assignation `$object->label = 'abc'` affecte la *variable membre* `label` ; cette ligne ne fait pas appel à la méthode d'assignation `setLabel()`. +* Ces propriétés ne prennent pas en charge la visibilité. Cela ne fait aucune différence pour les méthodes d'obtention et d'assignation qui définissent une propriété, que cette propriété soit publique, protégée ou privée. * Les propriétés peuvent uniquement être définies par des méthodes d'obtention et d'assignation *non-statiques*. Les méthodes statiques ne sont pas traitées de la même manière. * Un appel normal à la méthode `property_exists()` ne fonctionne pas pour déterminer des propriétés magiques. Vous devez appeler [[yii\base\BaseObject::canGetProperty()|canGetProperty()]] ou [[yii\base\BaseObject::canSetProperty()|canSetProperty()]] respectivement. diff --git a/docs/guide-fr/concept-service-locator.md b/docs/guide-fr/concept-service-locator.md index 17873baa950..f844f6299a8 100644 --- a/docs/guide-fr/concept-service-locator.md +++ b/docs/guide-fr/concept-service-locator.md @@ -52,7 +52,7 @@ Lorsque vous accédez à un composant pour la première fois, [[yii\di\ServiceLo Vous pouvez utiliser [[yii\di\ServiceLocator::has()]] pour savoir si un identifiant de composant a déjà été enregistré. Si vous appelez [[yii\di\ServiceLocator::get()]] avec un identifiant invalide, une exception est levée. -Comme les localisateurs de services sont souvent créés avec des [configurations](concept-configurations.md), une propriété accessible en écriture, et nommée [[yii\di\ServiceLocator::setComponents()|components]], est fournie. Cela vous permet de configurer et d'enregistrer plusieurs composants à la fois. Le code suivant montre un tableau de configuration qui peut être utilisé pour configurer un localisateur de services (p. ex. une [application](structure-applications.md)) avec les composants `db`, `cache` et `search` : +Comme les localisateurs de services sont souvent créés avec des [configurations](concept-configurations.md), une propriété accessible en écriture, et nommée [[yii\di\ServiceLocator::setComponents()|components]], est fournie. Cela vous permet de configurer et d'enregistrer plusieurs composants à la fois. Le code suivant montre un tableau de configuration qui peut être utilisé pour configurer un localisateur de services (p. ex. une [application](structure-applications.md)) avec les composants `db`, `cache`, `tz` et `search` : ```php return [ @@ -65,6 +65,9 @@ return [ 'password' => '', ], 'cache' => 'yii\caching\ApcCache', + 'tz' => function() { + return new \DateTimeZone(Yii::$app->formatter->defaultTimeZone); + }, 'search' => function () { $solr = new app\components\SolrService('127.0.0.1'); // ... other initializations ... @@ -99,3 +102,13 @@ return [ ``` Cette approche alternative est à utiliser de préférence lorsque vous publiez une composant Yii qui encapsule quelques bibliothèques de tierces parties. Vous utilisez la méthode statique comme c'est montré ci-dessus pour représenter la logique complexe de construction de l'objet de tierce partie, et l'utilisateur de votre composant doit seulement appeler la méthode statique pour configurer le composant. + +## Parcours d'un arbre + +Les modules acceptent les inclusions arbitraires; une application Yii est essentiellement un arbre de modules. Comme chacun de ces modules est un localisateur de services, cela a du sens pour les enfants d'accéder à leur parent. +Cela permet aux modules d'utiliser `$this->get('db')` au lieu de faire référence au localisateur de services racine `Yii::$app->get('db')`. +Un bénéficie supplémentaire pour le développeur est de pouvoir redéfinir la configuration dans un module. + +Toute requête d'un service à l'intérieur d'un module est passée à son parent dans le cas où le module lui-même est incapable de la satisfaire. + +Notez que la configuration depuis des composants dans un module n'est jamais fusionnée avec celle depuis un composant du module parent. Le modèle de localisateur de services nous permet de définir des services nommés mais on ne peut supposer que des services du même nom utilisent les mêmes paramètres de configuration. diff --git a/docs/guide-fr/db-active-record.md b/docs/guide-fr/db-active-record.md index c10135eafd0..95c9ecfa08b 100644 --- a/docs/guide-fr/db-active-record.md +++ b/docs/guide-fr/db-active-record.md @@ -1,9 +1,16 @@ Enregistrement actif (*Active Record*) ===================================== -L'[enregistrement actif](http://en.wikipedia.org/wiki/Active_record_pattern) fournit une interface orientée objet pour accéder aux données stockées dans une base de données et les manipuler. Une classe d'enregistrement actif est associée à une table de base de données, une instance de cette classe représente une ligne de cette table, et un *attribut* d'une instance d'enregistrement actif représente la valeur d'une colonne particulière dans cette ligne. Au lieu d'écrire des instructions SQL brutes, vous pouvez accéder aux attributs de l'objet enregistrement actif et appeler ses méthodes pour accéder aux données stockées dans les tables de la base de données et les manipuler. +L'[enregistrement actif](http://en.wikipedia.org/wiki/Active_record_pattern) fournit une interface orientée objet pour accéder aux données stockées dans une base de données et les manipuler. +Une classe d'enregistrement actif (ActiveRecord) est associée à une table de base de données, une instance de cette classe représente une ligne de cette table, et un *attribut* d'une instance d'enregistrement actif représente la valeur d'une colonne particulière dans cette ligne. +Au lieu d'écrire des instructions SQL brutes, +vous pouvez accéder aux attributs de l'objet enregistrement actif et appeler ses méthodes pour accéder aux données stockées dans les tables de la base de données et les manipuler. + + + +Par exemple, supposons que `Customer` soit une classe d'enregistrement actif associée à la table `customer` et que `name` soit une colonne de la table `customer`. +Vous pouvez écrire le code suivant pour insérer une nouvelle ligne dans la table `customer` : -Par exemple, supposons que `Customer` soit une classe d'enregistrement actif associée à la table `customer` et que `name` soit une colonne de la table `customer`. Vous pouvez écrire le code suivant pour insérer une nouvelle ligne dans la table `customer` : ```php $customer = new Customer(); @@ -13,6 +20,7 @@ $customer->save(); Le code ci-dessus est équivalent à l'utilisation de l'instruction SQL brute suivante pour MySQL, qui est moins intuitive, plus propice aux erreurs, et peut même poser des problèmes de compatibilité sur vous utilisez un système de gestion de base données différent. + ```php $db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [ ':name' => 'Qiang', @@ -26,7 +34,8 @@ Yii assure la prise en charge de l'enregistrement actif (*Active Record*) pour l * SQLite 2 et 3 : via [[yii\db\ActiveRecord]] * Microsoft SQL Server 2008 ou versions postérieures : via [[yii\db\ActiveRecord]] * Oracle : via [[yii\db\ActiveRecord]] -* CUBRID 9.3 ou versions postérieures : via [[yii\db\ActiveRecord]] (Notez que, à cause d'un [bogue](http://jira.cubrid.org/browse/APIS-658) dans l'extension CUBRID 9:3, l'entourage des valeurs par des marques de citation ne fonctionne pas, c'est pourquoi vous avez besoin de CUBRID 9.3 à la fois comme client et comme serveur) +* CUBRID 9.3 ou versions postérieures : via [[yii\db\ActiveRecord]] + (Notez que, à cause d'un [bogue](http://jira.cubrid.org/browse/APIS-658) dans l'extension CUBRID 9.3, l'entourage des valeurs par des marques de citation ne fonctionne pas, c'est pourquoi vous avez besoin de CUBRID 9.3 à la fois comme client et comme serveur) * Sphinx : via [[yii\sphinx\ActiveRecord]], requiert l'extension `yii2-sphinx` * ElasticSearch : via [[yii\elasticsearch\ActiveRecord]], requiert l'extension `yii2-elasticsearch` @@ -35,13 +44,28 @@ De plus, Yii prend aussi en charge l'enregistrement actif (*Active Record*) avec * Redis 2.6.12 ou versions postérieures : via [[yii\redis\ActiveRecord]], requiert l'extension `yii2-redis` * MongoDB 1.3.0 ou versions postérieures: via [[yii\mongodb\ActiveRecord]], requiert l'extension `yii2-mongodb` -Dans ce tutoriel, nous décrivons essentiellement l'utilisation de l'enregistrement actif pour des bases de données relationnelles. Cependant, la majeure partie du contenu décrit ici est aussi applicable aux bases de données non SQL. +Dans ce tutoriel, nous décrivons essentiellement l'utilisation de l'enregistrement actif pour des bases de données relationnelles. +Cependant, la majeure partie du contenu décrit ici est aussi applicable aux bases de données non SQL. ## Déclaration des classes d'enregistrement actif (*Active Record*) -Pour commencer, déclarez une classe d'enregistrement actif en étendant la classe [[yii\db\ActiveRecord]]. Comme chacune des classes d'enregistrement actif est associée à une table de la base de données, dans cette classe, vous devez redéfinir la méthode [[yii\db\ActiveRecord::tableName()|tableName()]] -pour spécifier à quelle table cette classe est associée. Dans l'exemple qui suit, nous déclarons une classe d'enregistrement actif nommée `Customer` pour la table de base de données `customer`. +Pour commencer, déclarez une classe d'enregistrement actif en étendant la classe [[yii\db\ActiveRecord]]. + +### Définir un nom de table + +Par défaut, chacune des classes d'enregistrement actif est associée à une table de la base de données. +La méthode [[yii\db\ActiveRecord::tableName()|tableName()]] retourne le nom de la table en convertissant le nom via [[yii\helpers\Inflector::camel2id()]]. +Vous pouvez redéfinir cette méthode si le nom de la table ne suit pas cette convention. + +Un [[yii\db\Connection::$tablePrefix|préfixe de table]] par défaut peut également être appliqué. +Par exemple, si le [[yii\db\Connection::$tablePrefix|préfixe de table]] est `tbl_`, `Customer` devient `tbl_customer` et `OrderItem` devient `tbl_order_item`. + +Si un nom de table est fourni sous la forme `{{%TableName}}`, alors le caractère `%` est remplacé par le préfixe de table. +Par exemple, `{{%post}}` devient `{{tbl_post}}`. Les accolades autour du nom de table sont utilisées pour +[l'entourage par des marques de citation dans une requête SQL ](db-dao.md#quoting-table-and-column-names). + +Dans l'exemple suivant, nous déclarons une classe d'enregistrement actif nommée `Customer` pour la table de base de données `customer`. ```php namespace app\models; @@ -63,14 +87,21 @@ class Customer extends ActiveRecord } ``` -Les instances d'une classe d'enregistrement actif (*Active Record*) sont considérées comme des [modèles](structure-models.md). Pour cette raison, nous plaçons les classes d'enregistrement actif dans l'espace de noms `app\models`(ou autres espaces de noms prévus pour contenir des classes de modèles). +### Les enregistrements actifs sont appelés "modèles" -Comme la classe [[yii\db\ActiveRecord]] étend la classe [[yii\base\Model]], elle hérite de *toutes* les fonctionnalités d'un [modèle](structure-models.md), comme les attributs, les règles de validation, la sérialisation des données, etc. +Les instances d'une classe d'enregistrement actif (*Active Record*) sont considérées comme des [modèles](structure-models.md). + Pour cette raison, nous plaçons les classes d'enregistrement actif dans l'espace de noms `app\models`(ou autres espaces de noms prévus pour contenir des classes de modèles). + +Comme la classe [[yii\db\ActiveRecord]] étend la classe [[yii\base\Model]], +elle hérite de *toutes* les fonctionnalités d'un [modèle](structure-models.md), comme les attributs, les règles de validation, la sérialisation des données, etc. ## Connexion aux bases de données -Par défaut, l'enregistrement actif utilise le [composant d'application](structure-application-components.md) `db` en tant que [[yii\db\Connection|DB connexion à une base de données]] pour accéder aux données de la base de données et les manipuler. Comme expliqué dans la section [Objets d'accès aux bases de données](db-dao.md), vous pouvez configurer le composant `db` dans la configuration de l'application comme montré ci-dessous : +Par défaut, l'enregistrement actif utilise le [composant d'application](structure-application-components.md) `db` en tant que [[yii\db\Connection|connexion à une base de données]] +pour accéder aux données de la base de données et les manipuler. +Comme expliqué dans la section [Objets d'accès aux bases de données](db-dao.md), vous pouvez configurer le composant `db` dans la configuration de l'application comme montré ci-dessous : + ```php return [ @@ -110,7 +141,10 @@ Après avoir déclaré une classe d'enregistrement actif, vous pouvez l'utiliser 2. Construire l'objet *query* en appelant des [méthodes de construction de requête](db-query-builder.md#building-queries); 3. Appeler une [méthode de requête](db-query-builder.md#query-methods) pour retrouver les données en terme d'instances d'enregistrement actif. -Comme vous pouvez le voir, cela est très similaire à la procédure avec le [constructeur de requêtes](db-query-builder.md). La seule différence est que, au lieu d'utiliser l'opérateur `new` pour créer un objet *query* (requête), vous appelez la méthode [[yii\db\ActiveRecord::find()]] pour retourner un nouvel objet *query* qui est de la classe [[yii\db\ActiveQuery]]. +Comme vous pouvez le voir, cela est très similaire à la procédure avec le [constructeur de requêtes](db-query-builder.md). +La seule différence est que, au lieu d'utiliser l'opérateur `new` pour créer un objet *query* (requête), vous appelez la méthode [[yii\db\ActiveRecord::find()]] pour retourner un nouvel objet *query* qui est de la classe [[yii\db\ActiveQuery]]. + + Ce-dessous, nous donnons quelques exemples qui montrent comment utiliser l'*Active Query* (requête active) pour demander des données : @@ -121,7 +155,7 @@ $customer = Customer::find() ->where(['id' => 123]) ->one(); -// retourne tous les clients actifs et les classes par leur identifiant +// retourne tous les clients actifs et les classe par leur identifiant // SELECT * FROM `customer` WHERE `status` = 1 ORDER BY `id` $customers = Customer::find() ->where(['status' => Customer::STATUS_ACTIVE]) @@ -141,12 +175,15 @@ $customers = Customer::find() ->all(); ``` -Dans le code ci-dessus, `$customer` est un objet `Customer` tandis que `$customers` est un tableau d'objets `Customer`. Ils sont tous remplis par les données retrouvées dans la table `customer`. +Dans le code ci-dessus, `$customer` est un objet `Customer` tandis que `$customers` est un tableau d'objets `Customer`. +Ils sont tous remplis par les données retrouvées dans la table `customer`. -> Info: comme la classe [[yii\db\ActiveQuery]] étend la classe [[yii\db\Query]], vous pouvez utiliser *toutes* les méthodes de construction et de requête comme décrit dans la section sur le [constructeur de requête](db-query-builder.md). +> Info: comme la classe [[yii\db\ActiveQuery]] étend la classe [[yii\db\Query]], +vous pouvez utiliser *toutes* les méthodes de construction et de requête comme décrit dans la section sur le [constructeur de requête](db-query-builder.md). Parce que faire une requête de données par les valeurs de clés primaires ou par jeu de valeurs de colonne est une tâche assez courante, Yii fournit une prise en charge de méthodes raccourcis pour cela : + - [[yii\db\ActiveRecord::findOne()]]: retourne une instance d'enregistrement actif remplie avec la première ligne du résultat de la requête. - [[yii\db\ActiveRecord::findAll()]]: retourne un tableau d'instances d'enregistrement actif rempli avec *tous* les résultats de la requête. @@ -154,8 +191,10 @@ Les deux méthodes acceptent un des formats de paramètres suivants : - une valeur scalaire : la valeur est traitée comme la valeur de la clé primaire à rechercher. Yii détermine automatiquement quelle colonne est la colonne de clé primaire en lisant les informations du schéma de la base de données. - un tableau de valeurs scalaires : le tableau est traité comme les valeurs de clé primaire désirées à rechercher. -- un tableau associatif : les clés sont les noms de colonne et les valeurs sont les valeurs de colonne désirées à rechercher. Reportez-vous au [format haché](db-query-builder.md#hash-format) pour plus de détails. +- un tableau associatif : les clés sont les noms de colonne et les valeurs sont les valeurs de colonne désirées à rechercher. +Reportez-vous au [format haché](db-query-builder.md#hash-format) pour plus de détails. + Le code qui suit montre comment ces méthodes peuvent être utilisées : ```php @@ -181,9 +220,31 @@ $customers = Customer::findAll([ ]); ``` +> Attention : si vous avez besoin de passer des saisies utilisateur à +ces méthodes, assurez-vous que la valeurs saisie est un scalaire ou dans le cas d'une +> condition tableau, assurez-vous que la structure du tableau ne peut pas être changée depuis l'extérieur : +> +> ```php +> // yii\web\Controller garantit que $id est un scalaire +> public function actionView($id) +> { +> $model = Post::findOne($id); +> // ... +> } +> +> // spécifier explicitement la colonne à chercher, passer un scalaire ou un tableau ici, aboutit à retrouver un enregistrement unique +> $model = Post::findOne(['id' => Yii::$app->request->get('id')]); +> +> // n'utilisez PAS le code suivant si possible ! Il est possible d'injecter une condition tableau pour filtrer par des valeurs de colonne arbitraires ! +> $model = Post::findOne(Yii::$app->request->get('id')); +> ``` + > Note: ni [[yii\db\ActiveRecord::findOne()]], ni [[yii\db\ActiveQuery::one()]] n'ajoutent `LIMIT 1` à l'instruction SQL générée. Si votre requête peut retourner plusieurs lignes de données, vous devez appeler `limit(1)` explicitement pour améliorer la performance, p. ex., `Customer::find()->limit(1)->one()`. -En plus d'utiliser les méthodes de construction de requête, vous pouvez aussi écrire du SQL brut pour effectuer une requête de données et vous servir des résultats pour remplir des objets enregistrements actifs. Vous pouvez le faire en appelant la méthode [[yii\db\ActiveRecord::findBySql()]] : +En plus d'utiliser les méthodes de construction de requête, vous pouvez aussi écrire du SQL brut pour effectuer une requête de données et vous servir des résultats pour remplir des objets enregistrements actifs. +Vous pouvez le faire en appelant la méthode [[yii\db\ActiveRecord::findBySql()]] : + + ```php // retourne tous les clients inactifs @@ -191,11 +252,15 @@ $sql = 'SELECT * FROM customer WHERE status=:status'; $customers = Customer::findBySql($sql, [':status' => Customer::STATUS_INACTIVE])->all(); ``` -N'appelez pas de méthodes de construction de requêtes supplémentaires après avoir appelé [[yii\db\ActiveRecord::findBySql()|findBySql()]] car elles seront ignorées. +N'appelez pas de méthodes de construction de requêtes supplémentaires après avoir appelé +[[yii\db\ActiveRecord::findBySql()|findBySql()]] +car elles seront ignorées. ## Accès aux données -Comme nous l'avons mentionné plus haut, les données extraites de la base de données servent à remplir des instances de la classe d'enregistrement actif et chacune des lignes du résultat de la requête correspond à une instance unique de la classe d'enregistrement actif. Vous pouvez accéder accéder aux valeurs des colonnes en accédant aux attributs des instances de la classe d'enregistrement actif, par exemple : + +Comme nous l'avons mentionné plus haut, les données extraites de la base de données servent à remplir des instances de la classe d'enregistrement actif et chacune des lignes du résultat de la requête correspond à une instance unique de la classe d'enregistrement actif. +Vous pouvez accéder accéder aux valeurs des colonnes en accédant aux attributs des instances de la classe d'enregistrement actif, par exemple : ```php // "id" et "email" sont les noms des colonnes de la table "customer" @@ -204,13 +269,23 @@ $id = $customer->id; $email = $customer->email; ``` -> Note: les attributs de l'instance de la classe d'enregistrement actif sont nommés d'après les noms des colonnes de la table associée en restant sensible à la casse. Yii définit automatiquement un attribut dans l'objet enregistrement actif pour chacune des colonnes de la table associée. Vous ne devez PAS déclarer à nouveau l'un quelconque des ces attributs. +> Note: les attributs de l'instance de la classe d'enregistrement actif sont nommés d'après les noms des colonnes de la table associée en restant sensibles à la casse. +Yii définit automatiquement un attribut dans l'objet enregistrement actif pour chacune des colonnes de la table associée. +Vous ne devez PAS déclarer à nouveau l'un quelconque des ces attributs. + +Comme les attributs de l'instance d'enregistrement actif sont nommés d'après le nom des colonnes, +vous pouvez vous retrouver en train d'écrire du code PHP tel que `$customer->first_name`, qui utilise le caractère (_) *souligné* pour séparer les mots dans les noms d'attributs si vos colonnes de table sont nommées de cette manière. +Si vous êtes attaché à la cohérence du style de codage, vous devriez renommer vos colonnes de tables en conséquence (p. ex. en utilisant la notation en dos de chameau). + -Comme les attributs de l'instance d'enregistrement actif sont nommés d'après le nom des colonnes, vous pouvez vous retrouver en train d'écrire du code PHP tel que `$customer->first_name`, qui utilise le caractère *souligné* pour séparer les mots dans les noms d'attributs si vos colonnes de table sont nommées de cette manière. Si vous êtes attaché à la cohérence du style de codage, vous devriez renommer vos colonnes de tables en conséquence (p. ex. en utilisant la notation en dos de chameau). ### Transformation des données -Il arrive souvent que les données entrées et/ou affichées soient dans un format qui diffère de celui utilisé pour stocker les données dans la base. Par exemple, dans la base de données, vous stockez la date d'anniversaire des clients sous la forme d'horodatages UNIX (bien que ce soit pas une conception des meilleures), tandis que dans la plupart des cas, vous avez envie de manipuler les dates d'anniversaire sous la forme de chaînes de caractères dans le format `'YYYY/MM/DD'`. Pour le faire, vous pouvez définir des méthodes de *transformation de données* dans la classe d'enregistrement actif comme ceci : +Il arrive souvent que les données entrées et/ou affichées soient dans un format qui diffère de celui utilisé pour stocker les données dans la base. +Par exemple, dans la base de données, vous stockez la date d'anniversaire des clients sous la forme de horodates UNIX (bien que ce soit pas une conception des meilleures), +tandis que dans la plupart des cas, vous avez envie de manipuler les dates d'anniversaire sous la forme de chaînes de caractères dans le format `'YYYY/MM/DD'`. +Pour le faire, vous pouvez définir des méthodes de *transformation de données* dans la classe d'enregistrement actif comme ceci : + ```php class Customer extends ActiveRecord @@ -231,12 +306,17 @@ class Customer extends ActiveRecord Désormais, dans votre code PHP, au lieu d'accéder à `$customer->birthday`, vous devez accéder à `$customer->birthdayText`, ce qui vous permet d'entrer et d'afficher les dates d'anniversaire dans le format `'YYYY/MM/DD'`. -> Tip: l'exemple qui précède montre une manière générique de transformer des données dans différents formats. Si vous travaillez avec des valeurs de dates, vous pouvez utiliser [DateValidator](tutorial-core-validators.md#date) et [[yii\jui\DatePicker|DatePicker]], qui sont plus faciles à utiliser et plus puissants. + +> Tip: l'exemple qui précède montre une manière générique de transformer des données dans différents formats. Si vous travaillez avec des valeurs de dates, vous pouvez utiliser [DateValidator](tutorial-core-validators.md#date) et [[yii\jui\DatePicker|DatePicker]], qui sont plus faciles à utiliser et plus puissantes. + + ### Retrouver des données dans des tableaux -Alors que retrouver des données en termes d'objets enregistrements actifs est souple et pratique, cela n'est pas toujours souhaitable lorsque vous devez extraire une grande quantité de données à cause de l'empreinte mémoire très importante. Dans ce cas, vous pouvez retrouver les données en utilisant des tableaux PHP en appelant [[yii\db\ActiveQuery::asArray()|asArray()]] avant d'exécuter une méthode de requête : +Alors que retrouver des données en termes d'objets enregistrements actifs est souple et pratique, cela n'est pas toujours souhaitable lorsque vous devez extraire une grande quantité de données à cause de l'empreinte mémoire très importante. +Dans ce cas, vous pouvez retrouver les données en utilisant des tableaux PHP en appelant [[yii\db\ActiveQuery::asArray()|asArray()]] avant d'exécuter une méthode de requête : + ```php // retourne tous les clients @@ -246,11 +326,17 @@ $customers = Customer::find() ->all(); ``` -> Note: bien que cette méthode économise de la mémoire et améliore la performance, elle est plus proche de la couche d'abstraction basse de la base de données et perd la plupart des fonctionnalité de l'objet enregistrement actif. Une distinction très importante réside dans le type de données des valeurs des colonnes. Lorsque vous retournez des données dans une instance d'enregistrement actif, les valeurs des colonnes sont automatiquement typées en fonction du type réel des colonnes ; par contre, lorsque vous retournez des données dans des tableaux, les valeurs des colonnes sont des chaînes de caractères (parce qu'elles résultent de PDO sans aucun traitement), indépendamment du type réel de ces colonnes. +> Note: bien que cette méthode économise de la mémoire et améliore la performance, elle est plus proche de la couche d'abstraction basse de la base de données et perd la plupart des fonctionnalités de l'objet enregistrement actif. Une distinction très importante réside dans le type de données des valeurs de colonne. + Lorsque vous retournez des données dans une instance d'enregistrement actif, les valeurs des colonnes sont automatiquement typées en fonction du type réel des colonnes ; + par contre, lorsque vous retournez des données dans des tableaux, les valeurs des colonnes sont des chaînes de caractères (parce qu'elles résultent de PDO sans aucun traitement), indépendamment du type réel de ces colonnes. + + + ### Retrouver des données dans des lots -Dans la section sur le [constructeur de requêtes](db-query-builder.md), nous avons expliqué que vous pouvez utiliser des *requêtes par lots* pour minimiser l'utilisation de la mémoire lorsque vous demandez de grandes quantités de données de la base de données. Vous pouvez utiliser la même technique avec l'enregistrement actif. Par exemple : +Dans la section sur le [constructeur de requêtes](db-query-builder.md), nous avons expliqué que vous pouvez utiliser des *requêtes par lots* pour minimiser l'utilisation de la mémoire lorsque vous demandez de grandes quantités de données de la base de données. +Vous pouvez utiliser la même technique avec l'enregistrement actif. Par exemple : ```php // va chercher 10 clients (customer) à la fois @@ -293,9 +379,14 @@ $customer->email = 'james@newexample.com'; $customer->save(); ``` -La méthode [[yii\db\ActiveRecord::save()|save()]] peut soit insérer, soit mettre à jour une ligne de données, selon l'état de l'instance de l'enregistrement actif. Si l'instance est en train d'être créée via l'opérateur `new`, appeler [[yii\db\ActiveRecord::save()|save()]] provoque l'insertion d'une nouvelle ligne de données ; si l'instance est le résultat d'une méthode de requête, appeler [[yii\db\ActiveRecord::save()|save()]] met à jour la ligne associée à l'instance. +La méthode [[yii\db\ActiveRecord::save()|save()]] peut soit insérer, soit mettre à jour une ligne de données, selon l'état de l'instance de l'enregistrement actif. +Si l'instance est en train d'être créée via l'opérateur `new`, appeler [[yii\db\ActiveRecord::save()|save()]] +provoque l'insertion d'une nouvelle ligne de données ; +si l'instance est le résultat d'une méthode de requête, appeler [[yii\db\ActiveRecord::save()|save()]] met à jour la ligne associée à l'instance. -Vous pouvez différentier les deux états d'une instance d'enregistrement actif en testant la valeur de sa propriété [[yii\db\ActiveRecord::isNewRecord|isNewRecord]]. Cette propriété est aussi utilisée par [[yii\db\ActiveRecord::save()|save()]] en interne, comme ceci : +Vous pouvez différentier les deux états d'une instance d'enregistrement actif en testant la valeur de sa propriété [[yii\db\ActiveRecord::isNewRecord|isNewRecord]]. +Cette propriété est aussi utilisée par [[yii\db\ActiveRecord::save()|save()]] +en interne, comme ceci : ```php public function save($runValidation = true, $attributeNames = null) @@ -308,21 +399,29 @@ public function save($runValidation = true, $attributeNames = null) } ``` -> Tip: vous pouvez appeler [[yii\db\ActiveRecord::insert()|insert()]] ou [[yii\db\ActiveRecord::update()|update()]] directement pour insérer ou mettre à jour une ligne. +> Astuce: vous pouvez appeler [[yii\db\ActiveRecord::insert()|insert()]] ou [[yii\db\ActiveRecord::update()|update()]] +directement pour insérer ou mettre à jour une ligne. ### Validation des données -Comme la classe [[yii\db\ActiveRecord]] étend la classe [[yii\base\Model]], elle partage la même fonctionnalité de [validation des données](input-validation.md). Vous pouvez déclarer les règles de validation en redéfinissant la méthode [[yii\db\ActiveRecord::rules()|rules()]] et effectuer la validation des données en appelant la méthode [[yii\db\ActiveRecord::validate()|validate()]]. +Comme la classe [[yii\db\ActiveRecord]] étend la classe [[yii\base\Model]], +elle partage la même fonctionnalité de [validation des données](input-validation.md). +Vous pouvez déclarer les règles de validation en redéfinissant la méthode [[yii\db\ActiveRecord::rules()|rules()]] et effectuer la validation des données en appelant la méthode [[yii\db\ActiveRecord::validate()|validate()]]. -Lorsque vous appelez la méthode [[yii\db\ActiveRecord::save()|save()]], par défaut, elle appelle automatiquement la méthode [[yii\db\ActiveRecord::validate()|validate()]]. C'est seulement si la validation réussit, que les données sont effectivement sauvegardées ; autrement elle retourne simplement `false`, et vous pouvez tester la propriété [[yii\db\ActiveRecord::errors|errors]] pour retrouver les messages d'erreurs de validation. +Lorsque vous appelez la méthode [[yii\db\ActiveRecord::save()|save()]], par défaut, elle appelle automatiquement la méthode [[yii\db\ActiveRecord::validate()|validate()]]. +C'est seulement si la validation réussit, que les données sont effectivement sauvegardées ; +autrement elle retourne simplement `false`, et vous pouvez tester la propriété [[yii\db\ActiveRecord::errors|errors]] pour retrouver les messages d'erreurs de validation. + +> Astuce: si vous avez la certitude que vos données n'ont pas besoin d'être validées (p. ex. vos données proviennent de sources fiables), vous pouvez appeler `save(false)` pour omettre la validation. -> Tip: si vous êtes sûr que vos données n'ont pas besoin d'être validées (p. ex. vos données proviennent de sources fiables), vous pouvez appeler `save(false)` pour omettre la validation. ### Assignation massive -Comme les [modèles](structure-models.md) habituels, les instances d'enregistrement actif profitent de la [fonctionnalité d'assignation massive](structure-models.md#massive-assignment). L'utilisation de cette fonctionnalité vous permet d'assigner plusieurs attributs d'un enregistrement actif en une seule instruction PHP, comme c'est montré ci-dessous. N'oubliez cependant pas que, seuls les [attributs sûrs](structure-models.md#safe-attributes) sont assignables en masse. +Comme les [modèles](structure-models.md) habituels, les instances d'enregistrement actif profitent de la [fonctionnalité d'assignation massive](structure-models.md#massive-assignment). +L'utilisation de cette fonctionnalité vous permet d'assigner plusieurs attributs d'un enregistrement actif en une seule instruction PHP, comme c'est montré ci-dessous. +N'oubliez cependant pas que, seuls les [attributs sûrs](structure-models.md#safe-attributes) sont assignables en masse. ```php $values = [ @@ -339,7 +438,9 @@ $customer->save(); ### Mise à jour des compteurs -C'est une tâche courante que d'incrémenter ou décrémenter une colonne dans une table de base de données. Nous appelons ces colonnes « colonnes compteurs*. Vous pouvez utiliser la méthode [[yii\db\ActiveRecord::updateCounters()|updateCounters()]] pour mettre à jour une ou plusieurs colonnes de comptage. Par exemple : +C'est une tâche courante que d'incrémenter ou décrémenter une colonne dans une table de base de données. +Nous appelons ces colonnes « colonnes compteurs*. Vous pouvez utiliser la méthode [[yii\db\ActiveRecord::updateCounters()|updateCounters()]] pour mettre à jour une ou plusieurs colonnes de comptage. +Par exemple : ```php $post = Post::findOne(100); @@ -351,20 +452,36 @@ $post->updateCounters(['view_count' => 1]); > Note: si vous utilisez la méthode [[yii\db\ActiveRecord::save()]] pour mettre à jour une colonne compteur, vous pouvez vous retrouver avec un résultat erroné car il est probable que le même compteur soit sauvegardé par de multiples requêtes qui lisent et écrivent la même valeur de compteur. + ### Attributs sales (*Dirty Attributes*) -Lorsque vous appelez la méthode [[yii\db\ActiveRecord::save()|save()]] pour sauvegarder une instance d'enregistrement actif, seuls les attributs dit *attributs sales* sont sauvegardés. Un attribut est considéré comme *sale* si sa valeur a été modifiée depuis qu'il a été chargé depuis la base de données ou sauvegardé dans la base de données le plus récemment. Notez que la validation des données est assurée sans se préoccuper de savoir si l'instance d'enregistrement actif possède des attributs sales ou pas. +Lorsque vous appelez la méthode [[yii\db\ActiveRecord::save()|save()]] pour sauvegarder une instance d'enregistrement actif, seuls les attributs dit *attributs sales* sont sauvegardés. +Un attribut est considéré comme *sale* si sa valeur a été modifiée depuis qu'il a été chargé depuis la base de données ou sauvegardé dans la base de données le plus récemment. +Notez que la validation des données est assurée sans se préoccuper de savoir si l'instance d'enregistrement actif possède des attributs sales ou pas. + -L'enregistrement actif tient à jour la liste des attributs sales. Il le fait en conservant une version antérieure des valeurs d'attribut et en les comparant avec les dernières. Vous pouvez appeler la méthode [[yii\db\ActiveRecord::getDirtyAttributes()]] pour obtenir les attributs qui sont couramment sales. Vous pouvez aussi appeler la méthode [[yii\db\ActiveRecord::markAttributeDirty()]] pour marquer explicitement un attribut comme sale. +L'enregistrement actif tient à jour la liste des attributs sales. Il le fait en conservant une version antérieure des valeurs d'attribut et en les comparant avec les dernières. +Vous pouvez appeler la méthode [[yii\db\ActiveRecord::getDirtyAttributes()]] pour obtenir les attributs qui sont couramment sales. +Vous pouvez aussi appeler la méthode [[yii\db\ActiveRecord::markAttributeDirty()]] pour marquer explicitement un attribut comme sale. -Si vous êtes intéressé par les valeurs d'attribut antérieurs à leur plus récente modification, vous pouvez appeler la méthode [[yii\db\ActiveRecord::getOldAttributes()|getOldAttributes()]] ou la méthode [[yii\db\ActiveRecord::getOldAttribute()|getOldAttribute()]]. -> Note: la comparaison entre les anciennes et les nouvelles valeurs est faite en utilisant l'opérateur `===` , ainsi une valeur est considérée comme sale si le type est différent même si la valeur reste la même. Cela est souvent le cas lorsque le modèle reçoit des entrées utilisateur de formulaires HTML ou chacune des valeurs est représentée par une chaîne de caractères. Pour garantir le type correct pour p. ex. des valeurs entières, vous devez appliquer un [filtre de validation](input-validation.md#data-filtering): -> `['attributeName', 'filter', 'filter' => 'intval']`. Cela fonctionne pour toutes les fonctions de transformation de type de PHP comme [intval()](http://php.net/manual/en/function.intval.php), [floatval()](http://php.net/manual/en/function.floatval.php), [boolval](http://php.net/manual/en/function.boolval.php), etc... +Si vous êtes intéressé par les valeurs d'attribut antérieurs à leur plus récente modification, vous pouvez appeler la méthode [[yii\db\ActiveRecord::getOldAttributes()|getOldAttributes()]] +ou la méthode [[yii\db\ActiveRecord::getOldAttribute()|getOldAttribute()]]. + +> Note: la comparaison entre les anciennes et les nouvelles valeurs est faite en utilisant l'opérateur `===` , ainsi une valeur est considérée comme sale si le type est différent même si la valeur reste la même. +Cela est souvent le cas lorsque le modèle reçoit des entrées utilisateur de formulaires HTML ou chacune des valeurs est représentée par une chaîne de caractères. +Pour garantir le type correct pour p. ex. des valeurs entières, vous devez appliquer un [filtre de validation](input-validation.md#data-filtering): +> `['attributeName', 'filter', 'filter' => 'intval']`. +Cela fonctionne pour toutes les fonctions de transformation de type de PHP comme [intval()](http://php.net/manual/en/function.intval.php), +[floatval()](http://php.net/manual/en/function.floatval.php), +[boolval](http://php.net/manual/en/function.boolval.php), etc... ### Valeurs d'attribut par défaut -Quelques unes de vos colonnes de tables peuvent avoir des valeurs par défaut définies dans la base de données. Parfois, vous voulez peut-être pré-remplir votre formulaire Web pour un enregistrement actif à partir des valeurs par défaut. Pour éviter d'écrire la même valeur par défaut à nouveau, vous pouvez appeler la méthode [[yii\db\ActiveRecord::loadDefaultValues()|loadDefaultValues()]] pour remplir les attributs de l'enregistrement actif avec les valeurs par défaut prédéfinies dans la base de données : +Quelques unes de vos colonnes de tables peuvent avoir des valeurs par défaut définies dans la base de données. +Parfois, vous voulez peut-être pré-remplir votre formulaire Web pour un enregistrement actif à partir des valeurs par défaut. +Pour éviter d'écrire les mêmes valeurs par défaut à nouveau, vous pouvez appeler la méthode [[yii\db\ActiveRecord::loadDefaultValues()|loadDefaultValues()]] pour remplir les attributs de l'enregistrement actif avec les valeurs par défaut prédéfinies dans la base de données : + ```php $customer = new Customer(); @@ -373,9 +490,58 @@ $customer->loadDefaultValues(); ``` +### Conversion de type d'attributs + +Étant peuplé par les résultats des requêtes, l'[[yii\db\ActiveRecord|enregistrement actif]] effectue des conversions automatiques de type pour ses valeurs d'attribut, en utilisant les informations du [schéma des tables de base de données](db-dao.md#database-schema). +Cela permet aux données retrouvées dans les colonnes de la table et déclarées comme entiers de peupler une instance d'enregistrement actif avec des entiers PHP, les valeurs booléennes avec des valeurs booléennes, et ainsi de suite. +Néanmoins, le mécanisme de conversion de type souffre de plusieurs limitation : + +* Les valeurs flottantes (Float) ne sont pas converties et sont représentées par des chaînes de caractères, autrement elles pourraient perdre de la précision. +* La conversion des valeurs entières dépend de la capacité du système d'exploitation utilisé. +En particulier, les valeurs de colonne déclarée comme « entier non signé », ou « grand entier » (big integer) sont converties en entier PHP seulement pour les système d'exploitation 64 bits, tandis que sur les systèmes 32 bits, elles sont représentées par des chaînes de caractères. + + + +Notez que la conversion de type des attributs n'est effectuée que lors du peuplement d'une instance d'enregistrement actif par les résultats d'une requête. +Il n'y a pas de conversion automatique pour les valeurs chargées par une requête HTTP ou définies directement par accès à des propriétés. +Le schéma de table est aussi utilisé lors de la préparation des instructions SQL pour la sauvegarde de l'enregistrement actif, garantissant ainsi que les valeurs sont liées à la requête avec le type correct. +Cependant, les valeurs d'attribut d'une instance d'enregistrement actif ne sont pas converties durant le processus de sauvegarde. + + +> Astuce : vous pouvez utiliser [[yii\behaviors\AttributeTypecastBehavior]] pour faciliter la conversion de type des valeurs d'attribut lors de la validation ou la sauvegarde d'un enregistrement actif. + + +Depuis la version 2.0.14, la classe ActiveRecord de Yii prend en charge des types de données complexe tels que JSON ou les tableaux multi-dimensionnels. + +#### JSON dans MySQL et PostgreSQL + +Après le peuplement par les données, la valeur d'une colonne JSON est automatiquement décodée selon les règles de décodage standard de JSON. + + +Pour sauvegarder une valeur d'attribut dans une colonne de type JSON, la classe ActiveRecord crée automatiquement un objet [[yii\db\JsonExpression|JsonExpression]] +qui est encodé en une chaîne JSON au niveau du [constructeur de requête](db-query-builder.md). + +#### Tableaux dans PostgreSQL + +Après le peuplement par les données, les valeurs issues de colonnes de type tableau sont automatiquement décodée de la notation PgSQL en un objet [[yii\db\ArrayExpression|ArrayExpression]]. +Il met en œuvre l'interface `ArrayAccess`, ainsi pouvez-vous l'utiliser comme un tableau, ou appeler `->getValue()` pour obtenir le tableau lui-même. + +Pour sauvegarder une valeur d'attribut dans une colonne de type tableau,la classe ActiveRecord crée automatiquement un objet [[yii\db\ArrayExpression|ArrayExpression]] qui est encodé par le [constructeur de requête](db-query-builder.md) en une chaîne PgSQL représentant le tableau. + + +Vous pouvez aussi utiliser des conditions pour les colonnes de type JSON : + +```php +$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar']) +``` + +Pour en apprendre plus sur les le système de construction d'expressions, reportez-vous à l'article [Constructeur de requêtes – Ajout de conditions et d'expressions personnalisées](db-query-builder.md#adding-custom-conditions-and-expressions). + ### Mise à jour de plusieurs lignes -Les méthodes décrites ci-dessus fonctionnent toutes sur des instances individuelles d'enregistrement actif. Pour mettre à jour plusieurs lignes à la fois, vous devez appeler la méthode statique [[yii\db\ActiveRecord::updateAll()|updateAll()]]. +Les méthodes décrites ci-dessus fonctionnent toutes sur des instances individuelles d'enregistrement actif pour insérer ou mettre à jour des lignes individuelles de table. +Pour mettre à jour plusieurs lignes à la fois, vous devez appeler la méthode statique [[yii\db\ActiveRecord::updateAll()|updateAll()]]. + ```php // UPDATE `customer` SET `status` = 1 WHERE `email` LIKE `%@example.com%` @@ -394,6 +560,8 @@ Customer::updateAllCounters(['age' => 1]); Pour supprimer une ligne unique de données, commencez par retrouver l'instance d'enregistrement actif correspondant à cette ligne et appelez la méthode [[yii\db\ActiveRecord::delete()]]. + + ```php $customer = Customer::findOne(123); $customer->delete(); @@ -405,21 +573,27 @@ Vous pouvez appeler [[yii\db\ActiveRecord::deleteAll()]] pour effacer plusieurs Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]); ``` -> Note: soyez très prudent lorsque vous appelez [[yii\db\ActiveRecord::deleteAll()|deleteAll()]] parce que cela peut effacer totalement toutes les données de votre table si vous faites une erreur en spécifiant la condition. +> Note : agissez avec prudence lorsque vous appelez [[yii\db\ActiveRecord::deleteAll()|deleteAll()]] parce que cela peut effacer totalement toutes les données de votre table si vous faites une erreur en spécifiant la condition. ## Cycles de vie de l'enregistrement actif -Il est important que vous compreniez les cycles de vie d'un enregistrement actif lorsqu'il est utilisé à des fins différentes. Lors de chaque cycle de vie, une certaine séquence d'invocation de méthodes a lieu, et vous pouvez redéfinir ces méthodes pour avoir une chance de personnaliser le cycle de vie. Vous pouvez également répondre à certains événements de l'enregistrement actif déclenchés durant un cycle de vie pour injecter votre code personnalisé. Ces événements sont particulièrement utiles lorsque vous développez des [comportements](concept-behaviors.md) d'enregistrement actif qui ont besoin de personnaliser les cycles de vies d'enregistrement actifs. +Il est important que vous compreniez les cycles de vie d'un enregistrement actif lorsqu'il est utilisé à des fins différentes. +Lors de chaque cycle de vie, une certaine séquence d'invocation de méthodes a lieu, et vous pouvez redéfinir ces méthodes pour avoir une chance de personnaliser le cycle de vie. +Vous pouvez également répondre à certains événements de l'enregistrement actif déclenchés durant un cycle de vie pour injecter votre code personnalisé. +Ces événements sont particulièrement utiles lorsque vous développez des [comportements](concept-behaviors.md) d'enregistrement actif qui ont besoin de personnaliser les cycles de vie d'enregistrement actifs. + + + +Dans l'exemple suivant, nous résumons les différents cycles de vie d'enregistrement actif et les méthodes/événements à qui il est fait appel dans ces cycles. -Dans l'exemple précédent, nous résumons les différents cycles de vie d'enregistrement actif et les méthodes/événements à qui il est fait appel dans ces cycles. ### Cycle de vie d'une nouvelle instance -Losque vous créez un nouvel enregistrement actif via l'opérateur `new`, le cycle suivant se réalise : +Lorsque vous créez un nouvel enregistrement actif via l'opérateur `new`, le cycle suivant se réalise : -1. Constructeur de la classe. +1. Construction de la classe. 2. [[yii\db\ActiveRecord::init()|init()]]: déclenche un événement [[yii\db\ActiveRecord::EVENT_INIT|EVENT_INIT]]. @@ -427,7 +601,8 @@ Losque vous créez un nouvel enregistrement actif via l'opérateur `new`, le cyc Lorsque vous effectuez une requête de données via l'une des [méthodes de requête](#querying-data), chacun des enregistrements actifs nouvellement rempli entreprend le cycle suivant : -1. Constructeur de la classe. + +1. Construction de la classe. 2. [[yii\db\ActiveRecord::init()|init()]]: déclenche un événement [[yii\db\ActiveRecord::EVENT_INIT|EVENT_INIT]]. 3. [[yii\db\ActiveRecord::afterFind()|afterFind()]]: déclenche un événement [[yii\db\ActiveRecord::EVENT_AFTER_FIND|EVENT_AFTER_FIND]]. @@ -436,26 +611,39 @@ Lorsque vous effectuez une requête de données via l'une des [méthodes de requ En appelant [[yii\db\ActiveRecord::save()|save()]] pour insérer ou mettre à jour une instance d'enregistrement actif, le cycle de vie suivant se réalise : -1. [[yii\db\ActiveRecord::beforeValidate()|beforeValidate()]]: déclenche un événement [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]] . Si la méthode retourne `false` (faux), ou si [[yii\base\ModelEvent::isValid]] est `false`, les étapes suivantes sont sautées. -2. Effectue la validation des données. Si la validation échoue, les étapes après l'étape 3 saut sautées. -3. [[yii\db\ActiveRecord::afterValidate()|afterValidate()]]: déclenche un événement [[yii\db\ActiveRecord::EVENT_AFTER_VALIDATE|EVENT_AFTER_VALIDATE]]. -4. [[yii\db\ActiveRecord::beforeSave()|beforeSave()]]: déclenche un événement [[yii\db\ActiveRecord::EVENT_BEFORE_INSERT|EVENT_BEFORE_INSERT]] - ou un événement [[yii\db\ActiveRecord::EVENT_BEFORE_UPDATE|EVENT_BEFORE_UPDATE]]. Si la méthode retourne `false` ou si [[yii\base\ModelEvent::isValid]] est `false`, les étapes suivantes sont sautées. + +1. [[yii\db\ActiveRecord::beforeValidate()|beforeValidate()]]: déclenche un événement [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]] . + Si la méthode retourne `false` (faux), ou si [[yii\base\ModelEvent::isValid]] est `false`, les étapes suivantes sont sautées. +2. Effectue la validation des données. + Si la validation échoue, les étapes après l'étape 3 saut sautées. +3. [[yii\db\ActiveRecord::afterValidate()|afterValidate()]]: + déclenche un événement [[yii\db\ActiveRecord::EVENT_AFTER_VALIDATE|EVENT_AFTER_VALIDATE]]. +4. [[yii\db\ActiveRecord::beforeSave()|beforeSave()]]: + déclenche un événement [[yii\db\ActiveRecord::EVENT_BEFORE_INSERT|EVENT_BEFORE_INSERT]] + ou un événement [[yii\db\ActiveRecord::EVENT_BEFORE_UPDATE|EVENT_BEFORE_UPDATE]]. + Si la méthode retourne `false` ou si [[yii\base\ModelEvent::isValid]] est `false`, les étapes suivantes sont sautées. 5. Effectue l'insertion ou la mise à jour réelle. -6. [[yii\db\ActiveRecord::afterSave()|afterSave()]]: déclenche un événement [[yii\db\ActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] ou un événement [[yii\db\ActiveRecord::EVENT_AFTER_UPDATE|EVENT_AFTER_UPDATE]]. +6. [[yii\db\ActiveRecord::afterSave()|afterSave()]]: + déclenche un événement [[yii\db\ActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] + ou un événement [[yii\db\ActiveRecord::EVENT_AFTER_UPDATE|EVENT_AFTER_UPDATE]]. ### Cycle de vie lors d'une suppression de données En appelant [[yii\db\ActiveRecord::delete()|delete()]] pour supprimer une instance d'enregistrement actif, le cycle suivant se déroule : -1. [[yii\db\ActiveRecord::beforeDelete()|beforeDelete()]]: déclenche un événement [[yii\db\ActiveRecord::EVENT_BEFORE_DELETE|EVENT_BEFORE_DELETE]]. Si la méthode retourne `false` ou si [[yii\base\ModelEvent::isValid]] est `false`, les étapes suivantes sont sautées. + +1. [[yii\db\ActiveRecord::beforeDelete()|beforeDelete()]]: + déclenche un événement [[yii\db\ActiveRecord::EVENT_BEFORE_DELETE|EVENT_BEFORE_DELETE]]. + Si la méthode retourne `false` ou si [[yii\base\ModelEvent::isValid]] est `false`, les étapes suivantes sont sautées. 2. Effectue la suppression réelle des données. -3. [[yii\db\ActiveRecord::afterDelete()|afterDelete()]]: déclenche un événement [[yii\db\ActiveRecord::EVENT_AFTER_DELETE|EVENT_AFTER_DELETE]]. +3. [[yii\db\ActiveRecord::afterDelete()|afterDelete()]]: + déclenche un événement [[yii\db\ActiveRecord::EVENT_AFTER_DELETE|EVENT_AFTER_DELETE]]. -> Note: l'appel de l'une des méthodes suivantes n'initie AUCUN des cycles vus ci-dessus parce qu'elles travaillent directement sur la base de données et pas sur la base d'un enregistrement actif : +> Note : l'appel de l'une des méthodes suivantes n'initie AUCUN des cycles vus ci-dessus parce qu'elles travaillent directement sur la base de données et pas sur la base d'un enregistrement actif : > + > - [[yii\db\ActiveRecord::updateAll()]] > - [[yii\db\ActiveRecord::deleteAll()]] > - [[yii\db\ActiveRecord::updateCounters()]] @@ -463,7 +651,8 @@ En appelant [[yii\db\ActiveRecord::delete()|delete()]] pour supprimer une instan ### Cycle de vie lors du rafraîchissement des données -En appelant [[yii\db\ActiveRecord::refresh()|refresh()]] pour rafraîchir une instance d'enregistrement actif, l'événement [[yii\db\ActiveRecord::EVENT_AFTER_REFRESH|EVENT_AFTER_REFRESH]] est déclenché si le rafraîchissement réussit et si la méthode retourne `true`. +En appelant [[yii\db\ActiveRecord::refresh()|refresh()]] pour rafraîchir une instance d'enregistrement actif, l'événement [[yii\db\ActiveRecord::EVENT_AFTER_REFRESH|EVENT_AFTER_REFRESH]] +est déclenché si le rafraîchissement réussit et si la méthode retourne `true`. ## Travail avec des transactions @@ -492,10 +681,18 @@ try { } catch(\Exception $e) { $transaction->rollBack(); throw $e; +} catch(\Throwable $e) { + $transaction->rollBack(); + throw $e; } ``` -La deuxième façon consiste à lister les opérations de base de données qui nécessitent une prise en charge transactionnelle dans la méthode [[yii\db\ActiveRecord::transactions()]]. Par exemple : +> Note : dans le code précédent, nous utilisons deux blocs de capture pour être compatible avec PHP 5.x et PHP 7.x. +`\Exception` met en œuvre l'[interface `\Throwable`](http://php.net/manual/en/class.throwable.php) +> à partir de PHP 7.0, c'est pourquoi vous pouvez sauter la partie avec `\Exception` si votre application utilise PHP 7.0 ou une version plus récente. + +La deuxième façon consiste à lister les opérations de base de données qui nécessitent une prise en charge transactionnelle dans la méthode [[yii\db\ActiveRecord::transactions()]]. +Par exemple : ```php class Customer extends ActiveRecord @@ -512,36 +709,54 @@ class Customer extends ActiveRecord } ``` -La méthode [[yii\db\ActiveRecord::transactions()]] doit retourner un tableau dont les clés sont les noms de [scenario](structure-models.md#scenarios) et les valeurs les opérations correspondantes qui doivent être enfermées dans des transactions. Vous devez utiliser les constantes suivantes pour faire référence aux différentes opérations de base de données : +La méthode [[yii\db\ActiveRecord::transactions()]] +doit retourner un tableau dont les clés sont les noms de [scénario](structure-models.md#scenarios) et les valeurs les opérations correspondantes qui doivent être enfermées dans des transactions. +Vous devez utiliser les constantes suivantes pour faire référence aux différentes opérations de base de données : * [[yii\db\ActiveRecord::OP_INSERT|OP_INSERT]]: opération d'insertion réalisée par [[yii\db\ActiveRecord::insert()|insert()]]; * [[yii\db\ActiveRecord::OP_UPDATE|OP_UPDATE]]: opération de mise à jour réalisée par [[yii\db\ActiveRecord::update()|update()]]; * [[yii\db\ActiveRecord::OP_DELETE|OP_DELETE]]: opération de suppression réalisée par [[yii\db\ActiveRecord::delete()|delete()]]. -Utilisez l'opérateur `|` pour concaténer les constantes précédentes pour indiquer de multiples opérations. Vous pouvez également utiliser la constante raccourci [[yii\db\ActiveRecord::OP_ALL|OP_ALL]] pour faire référence à l'ensemble des trois opération ci-dessus. +Utilisez l'opérateur `|` pour concaténer les constantes précédentes pour indiquer de multiples opérations. +Vous pouvez également utiliser la constante raccourci [[yii\db\ActiveRecord::OP_ALL|OP_ALL]] pour faire référence à l'ensemble des trois opération ci-dessus. Les transactions qui sont créées en utilisant cette méthode sont démarrées avant d'appeler [[yii\db\ActiveRecord::beforeSave()|beforeSave()]] et sont entérinées après que la méthode [[yii\db\ActiveRecord::afterSave()|afterSave()]] a été exécutée. + ## Verrous optimistes -Le verrouillage optimiste est une manière d'empêcher les conflits qui peuvent survenir lorsqu'une même ligne de données est mise à jour par plusieurs utilisateurs. Par exemple, les utilisateurs A et B sont tous deux, simultanément, en train de modifier le même article de wiki. Après que l'utilisateur A a sauvegardé ses modifications, l'utilisateur B clique sur le bouton « Sauvegarder » dans le but de sauvegarder ses modifications lui aussi. Comme l'utilisateur B est en train de travailler sur une version périmée de l'article, il serait souhaitable de disposer d'un moyen de l'empêcher de sauvegarder sa version de l'article et de lui montrer un message d'explication. +Le verrouillage optimiste est une manière d'empêcher les conflits qui peuvent survenir lorsqu'une même ligne de données est mise à jour par plusieurs utilisateurs. +Par exemple, les utilisateurs A et B sont tous deux, simultanément, en train de modifier le même article de wiki. +Après que l'utilisateur A a sauvegardé ses modifications, l'utilisateur B clique sur le bouton « Sauvegarder » dans le but de sauvegarder ses modifications lui aussi. +Comme l'utilisateur B est en train de travailler sur une version périmée de l'article, il serait souhaitable de disposer d'un moyen de l'empêcher de sauvegarder sa version de l'article et de lui montrer un message d'explication. + -Le verrouillage optimiste résout le problème évoqué ci-dessus en utilisant une colonne pour enregistrer le numéro de version de chacune des lignes. Lorsqu'une ligne est sauvegardée avec un numéro de version périmée, une exception [[yii\db\StaleObjectException]] est levée, ce qui empêche la sauvegarde de la ligne. Le verrouillage optimiste, n'est seulement pris en charge que lorsque vous mettez à jour ou supprimez une ligne de données existante en utilisant les méthodes [[yii\db\ActiveRecord::update()]] ou [[yii\db\ActiveRecord::delete()]],respectivement. +Le verrouillage optimiste résout le problème évoqué ci-dessus en utilisant une colonne pour enregistrer le numéro de version de chacune des lignes. +Lorsqu'une ligne est sauvegardée avec un numéro de version périmée, une exception [[yii\db\StaleObjectException]] est levée, ce qui empêche la sauvegarde de la ligne. +Le verrouillage optimiste, n'est seulement pris en charge que lorsque vous mettez à jour ou supprimez une ligne de données existante en utilisant les méthodes [[yii\db\ActiveRecord::update()]] +ou [[yii\db\ActiveRecord::delete()]],respectivement. Pour utiliser le verrouillage optimiste : -1. Créez une colonne dans la table de base de données associée à la classe d'enregistrement actif pour stocker le numéro de version de chacune des lignes. Le colonne doit être du type *big integer* (dans MySQL ce doit être `BIGINT DEFAULT 0`). +1. Créez une colonne dans la table de base de données associée à la classe d'enregistrement actif pour stocker le numéro de version de chacune des lignes. +La colonne doit être du type *big integer* +(dans MySQL ce doit être `BIGINT DEFAULT 0`). 2. Redéfinissez la méthode [[yii\db\ActiveRecord::optimisticLock()]] pour qu'elle retourne le nom de cette colonne. -3. Dans le formulaire Web qui reçoit les entrées de l'utilisateur, ajoutez un champ caché pour stocker le numéro de version courant de la ligne en modification. Assurez-vous que votre attribut *version* dispose de règles de validation et valide correctement. -4. Dans l'action de contrôleur qui met la ligne à jour en utilisant l'enregistrement actif, utiliser une structure *try-catch* pour l'exception [[yii\db\StaleObjectException]]. Mettez en œuvre la logique requise (p. ex. fusionner les modification, avertir des données douteuses) pour résoudre le conflit. -Par exemple, supposons que la colonne du numéro de version est nommée `version`. Vous pouvez mettre en œuvre le verrouillage optimiste avec un code similaire au suivant : +3. Dans la classe de votre modèle, mettez en œuvre [[\yii\behaviors\OptimisticLockBehavior|OptimisticLockBehavior]] pour analyser automatiquement sa valeur des requêtes reçues. +4. Dans le formulaire Web qui reçoit les entrées de l'utilisateur, ajoutez un champ caché pour stocker le numéro de version courant de la ligne en modification. + Retirez l'attribut version des règles de validation étant donné que [[\yii\behaviors\OptimisticLockBehavior|OptimisticLockBehavior]] s'en charge. +5. Dans l'action de contrôleur qui met la ligne à jour en utilisant l'enregistrement actif, utiliser une structure *try-catch* pour l'exception [[yii\db\StaleObjectException]]. + Mettez en œuvre la logique requise (p. ex. fusionner les modifications, avertir des données douteuses) pour résoudre le conflit. +Par exemple, supposons que la colonne du numéro de version est nommée `version`. + Vous pouvez mettre en œuvre le verrouillage optimiste avec un code similaire au suivant : + ```php // ------ view code ------- use yii\helpers\Html; -// ...autres champs de saisie +// ...other input fields echo Html::activeHiddenInput($model, 'version'); @@ -562,20 +777,41 @@ public function actionUpdate($id) ]); } } catch (StaleObjectException $e) { - // logique de résolution du conflit + // logique pour résoudre le conflict } } + +// ------ model code ------- + +use yii\behaviors\OptimisticLockBehavior; + +public function behaviors() +{ + return [ + OptimisticLockBehavior::className(), + ]; +} ``` +> Note : comme [[\yii\behaviors\OptimisticLockBehavior|OptimisticLockBehavior]] garantit que l'enregistrement n'est sauvegardé que +> si l'utilisateur soumet un numéro de version valide en analysant directement [[\yii\web\Request::getBodyParam()|getBodyParam()]], +> il peut être utile d'étendre votre classe de modèle et de réaliser l'étape 2 dans le modèle du parent lors de l'attachement du comportement (étape 3) à la classe enfant; +> ainsi vous pouvez disposer d'une instance dédiée à l'usage interne tout en liant l'autre aux contrôleurs chargés de recevoir +> les entrées de l'utilisateur final. En alternative, vous pouvez mettre en œuvre votre propre logique en configurant sa propriété [[\yii\behaviors\OptimisticLockBehavior::$value|value]]. ## Travail avec des données relationnelles -En plus de travailler avec des tables de base de données individuelles, l'enregistrement actif permet aussi de rassembler des données en relation, les rendant ainsi immédiatement accessibles via les données primaires. Par exemple, la donnée client est en relation avec les données commandes parce qu'un client peut avoir passé une ou plusieurs commandes. Avec les déclarations appropriées de cette relation, vous serez capable d'accéder aux commandes d'un client en utilisant l'expression `$customer->orders` qui vous renvoie les informations sur les commandes du client en terme de tableau d'instances `Order` (Commande) d'enregistrement actif. +En plus de travailler avec des tables de base de données individuelles, l'enregistrement actif permet aussi de rassembler des données en relation, les rendant ainsi immédiatement accessibles via les données primaires. +Par exemple, la donnée client est en relation avec les données commandes parce qu'un client peut avoir passé une ou plusieurs commandes. +Avec les déclarations appropriées de cette relation, vous serez capable d'accéder aux commandes d'un client en utilisant l'expression `$customer->orders` qui vous renvoie les informations sur les commandes du client en terme de tableau d'instances `Order` (Commande) d'enregistrement actif. + + ### Déclaration de relations -Pour travailler avec des données relationnelles en utilisant l'enregistrement actif, vous devez d'abord déclarer les relations dans les classes d'enregistrement actif. La tâche est aussi simple que de déclarer une *méthode de relation* pour chacune des relations concernées, comme ceci : +Pour travailler avec des données relationnelles en utilisant l'enregistrement actif, vous devez d'abord déclarer les relations dans les classes d'enregistrement actif. +La tâche est aussi simple que de déclarer une *méthode de relation* pour chacune des relations concernées, comme ceci : ```php class Customer extends ActiveRecord @@ -601,19 +837,33 @@ class Order extends ActiveRecord Dans le code ci-dessus, nous avons déclaré une relation `orders` (commandes) pour la classe `Customer` (client), et une relation `customer` (client) pour la classe `Order` (commande). -Chacune des méthodes de relation doit être nommée sous la forme `getXyz`. Nous appelons `xyz` (la première lettre est en bas de casse) le *nom de la relation*. Notez que les noms de relation sont *sensibles à la casse*. + +Chacune des méthodes de relation doit être nommée sous la forme `getXyz`. Nous appelons `xyz` (la première lettre est en bas de casse) le *nom de la relation*. +Notez que les noms de relation sont *sensibles à la casse*. En déclarant une relation, vous devez spécifier les informations suivantes : -- la multiplicité de la relation : spécifiée en appelant soit la méthode [[yii\db\ActiveRecord::hasMany()|hasMany()]], soit la méthode [[yii\db\ActiveRecord::hasOne()|hasOne()]]. Dans l'exemple ci-dessus vous pouvez facilement déduire en lisant la déclaration des relations qu'un client a beaucoup de commandes, tandis qu'une commande n'a qu'un client. -- le nom de la classe d'enregistrement actif : spécifié comme le premier paramètre de [[yii\db\ActiveRecord::hasMany()|hasMany()]] ou de [[yii\db\ActiveRecord::hasOne()|hasOne()]]. Une pratique conseillée est d'appeler `Xyz::className()` pour obtenir la chaîne de caractères représentant le nom de la classe de manière à bénéficier de l'auto-complètement de l'EDI et de la détection d'erreur dans l'étape de compilation. -- Le lien entre les deux types de données : spécifie le(s) colonne(s) via lesquelles les deux types de données sont en relation. Les valeurs du tableau sont les colonnes des données primaires (représentées par la classe d'enregistrement actif dont vous déclarez les relations), tandis que les clés sont les colonnes des données en relation. +- la multiplicité de la relation : spécifiée en appelant soit la méthode [[yii\db\ActiveRecord::hasMany()|hasMany()]], +soit la méthode [[yii\db\ActiveRecord::hasOne()|hasOne()]]. +Dans l'exemple ci-dessus vous pouvez facilement déduire en lisant la déclaration des relations qu'un client a beaucoup de commandes, tandis qu'une commande n'a qu'un client. +- le nom de la classe d'enregistrement actif : spécifié comme le premier paramètre de [[yii\db\ActiveRecord::hasMany()|hasMany()]] ou de [[yii\db\ActiveRecord::hasOne()|hasOne()]]. +Une pratique conseillée est d'appeler `Xyz::className()` +pour obtenir la chaîne de caractères représentant le nom de la classe de manière à bénéficier +de l'auto-complètement de l'EDI et de la détection d'erreur dans l'étape de compilation. +- Le lien entre les deux types de données : spécifie le(s) colonne(s) via lesquelles les deux types de données sont en relation. +Les valeurs du tableau sont les colonnes des données primaires (représentées par la classe d'enregistrement actif dont vous déclarez les relations), tandis que les clés sont les colonnes des données en relation. + + +Une règle simple pour vous rappeler cela est, comme vous le voyez dans l'exemple ci-dessus, d'écrire la colonne qui appartient à l'enregistrement actif en relation juste à coté de lui. +Vous voyez là que l'identifiant du client (`customer_id`) est une propriété de `Order` et `id` est une propriété de `Customer`. + -Une règle simple pour vous rappeler cela est, comme vous le voyez dans l'exemple ci-dessus, d'écrire la colonne qui appartient à l'enregistrement actif en relation juste à coté de lui. Vous voyez là que l'identifiant du client (`customer_id`) est une propriété de `Order` et `id` est une propriété de `Customer`. ### Accès aux données relationnelles -Après avoir déclaré des relations, vous pouvez accéder aux données relationnelles via le nom des relations. Tout se passe comme si vous accédiez à une [propriété](concept-properties.md) d'un objet défini par la méthode de relation. Pour cette raison, nous appelons cette propriété *propriété de relation*. Par exemple : +Après avoir déclaré des relations, vous pouvez accéder aux données relationnelles via le nom des relations. +Tout se passe comme si vous accédiez à une [propriété](concept-properties.md) d'un objet défini par la méthode de relation. Pour cette raison, nous appelons cette propriété *propriété de relation*. +Par exemple : ```php // SELECT * FROM `customer` WHERE `id` = 123 @@ -624,14 +874,24 @@ $customer = Customer::findOne(123); $orders = $customer->orders; ``` -> Info: lorsque vous déclarez une relation nommée `xyz` via une méthode d'obtention `getXyz()`, vous êtes capable d'accéder à `xyz` comme à un [objet property](concept-properties.md). Notez que le nom est sensible à la casse. +> Info : lorsque vous déclarez une relation nommée `xyz` via une méthode d'obtention `getXyz()`, vous êtes capable d'accéder à `xyz` comme à un [objet property](concept-properties.md). + Notez que le nom est sensible à la casse. + +Si une relation est déclarée avec la méthode [[yii\db\ActiveRecord::hasMany()|hasMany()]], l'accès à cette propriété de relation retourne un tableau des instances de l'enregistrement actif en relation ; +si une relation est déclarée avec la méthode [[yii\db\ActiveRecord::hasOne()|hasOne()]], l'accès à la propriété de relation retourne l'instance de l'enregistrement actif en relation, ou `null` si aucune donnée en relation n'est trouvée. -Si une relation est déclarée avec la méthode [[yii\db\ActiveRecord::hasMany()|hasMany()]], l'accès à cette propriété de relation retourne un tableau des instances de l'enregistrement actif en relation ; si une relation est déclarée avec la méthode [[yii\db\ActiveRecord::hasOne()|hasOne()]], l'accès à la propriété de relation retourne l'instance de l'enregistrement actif en relation, ou `null` si aucune donnée en relation n'est trouvée. -Lorsque vous accédez à une propriété de relation pour la première fois, une instruction SQL est exécutée comme le montre l'exemple précédent. Si la même propriété fait l'objet d'un nouvel accès, le résultat précédent est retourné sans exécuter à nouveau l'instruction SQL. Pour forcer l'exécution à nouveau de l'instruction SQL, vous devez d'abord annuler la définition de la propriété de relation : `unset($customer->orders)`. -> Note: bien que ce concept semble similaire à la fonctionnalité [propriété d'objet](concept-properties.md), il y a une différence importante. Pour les propriétés normales d'objet, la valeur est du même type que la méthode d'obtention de définition. Une méthode de relation cependant retourne toujours une instance d'[[yii\db\ActiveRecord]] ou un tableau de telles instances. +Lorsque vous accédez à une propriété de relation pour la première fois, une instruction SQL est exécutée comme le montre l'exemple précédent. +Si la même propriété fait l'objet d'un nouvel accès, le résultat précédent est retourné sans exécuter à nouveau l'instruction SQL. +Pour forcer l'exécution à nouveau de l'instruction SQL, vous devez d'abord annuler la définition de la propriété de relation : `unset($customer->orders)`. + + +> Note : bien que ce concept semble similaire à la fonctionnalité [propriété d'objet](concept-properties.md), il y a une différence importante. + Pour les propriétés normales d'objet, la valeur est du même type que la méthode d'obtention de définition. + Une méthode de relation cependant retourne toujours une instance d'[[yii\db\ActiveRecord]] ou un tableau de telles instances. > +> > ```php > $customer->orders; // est un tableau d'objets `Order` > $customer->getOrders(); // retourne une instance d'ActiveQuery @@ -642,7 +902,8 @@ Lorsque vous accédez à une propriété de relation pour la première fois, une ### Requête relationnelle dynamique -Parce qu'une méthode de relation retourne une instance d'[[yii\db\ActiveQuery]], vous pouvez continuer à construire cette requête en utilisant les méthodes de construction avant de l'exécuter. Par exemple : +Parce qu'une méthode de relation retourne une instance d'[[yii\db\ActiveQuery]], vous pouvez continuer à construire cette requête en utilisant les méthodes de construction avant de l'exécuter. +Par exemple : ```php $customer = Customer::findOne(123); @@ -656,7 +917,9 @@ $orders = $customer->getOrders() Contrairement à l'accès à une propriété de relation, chaque fois que vous effectuez une requête relationnelle dynamique via une méthode de relation, une instruction SQL est exécutée, même si la même requête relationnelle dynamique a été effectuée auparavant. -Parfois, vous voulez peut-être paramétrer une déclaration de relation de manière à ce que vous puissiez effectuer des requêtes relationnelles dynamiques plus facilement. Par exemple, vous pouvez déclarer une relation `bigOrders` comme ceci :, + +Parfois, vous voulez peut-être paramétrer une déclaration de relation de manière à ce que vous puissiez effectuer des requêtes relationnelles dynamiques plus facilement. +Par exemple, vous pouvez déclarer une relation `bigOrders` comme ceci :, ```php class Customer extends ActiveRecord @@ -683,9 +946,15 @@ $orders = $customer->bigOrders; ### Relations via une table de jointure -Dans la modélisation de base de données, lorsque la multiplicité entre deux tables en relation est *many-to-many* (de plusieurs à plusieurs), une [table de jointure](https://en.wikipedia.org/wiki/Junction_table) est en général introduite. Par exemple, la table `order` (commande) et la table `item` peuvent être en relation via une table de jointure nommée `order_item` (item_de_commande). Une commande correspond ensuite à de multiples items de commande, tandis qu'un item de produit correspond lui-aussi à de multiples items de commande (*order items*). +Dans la modélisation de base de données, lorsque la multiplicité entre deux tables en relation est *many-to-many* (de plusieurs à plusieurs), une [table de jointure](https://en.wikipedia.org/wiki/Junction_table) est en général introduite. +Par exemple, la table `order` (commande) et la table `item` peuvent être en relation via une table de jointure nommée `order_item` (item_de_commande). +Une commande correspond ensuite à de multiples items de commande, tandis qu'un item de produit correspond lui-aussi à de multiples items de commande (*order items*). + -Lors de la déclaration de telles relations, vous devez appeler soit [[yii\db\ActiveQuery::via()|via()]], soit [[yii\db\ActiveQuery::viaTable()|viaTable()]], pour spécifier la table de jointure. La différence entre [[yii\db\ActiveQuery::via()|via()]] et [[yii\db\ActiveQuery::viaTable()|viaTable()]] est que la première spécifie la table de jointure en termes de noms de relation existante, tandis que la deuxième utilise directement la table de jointure. Par exemple : +Lors de la déclaration de telles relations, vous devez appeler soit [[yii\db\ActiveQuery::via()|via()]], +soit [[yii\db\ActiveQuery::viaTable()|viaTable()]], pour spécifier la table de jointure. +La différence entre [[yii\db\ActiveQuery::via()|via()]] et [[yii\db\ActiveQuery::viaTable()|viaTable()]] est que la première spécifie la table de jointure en termes de noms de relation existante, tandis que la deuxième utilise directement la table de jointure. +Par exemple : ```php class Order extends ActiveRecord @@ -729,9 +998,47 @@ $items = $order->items; ``` +### Chaînage de définitions de relation via de multiples tables + +Il est de plus possible de définir des relations via de multiples tables en chaînant les définitions de relation en utilisant [[yii\db\ActiveQuery::via()|via()]]. +En reprenant l'exemple ci-dessus, nous avons les classes `Customer`, `Order` et `Item`. +Nous pouvons ajouter une relation à la classe `Customer` qui liste tous les items de tous les commandes qu'ils ont passées, +et la nommer `getPurchasedItems()`, le chaînage de relations est présenté dans l'exemple de code suivant : + +```php +class Customer extends ActiveRecord +{ + // ... + + public function getPurchasedItems() + { + // items de clients pour lesquels la colonne 'id' de `Item` correspond à 'item_id' dans OrderItem + return $this->hasMany(Item::className(), ['id' => 'item_id']) + ->via('orderItems'); + } + + public function getOrderItems() + { + // items de commandes clients pour lesquels, la colonne 'id' de `Order` correspond à 'order_id' dans OrderItem + return $this->hasMany(OrderItem::className(), ['order_id' => 'id']) + ->via('orders'); + } + + public function getOrders() + { + // idem à ci-dessus + return $this->hasMany(Order::className(), ['customer_id' => 'id']); + } +} +``` + + ### Chargement paresseux et chargement précoce -Dans la sous-section [Accès aux données relationnelles](#accessing-relational-data), nous avons expliqué que vous pouvez accéder à une propriété de relation d'une instance d'enregistrement actif comme si vous accédiez à une propriété normale d'objet. Une instruction SQL est exécutée seulement lorsque vous accédez à cette propriété pour la première fois. Nous appelons une telle méthode d'accès à des données relationnelles, *chargement paresseux*. Par exemple : +Dans la sous-section [Accès aux données relationnelles](#accessing-relational-data), nous avons expliqué que vous pouvez accéder à une propriété de relation d'une instance d'enregistrement actif comme si vous accédiez à une propriété normale d'objet. +Une instruction SQL est exécutée seulement lorsque vous accédez à cette propriété pour la première fois. +Nous appelons une telle méthode d'accès à des données relationnelles, *chargement paresseux*. +Par exemple : ```php // SELECT * FROM `customer` WHERE `id` = 123 @@ -744,7 +1051,9 @@ $orders = $customer->orders; $orders2 = $customer->orders; ``` -Le chargement paresseux est très pratique à utiliser. Néanmoins, il peut souffrir d'un problème de performance lorsque vous avez besoin d'accéder à la même propriété de relation sur de multiples instances d'enregistrement actif. Examinons l'exemple de code suivant. Combien d'instruction SQL sont-elles exécutées ? +Le chargement paresseux est très pratique à utiliser. +Néanmoins, il peut souffrir d'un problème de performance lorsque vous avez besoin d'accéder à la même propriété de relation sur de multiples instances d'enregistrement actif. +Examinons l'exemple de code suivant. Combien d'instruction SQL sont-elles exécutées ? ```php // SELECT * FROM `customer` LIMIT 100 @@ -756,7 +1065,9 @@ foreach ($customers as $customer) { } ``` -Comme vous pouvez le constater dans le fragment de code ci-dessus, 101 instruction SQL sont exécutées ! Cela tient au fait que, à chaque fois que vous accédez à la propriété de relation `orders` d'un objet client différent dans la boucle for, une instruction SQL est exécutée. +Comme vous pouvez le constater dans le fragment de code ci-dessus, 101 instruction SQL sont exécutées ! +Cela tient au fait que, à chaque fois que vous accédez à la propriété de relation `orders` d'un objet client différent dans la boucle for, une instruction SQL est exécutée. + Pour résoudre ce problème de performance, vous pouvez utiliser ce qu'on appelle le *chargement précoce* comme montré ci-dessous : @@ -774,11 +1085,16 @@ foreach ($customers as $customer) { } ``` -En appelant [[yii\db\ActiveQuery::with()]], vous donner comme instruction à l'enregistrement actif de rapporter les commandes (*orders*) pour les 100 premiers clients (*customers*) en une seule instruction SQL. En conséquence, vous réduisez le nombre d'instructions SQL de 101 à 2 ! +En appelant [[yii\db\ActiveQuery::with()]], vous donner comme instruction à l'enregistrement actif de rapporter les commandes (*orders*) pour les 100 premiers clients (*customers*) en une seule instruction SQL. +En conséquence, vous réduisez le nombre d'instructions SQL de 101 à 2 ! -Vous pouvez charger précocement une ou plusieurs relations. Vous pouvez même charger précocement des *relations imbriquées*. Une relation imbriquée est une relation qui est déclarée dans une classe d'enregistrement actif. Par exemple, `Customer` est en relation avec `Order` via la relation `orders`, et `Order` est en relation avec `Item` via la relation `items`. Lorsque vous effectuez une requête pour `Customer`, vous pouvez charger précocement `items` en utilisant la notation de relation imbriquée `orders.items`. +Vous pouvez charger précocement une ou plusieurs relations. Vous pouvez même charger précocement des *relations imbriquées*. +Une relation imbriquée est une relation qui est déclarée dans une classe d'enregistrement actif. +Par exemple, `Customer` est en relation avec `Order` via la relation `orders`, et `Order` est en relation avec `Item` via la relation `items`. +Lorsque vous effectuez une requête pour `Customer`, vous pouvez charger précocement `items` en utilisant la notation de relation imbriquée `orders.items`. -Le code suivant montre différentes utilisations de [[yii\db\ActiveQuery::with()|with()]]. Nous supposons que la classe `Customer` possède deux relations `orders` (commandes) et `country` (pays), tandis que la classe `Order` possède une relation `items`. +Le code suivant montre différentes utilisations de [[yii\db\ActiveQuery::with()|with()]]. +Nous supposons que la classe `Customer` possède deux relations `orders` (commandes) et `country` (pays), tandis que la classe `Order` possède une relation `items`. ```php // chargement précoce à la fois de "orders" et de "country" @@ -797,11 +1113,16 @@ $customers = Customer::find()->with('orders.items')->all(); $items = $customers[0]->orders[0]->items; ``` -Vous pouvez charger précocement des relations imbriquées en profondeur, telles que `a.b.c.d`. Toutes les relations parentes sont chargées précocement. C'est à dire, que lorsque vous appelez [[yii\db\ActiveQuery::with()|with()]] en utilisant `a.b.c.d`, vous chargez précocement `a`, `a.b`, `a.b.c` et `a.b.c.d`. +Vous pouvez charger précocement des relations imbriquées en profondeur, telles que `a.b.c.d`. Toutes les relations parentes sont chargées précocement. +C'est à dire, que lorsque vous appelez [[yii\db\ActiveQuery::with()|with()]] en utilisant `a.b.c.d`, vous chargez précocement `a`, `a.b`, `a.b.c` et `a.b.c.d`. + -> Info: en général, lors du chargement précoce de `N` relations parmi lesquelles `M` relations sont définies par une [table de jointure](#junction-table), `N+M+1` instructions SQL sont exécutées au total. Notez qu'une relation imbriquée `a.b.c.d` possède 4 relations. +> Info : en général, lors du chargement précoce de `N` relations parmi lesquelles `M` relations sont définies par une [table de jointure](#junction-table), `N+M+1` instructions SQL sont exécutées au total. +Notez qu'une relation imbriquée `a.b.c.d` possède 4 relations. -Lorsque vous chargez précocement une relation, vous pouvez personnaliser le requête relationnelle correspondante en utilisant une fonction anonyme. Par exemple : + +Lorsque vous chargez précocement une relation, vous pouvez personnaliser le requête relationnelle correspondante en utilisant une fonction anonyme. +Par exemple : ```php // trouve les clients et rapporte leur pays et leurs commandes actives @@ -816,9 +1137,14 @@ $customers = Customer::find()->with([ ])->all(); ``` -Lors de la personnalisation de la requête relationnelle pour une relation, vous devez spécifier le nom de la relation comme une clé de tableau et utiliser une fonction anonyme comme valeur de tableau correspondante. La fonction anonyme accepte une paramètre `$query` qui représente l'objet [[yii\db\ActiveQuery]] utilisé pour effectuer la requête relationnelle pour la relation. Dans le code ci-dessus, nous modifions la requête relationnelle en ajoutant une condition additionnelle à propos de l'état de la commande (*order*). +Lors de la personnalisation de la requête relationnelle pour une relation, vous devez spécifier le nom de la relation comme une clé de tableau et utiliser une fonction anonyme comme valeur de tableau correspondante. +La fonction anonyme accepte une paramètre `$query` qui représente l'objet [[yii\db\ActiveQuery]] utilisé pour effectuer la requête relationnelle pour la relation. +Dans le code ci-dessus, nous modifions la requête relationnelle en ajoutant une condition additionnelle à propos de l'état de la commande (*order*). + -> Note: si vous appelez [[yii\db\Query::select()|select()]] tout en chargeant précocement les relations, vous devez vous assurer que les colonnes référencées dans la déclaration de la relation sont sélectionnées. Autrement, les modèles en relation peuvent ne pas être chargés correctement. Par exemple : +> Note : si vous appelez [[yii\db\Query::select()|select()]] tout en chargeant précocement les relations, vous devez vous assurer que les colonnes référencées dans la déclaration de la relation sont sélectionnées. +> Autrement, les modèles en relation peuvent ne pas être chargés correctement. +> Par exemple : > > ```php > $orders = Order::find()->select(['id', 'amount'])->with('customer')->all(); @@ -829,9 +1155,13 @@ Lors de la personnalisation de la requête relationnelle pour une relation, vous ### Jointure avec des relations -> Note: le contenu décrit dans cette sous-section ne s'applique qu'aux bases de données relationnelles, telles que MySQL, PostgreSQL, etc. +> Note : le contenu décrit dans cette sous-section ne s'applique qu'aux bases de données relationnelles, telles que MySQL, PostgreSQL, etc. + -Les requêtes relationnelles que nous avons décrites jusqu'à présent ne font référence qu'aux colonnes de table primaires lorsque nous faisons une requête des données primaires. En réalité, nous avons souvent besoin de faire référence à des colonnes dans les tables en relation. Par exemple, vous désirez peut-être rapporter les clients qui ont au moins une commande active. Pour résoudre ce problème, nous pouvons construire une requête avec jointure comme suit : +Les requêtes relationnelles que nous avons décrites jusqu'à présent ne font référence qu'aux colonnes de table primaires lorsque nous faisons une requête des données primaires. +En réalité, nous avons souvent besoin de faire référence à des colonnes dans les tables en relation. +Par exemple, vous désirez peut-être rapporter les clients qui ont au moins une commande active. +Pour résoudre ce problème, nous pouvons construire une requête avec jointure comme suit : ```php // SELECT `customer`.* FROM `customer` @@ -847,7 +1177,8 @@ $customers = Customer::find() ->all(); ``` -> Note: il est important de supprimer les ambiguïtés sur les noms de colonnes lorsque vous construisez les requêtes relationnelles faisant appel à des instructions SQL JOIN. Une pratique courante est de préfixer les noms de colonnes par le nom des tables correspondantes. +> Note : il est important de supprimer les ambiguïtés sur les noms de colonnes lorsque vous construisez les requêtes relationnelles faisant appel à des instructions SQL JOIN. +> Une pratique courante est de préfixer les noms de colonnes par le nom des tables correspondantes. Néanmoins, une meilleure approche consiste à exploiter les déclarations de relations existantes en appelant [[yii\db\ActiveQuery::joinWith()]] : @@ -860,11 +1191,19 @@ $customers = Customer::find() Les deux approches exécutent le même jeu d'instructions SQL. La deuxième approche est plus propre et plus légère cependant. -Par défaut, [[yii\db\ActiveQuery::joinWith()|joinWith()]] utilise `LEFT JOIN` pour joindre la table primaire avec les tables en relation. Vous pouvez spécifier une jointure différente (p .ex. `RIGHT JOIN`) via sont troisième paramètre `$joinType`. Si le type de jointure que vous désirez est `INNER JOIN`, vous pouvez simplement appeler [[yii\db\ActiveQuery::innerJoinWith()|innerJoinWith()]], à la place. +Par défaut, [[yii\db\ActiveQuery::joinWith()|joinWith()]] utilise `LEFT JOIN` pour joindre la table primaire avec les tables en relation. +Vous pouvez spécifier une jointure différente (p .ex. `RIGHT JOIN`) via son troisième paramètre `$joinType`. +Si le type de jointure que vous désirez est `INNER JOIN`, vous pouvez simplement appeler [[yii\db\ActiveQuery::innerJoinWith()|innerJoinWith()]], à la place. -L'appel de [[yii\db\ActiveQuery::joinWith()|joinWith()]] [charge précocement](#lazy-eager-loading) les données en relation par défaut. Si vous ne voulez pas charger les données en relation, vous pouvez spécifier son deuxième paramètre `$eagerLoading` comme étant `false`. +L'appel de [[yii\db\ActiveQuery::joinWith()|joinWith()]] [charge précocement](#lazy-eager-loading) les données en relation par défaut. +Si vous ne voulez pas charger les données en relation, vous pouvez spécifier son deuxième paramètre `$eagerLoading` comme étant `false`. -Comme avec [[yii\db\ActiveQuery::with()|with()]], vous pouvez joindre une ou plusieurs relations ; vous pouvez personnaliser les requêtes de relation à la volée ; vous pouvez joindre des relations imbriquées ; et vous pouvez mélanger l'utilisation de [[yii\db\ActiveQuery::with()|with()]] et celle de [[yii\db\ActiveQuery::joinWith()|joinWith()]]. Par exemple : +> Note : même en utilisant [[yii\db\ActiveQuery::joinWith()|joinWith()]] ou [[yii\db\ActiveQuery::innerJoinWith()|innerJoinWith()]] + avec le chargement précoce activé les données en relation ne sont **pas** peuplées à partir du résultat de la requête `JOIN`. C'est pourquoi il y a + toujours une requête supplémetaire pour chacune des relations jointes comme expliqué à la section [chargement précoce](#lazy-eager-loading). + +Comme avec [[yii\db\ActiveQuery::with()|with()]], vous pouvez joindre une ou plusieurs relations ; vous pouvez personnaliser les requêtes de relation à la volée ; vous pouvez joindre des relations imbriquées ; et vous pouvez mélanger l'utilisation de [[yii\db\ActiveQuery::with()|with()]] et celle de [[yii\db\ActiveQuery::joinWith()|joinWith()]]. +Par exemple : ```php $customers = Customer::find()->joinWith([ @@ -875,7 +1214,9 @@ $customers = Customer::find()->joinWith([ ->all(); ``` -Parfois, en joignant deux tables, vous désirez peut-être spécifier quelques conditions supplémentaires dans la partie `ON` de la requête JOIN. Cela peut être réalisé en appelant la méthode [[yii\db\ActiveQuery::onCondition()]] comme ceci : +Parfois, en joignant deux tables, vous désirez peut-être spécifier quelques conditions supplémentaires dans la partie `ON` de la requête JOIN. +Cela peut être réalisé en appelant la méthode [[yii\db\ActiveQuery::onCondition()]] +comme ceci : ```php // SELECT `customer`.* FROM `customer` @@ -889,13 +1230,18 @@ $customers = Customer::find()->joinWith([ ])->all(); ``` -La requête ci-dessus retourne *tous* les clients, et pour chacun des clients, toutes les commandes actives. Notez que cela est différent de notre exemple précédent qui ne retourne que les clients qui ont au moins une commande active. +La requête ci-dessus retourne *tous* les clients, et pour chacun des clients, toutes les commandes actives. +Notez que cela est différent de notre exemple précédent qui ne retourne que les clients qui ont au moins une commande active. + +> Info : quand [[yii\db\ActiveQuery]] est spécifiée avec une condition via une jointure [[yii\db\ActiveQuery::onCondition()|onCondition()]], la condition est placée dans la partie `ON` si la requête fait appel à une requête JOIN. +Si la requête ne fait pas appel à JOIN, la *on-condition* est automatiquement ajoutée à la partie `WHERE` de la requête. +Par conséquent elle peut ne contenir que des conditions incluant des colonnes de la table en relation. -> Info: quand [[yii\db\ActiveQuery]] est spécifiée avec une condition via une jointure [[yii\db\ActiveQuery::onCondition()|onCondition()]], la condition est placée dans la partie `ON` si la requête fait appel à une requête JOIN. Si la requête ne fait pas appel à JOIN, la *on-condition* est automatiquement ajoutée à la partie `WHERE` de la requête. Par conséquent elle peut ne contenir que des conditions incluant des colonnes de la table en relation. #### Alias de table de relation -Comme noté auparavant, lorsque vous utilisez une requête JOIN, vous devez lever les ambiguïtés sur le nom des colonnes. Pour cela, un alias est souvent défini pour une table. Définir un alias pour la requête relationnelle serait possible en personnalisant le requête de relation de la manière suivante : +Comme noté auparavant, lorsque vous utilisez une requête JOIN, vous devez lever les ambiguïtés sur le nom des colonnes. +Pour cela, un alias est souvent défini pour une table. Définir un alias pour la requête relationnelle serait possible en personnalisant le requête de relation de la manière suivante : ```php $query->joinWith([ @@ -905,16 +1251,29 @@ $query->joinWith([ ]) ``` -Cela paraît cependant très compliqué et implique soit de coder en dur les noms de tables des objets en relation, soit d'appeler `Order::tableName()`. Depuis la version 2.0.7, Yii fournit un raccourci pour cela. Vous pouvez maintenant définir et utiliser l'alias pour la table de relation comme ceci : +Cela paraît cependant très compliqué et implique soit de coder en dur les noms de tables des objets en relation, soit d'appeler `Order::tableName()`. +Depuis la version 2.0.7, Yii fournit un raccourci pour cela. Vous pouvez maintenant définir et utiliser l'alias pour la table de relation comme ceci : ```php // joint la relation orders et trie les résultats par orders.id $query->joinWith(['orders o'])->orderBy('o.id'); ``` +La syntaxe ci-dessus ne fonctionne que pour des relations simples. Si vous avez besoin d'un alias pour une table intermédiaire lors de la jointure via des relations imbriquées, p. ex. `$query->joinWith(['orders.product'])`, +vous devez imbriquer les appels joinWith comme le montre l'exemple suivant : + +```php +$query->joinWith(['orders o' => function($q) { + $q->joinWith('product p'); + }]) + ->where('o.amount > 100'); +``` + + ### Relations inverses -Les déclarations de relations sont souvent réciproques entre deux classes d'enregistrement actif. Par exemple, `Customer` est en relation avec `Order` via la relation `orders`, et `Order` est en relation inverse avec `Customer` via la relation `customer`. +Les déclarations de relations sont souvent réciproques entre deux classes d'enregistrement actif. +Par exemple, `Customer` est en relation avec `Order` via la relation `orders`, et `Order` est en relation inverse avec `Customer` via la relation `customer`. ```php class Customer extends ActiveRecord @@ -950,11 +1309,14 @@ $customer2 = $order->customer; echo $customer2 === $customer ? 'same' : 'not the same'; ``` -On aurait tendance à penser que `$customer` et `$customer2` sont identiques, mais ils ne le sont pas ! En réalité, ils contiennent les mêmes données de client, mais ce sont des objets différents. En accédant à `$order->customer`, une instruction SQL supplémentaire est exécutée pour remplir un nouvel objet `$customer2`. +On aurait tendance à penser que `$customer` et `$customer2` sont identiques, mais ils ne le sont pas ! +En réalité, ils contiennent les mêmes données de client, mais ce sont des objets différents. +En accédant à `$order->customer`, une instruction SQL supplémentaire est exécutée pour remplir un nouvel objet `$customer2`. Pour éviter l'exécution redondante de la dernière instruction SQL dans l'exemple ci-dessus, nous devons dire à Yii que `customer` est une *relation inverse* de `orders` en appelant la méthode [[yii\db\ActiveQuery::inverseOf()|inverseOf()]] comme ci-après : + ```php class Customer extends ActiveRecord { @@ -981,12 +1343,16 @@ $customer2 = $order->customer; echo $customer2 === $customer ? 'same' : 'not the same'; ``` -> Note: les relations inverses ne peuvent être définies pour des relations faisant appel à une [table de jointure](#junction-table). C'est à dire que, si une relation est définie avec [[yii\db\ActiveQuery::via()|via()]] ou avec [[yii\db\ActiveQuery::viaTable()|viaTable()]], vous ne devez pas appeler [[yii\db\ActiveQuery::inverseOf()|inverseOf()]] ensuite. +> Note : les relations inverses ne peuvent être définies pour des relations faisant appel à une [table de jointure](#junction-table). +C'est à dire que, si une relation est définie avec [[yii\db\ActiveQuery::via()|via()]] ou avec [[yii\db\ActiveQuery::viaTable()|viaTable()]], vous ne devez pas appeler [[yii\db\ActiveQuery::inverseOf()|inverseOf()]] ensuite. + ## Sauvegarde des relations -En travaillant avec des données relationnelles, vous avez souvent besoin d'établir de créer des relations entre différentes données ou de supprimer des relations existantes. Cela requiert de définir les valeurs appropriées pour les colonnes qui définissent ces relations. En utilisant l'enregistrement actif, vous pouvez vous retrouver en train d'écrire le code de la façon suivante : +En travaillant avec des données relationnelles, vous avez souvent besoin d'établir de créer des relations entre différentes données ou de supprimer des relations existantes. +Cela requiert de définir les valeurs appropriées pour les colonnes qui définissent ces relations. +En utilisant l'enregistrement actif, vous pouvez vous retrouver en train d'écrire le code de la façon suivante : ```php $customer = Customer::findOne(123); @@ -999,7 +1365,7 @@ $order->customer_id = $customer->id; $order->save(); ``` -L'enregistrement actif fournit la méthode [[yii\db\ActiveRecord::link()|link()]]qui vous permet d'accomplir cette tâche plus élégamment : +L'enregistrement actif fournit la méthode [[yii\db\ActiveRecord::link()|link()]] qui vous permet d'accomplir cette tâche plus élégamment : ```php $customer = Customer::findOne(123); @@ -1010,11 +1376,17 @@ $order->subtotal = 100; $order->link('customer', $customer); ``` -La méthode [[yii\db\ActiveRecord::link()|link()]] requiert que vous spécifiiez le nom de la relation et l'instance d'enregistrement actif cible avec laquelle le relation doit être établie. La méthode modifie les valeurs des attributs qui lient deux instances d'enregistrement actif et les sauvegarde dans la base de données. Dans l'exemple ci-dessus, elle définit l'attribut `customer_id` de l'instance `Order` comme étant la valeur de l'attribut `id` de l'instance `Customer` et le sauvegarde ensuite dans la base de données. +La méthode [[yii\db\ActiveRecord::link()|link()]] requiert que vous spécifiiez le nom de la relation et l'instance d'enregistrement actif cible avec laquelle le relation doit être établie. +La méthode modifie les valeurs des attributs qui lient deux instances d'enregistrement actif et les sauvegardes dans la base de données. +Dans l'exemple ci-dessus, elle définit l'attribut `customer_id` de l'instance `Order` comme étant la valeur de l'attribut `id` de l'instance `Customer` et le sauvegarde ensuite dans la base de données. -> Note: vous ne pouvez pas lier deux instances d'enregistrement actif nouvellement créées. -L'avantage d'utiliser [[yii\db\ActiveRecord::link()|link()]] est même plus évident lorsqu'une relation est définie via une [table de jointure](#junction-table). Par exemple, vous pouvez utiliser le code suivant pour lier une instance de `Order` à une instance de `Item` : + +> Note : vous ne pouvez pas lier deux instances d'enregistrement actif nouvellement créées. + +L'avantage d'utiliser [[yii\db\ActiveRecord::link()|link()]] +est même plus évident lorsqu'une relation est définie via une [table de jointure](#junction-table). +Par exemple, vous pouvez utiliser le code suivant pour lier une instance de `Order` à une instance de `Item` : ```php $order->link('items', $item); @@ -1022,23 +1394,32 @@ $order->link('items', $item); Le code ci-dessus insère automatiquement une ligne dans la table de jointure `order_item` pour mettre la commande en relation avec l'item. -> Info: la méthode [[yii\db\ActiveRecord::link()|link()]] n'effectue AUCUNE validation de données lors de la sauvegarde de l'instance d'enregistrement actif affectée. Il est de votre responsabilité de valider toutes les données entrées avant d'appeler cette méthode. +> Info : la méthode [[yii\db\ActiveRecord::link()|link()]] n'effectue AUCUNE validation de données lors de la sauvegarde de l'instance d'enregistrement actif affectée. +> Il est de votre responsabilité de valider toutes les données entrées avant d'appeler cette méthode. + -L'opération opposée à [[yii\db\ActiveRecord::link()|link()]] est [[yii\db\ActiveRecord::unlink()|unlink()]] qui casse une relation existante entre deux instances d'enregistrement actif. Par exemple : +L'opération opposée à [[yii\db\ActiveRecord::link()|link()]] est [[yii\db\ActiveRecord::unlink()|unlink()]] +qui casse une relation existante entre deux instances d'enregistrement actif. Par exemple : ```php $customer = Customer::find()->with('orders')->where(['id' => 123])->one(); $customer->unlink('orders', $customer->orders[0]); ``` -Par défaut, la méthode [[yii\db\ActiveRecord::unlink()|unlink()]] définit la valeur de la (des) clé(s) qui spécifie(nt) la relation existante à `null`. Vous pouvez cependant, choisir de supprimer la ligne de la table qui contient la valeur de clé étrangère en passant à la méthode la valeur `true` pour le paramètre `$delete`. +Par défaut, la méthode [[yii\db\ActiveRecord::unlink()|unlink()]] définit la valeur de la (des) clé(s) étrangères qui spécifie(nt) la relation existante à `null`. +Vous pouvez cependant, choisir de supprimer la ligne de la table qui contient la valeur de clé étrangère en passant à la méthode la valeur `true` pour le paramètre `$delete`. + Lorsqu'une table de jointure est impliquée dans une relation, appeler [[yii\db\ActiveRecord::unlink()|unlink()]] provoque l'effacement des clés étrangères dans la table de jointure, ou l'effacement de la ligne correspondante dans la table de jointure si `#delete` vaut `true`. + + ## Relations inter bases de données -L'enregistrement actif vous permet de déclarer des relations entre les classes d'enregistrement actif qui sont mise en œuvre par différentes bases de données. Les bases de données peuvent être de types différents (p. ex. MySQL and PostgreSQL, ou MS SQL et MongoDB), et elles peuvent s'exécuter sur des serveurs différents. Vous pouvez utiliser la même syntaxe pour effectuer des requêtes relationnelles. Par exemple : +L'enregistrement actif vous permet de déclarer des relations entre les classes d'enregistrement actif qui sont mise en œuvre par différentes bases de données. +Les bases de données peuvent être de types différents (p. ex. MySQL and PostgreSQL, ou MS SQL et MongoDB), et elles peuvent s'exécuter sur des serveurs différents. +Vous pouvez utiliser la même syntaxe pour effectuer des requêtes relationnelles. Par exemple : ```php // Customer est associé à la table "customer" dans la base de données relationnelle (e.g. MySQL) @@ -1076,12 +1457,15 @@ $customers = Customer::find()->with('comments')->all(); Vous pouvez utiliser la plupart des fonctionnalités de requêtes relationnelles qui ont été décrites dans cette section. -> Note: l'utilisation de [[yii\db\ActiveQuery::joinWith()|joinWith()]] est limitée aux bases de données qui permettent les requête JOIN inter bases. Pour cette raison, vous ne pouvez pas utiliser cette méthode dans l'exemple ci-dessus car MongoDB ne prend pas JOIN en charge. +> Note : l'utilisation de [[yii\db\ActiveQuery::joinWith()|joinWith()]] est limitée aux bases de données qui permettent les requête JOIN inter bases. +Pour cette raison, vous ne pouvez pas utiliser cette méthode dans l'exemple ci-dessus car MongoDB ne prend pas JOIN en charge. ## Personnalisation des classes de requête -Par défaut, toutes les requêtes d'enregistrement actif sont prises en charge par [[yii\db\ActiveQuery]]. Pour utiliser une classe de requête personnalisée dans une classe d'enregistrement actif, vous devez redéfinir la méthode [[yii\db\ActiveRecord::find()]] et retourner une instance de votre classe de requête personnalisée .Par exemple : +Par défaut, toutes les requêtes d'enregistrement actif sont prises en charge par [[yii\db\ActiveQuery]]. +Pour utiliser une classe de requête personnalisée dans une classe d'enregistrement actif, vous devez redéfinir la méthode [[yii\db\ActiveRecord::find()]] et retourner une instance de votre classe de requête personnalisée . +Par exemple : ```php namespace app\models; @@ -1096,38 +1480,51 @@ class Comment extends ActiveRecord return new CommentQuery(get_called_class()); } } - -class CommentQuery extends ActiveQuery -{ - // ... -} ``` Désormais, à chaque fois que vous effectuez une requête (p. ex. `find()`, `findOne()`) ou définissez une relation (p. ex. `hasOne()`) avec `Comment`, vous travaillez avec une instance de `CommentQuery` au lieu d'une instance d'`ActiveQuery`. -> Tip: dans les gros projets, il est recommandé que vous utilisiez des classes de requête personnalisées pour contenir la majeure partie de code relatif aux requêtes de manière à ce que les classe d'enregistrement actif puissent être maintenues propres. -Vous pouvez personnaliser une classe de requête de plusieurs manières créatives pour améliorer votre expérience de la construction de requêtes. Par exemple, vous pouvez définir de nouvelles méthodes de construction de requête dans des classes de requête personnalisées : +Vous devez maintenant définir la classe `CommentQuery`, qui peut être personnalisée de maintes manières créatives pour améliorer votre expérience de la construction de requête. Par exemple : ```php +// fichier CommentQuery.php +namespace app\models; + +use yii\db\ActiveQuery; + class CommentQuery extends ActiveQuery { + // conditions ajoutées par défaut (peut être sauté) + public function init() + { + $this->andOnCondition(['deleted' => false]); + parent::init(); + } + + // ... ajoutez vos méthodes de requêtes personnalisées ici ... + public function active($state = true) { - return $this->andWhere(['active' => $state]); + return $this->andOnCondition(['active' => $state]); } } ``` -> Note: au lieu d'appeler [[yii\db\ActiveQuery::where()|where()]], vous devez ordinairement appeler [[yii\db\ActiveQuery::andWhere()|andWhere()]] ou [[yii\db\ActiveQuery::orWhere()|orWhere()]] pour ajouter des conditions additionnelles lors de la définition de nouvelles méthodes de construction de requête afin que les conditions existantes ne soient pas redéfinies. +> Note : au lieu d'appeler [[yii\db\ActiveQuery::onCondition()|onCondition()]], vous devez généralement appeler + [[yii\db\ActiveQuery::andOnCondition()|andOnCondition()]] ou [[yii\db\ActiveQuery::orOnCondition()|orOnCondition()]] + pour ajouter des conditions supplémentaires lors de la définition de nouvelles méthodes de requête de façon à ce que aucune condition existante en soit redéfinie. + +Cela vous permet d'écrire le code de construction de requête comme suit : -Cela vous permet d'écrire le code de construction de requêtes comme suit : - ```php $comments = Comment::find()->active()->all(); $inactiveComments = Comment::find()->active(false)->all(); ``` +> Astuce : dans les gros projets, il est recommandé que vous utilisiez des classes de requête personnalisées pour contenir la majeure partie de code relatif aux requêtes de manière à ce que les classe d'enregistrement actif puissent être maintenues propres. + + Vous pouvez aussi utiliser les méthodes de construction de requêtes en définissant des relations avec `Comment` ou en effectuant une requête relationnelle : ```php @@ -1139,25 +1536,39 @@ class Customer extends \yii\db\ActiveRecord } } -$customers = Customer::find()->with('activeComments')->all(); +$customers = Customer::find()->joinWith('activeComments')->all(); -// ou alternativement - -$customers = Customer::find()->with([ +// ou en alternative +class Customer extends \yii\db\ActiveRecord +{ + public function getComments() + { + return $this->hasMany(Comment::className(), ['customer_id' => 'id']); + } +} + +$customers = Customer::find()->joinWith([ 'comments' => function($q) { $q->active(); } ])->all(); ``` -> Info: dans Yii 1.1, il existe un concept appelé *scope*. Scope n'est plus pris en charge directement par Yii 2.0, et vous devez utiliser des classes de requête personnalisée et des méthodes de requêtes pour remplir le même objectif. +> Info : dans Yii 1.1, il existe un concept appelé *scope*. +> Scope n'est plus pris en charge directement par Yii 2.0, et vous devez utiliser des classes de requête personnalisées et des méthodes de requêtes pour remplir le même objectif. ## Sélection de champs supplémentaires Quand un enregistrement actif est rempli avec les résultats d'une requête, ses attributs sont remplis par les valeurs des colonnes correspondantes du jeu de données reçu. -Il vous est possible d'aller chercher des colonnes ou des valeurs additionnelles à partir d'une requête et des les stocker dans l'enregistrement actif. Par exemple, supposons que nous ayons une table nommée `room`, qui contient des informations sur les chambres (rooms) disponibles dans l'hôtel. Chacune des chambres stocke des informations sur ses dimensions géométriques en utilisant des champs `length` (longueur), `width` (largeur) , `height` (hauteur). Imaginons que vous ayez besoin de retrouver une liste des chambres disponibles en les classant par volume décroissant. Vous ne pouvez pas calculer le volume en PHP parce que vous avez besoin de trier les enregistrements par cette valeur, mais vous voulez peut-être aussi que `volume` soit affiché dans la liste. Pour atteindre ce but, vous devez déclarer un champ supplémentaire dans la classe d'enregistrement actif `Room` qui contiendra la valeur de `volume` : + +Il vous est possible d'aller chercher des colonnes ou des valeurs additionnelles à partir d'une requête et des les stocker dans l'enregistrement actif. +Par exemple, supposons que nous ayons une table nommée `room`, qui contient des informations sur les chambres (rooms) disponibles dans l'hôtel. +Chacune des chambres stocke des informations sur ses dimensions géométriques en utilisant des champs `length` (longueur), `width` (largeur) , `height` (hauteur). +Imaginons que vous ayez besoin de retrouver une liste des chambres disponibles en les classant par volume décroissant. +Vous ne pouvez pas calculer le volume en PHP parce que vous avez besoin de trier les enregistrements par cette valeur, mais vous voulez peut-être aussi que `volume` soit affiché dans la liste. +Pour atteindre ce but, vous devez déclarer un champ supplémentaire dans la classe d'enregistrement actif `Room` qui contiendra la valeur de `volume` : ```php @@ -1185,7 +1596,9 @@ foreach ($rooms as $room) { } ``` -La possibilité de sélectionner des champs supplémentaires peut être exceptionnellement utile pour l'agrégation de requêtes. Supposons que vous ayez besoin d'afficher une liste des clients avec le nombre total de commandes qu'ils ont passées. Tout d'abord, vous devez déclarer une classe `Customer` avec une relation `orders` et un champ supplémentaire pour le stockage du nombre de commandes : +La possibilité de sélectionner des champs supplémentaires peut être exceptionnellement utile pour l'agrégation de requêtes. +Supposons que vous ayez besoin d'afficher une liste des clients avec le nombre total de commandes qu'ils ont passées. +Tout d'abord, vous devez déclarer une classe `Customer` avec une relation `orders` et un champ supplémentaire pour le stockage du nombre de commandes : ```php class Customer extends \yii\db\ActiveRecord @@ -1214,7 +1627,9 @@ $customers = Customer::find() ->all(); ``` -Un inconvénient de l'utilisation de cette méthode est que si l'information n'est pas chargée dans la requête SQL, elle doit être calculée séparément, ce qui signifie aussi que l'enregistrement nouvellement sauvegardé ne contient les informations d'aucun champ supplémentaire : +Un inconvénient de l'utilisation de cette méthode est que si l'information n'est pas chargée dans la requête SQL, elle doit être calculée séparément. +Par conséquent, si vous avez trouvé un enregistrement particulier via une requête régulière sans instruction de sélection supplémentaire, il ne pourra retourner la valeur réelle du champ supplémentaire. +La même chose se produit pour l'enregistrement nouvellement sauvegardé. ```php $room = new Room(); @@ -1227,6 +1642,7 @@ $room->volume; // cette valeur est `null` puisqu'elle n'a pas encore été décl En utilisant les méthodes magiques [[yii\db\BaseActiveRecord::__get()|__get()]] et [[yii\db\BaseActiveRecord::__set()|__set()]] nous pouvons émuler le comportement d'une propriété : + ```php class Room extends \yii\db\ActiveRecord { @@ -1256,9 +1672,10 @@ class Room extends \yii\db\ActiveRecord } ``` -Lorsque la requête *select* ne fournit pas le volume, le modèle est pas capable de le calculer automatiquement en utilisant les attributs du modèle. +Lorsque la requête *select* ne fournit pas le volume, le modèle est capable de le calculer automatiquement en utilisant les attributs du modèle. + -De façon similaire, il peut être utilisé sur des champs supplémentaires en fonction des données relationnelles : +Vous pouvez aussi bien calculer les champs agrégés en utilisant les relations définies : ```php class Customer extends \yii\db\ActiveRecord @@ -1273,11 +1690,11 @@ class Customer extends \yii\db\ActiveRecord public function getOrdersCount() { if ($this->isNewRecord) { - return null; // this avoid calling a query searching for null primary keys + return null; // cela évite d'appeler une requête pour chercher une clé primaire nulle } if ($this->_ordersCount === null) { - $this->setOrdersCount(count($this->orders)); + $this->setOrdersCount($this->getOrders()->count()); // calcule l'aggrégation à la demande à partir de la relation } return $this->_ordersCount; @@ -1292,3 +1709,53 @@ class Customer extends \yii\db\ActiveRecord } ``` +Avec ce code, dans le cas où 'ordersCount' est présent dans l'instruction 'select' - `Customer::ordersCount` est peuplé +par les résultats de la requête, autrement il est calculé à la demande en utilisant la relation `Customer::orders`. + +Cette approche peut aussi bien être utilisée pour la création de raccourcis pour certaines données relationnelles, en particulier pour l'aggrégation. +Par exemple : + +```php +class Customer extends \yii\db\ActiveRecord +{ + /** + * Definit une propriété en lecture seule pour les données agrégées. + */ + public function getOrdersCount() + { + if ($this->isNewRecord) { + return null; // ceci évite l'appel d'une requête pour cherche une clé primaire nulle + } + + return empty($this->ordersAggregation) ? 0 : $this->ordersAggregation[0]['counted']; + } + + /** + * Déclere une relation 'orders' normale. + */ + public function getOrders() + { + return $this->hasMany(Order::className(), ['customer_id' => 'id']); + } + + /** + * Déclare une nouvelle relation basée sur 'orders', qui fournit l'agrégation. + */ + public function getOrdersAggregation() + { + return $this->getOrders() + ->select(['customer_id', 'counted' => 'count(*)']) + ->groupBy('customer_id') + ->asArray(true); + } + + // ... +} + +foreach (Customer::find()->with('ordersAggregation')->all() as $customer) { + echo $customer->ordersCount; // fournit les données agrégées à partir de la relation sans requête supplémentaire grâce au chargement précoce. +} + +$customer = Customer::findOne($pk); +$customer->ordersCount; // fournit les données agrégées à partir de la relation paresseuse chargée + diff --git a/docs/guide-fr/db-dao.md b/docs/guide-fr/db-dao.md index af899f1cd3b..9fc1887e3ae 100644 --- a/docs/guide-fr/db-dao.md +++ b/docs/guide-fr/db-dao.md @@ -1,19 +1,26 @@ Objets d'accès aux bases de données =================================== -Construits au dessus des [objets de bases de données PHP (PDO – PHP Data Objects)](http://www.php.net/manual/en/book.pdo.php), les objets d'accès aux bases de données de Yii (DAO – Database Access Objects) fournissent une API orientée objets pour accéder à des bases de données relationnelles. C'est la fondation pour d'autres méthodes d'accès aux bases de données plus avancées qui incluent le [constructeur de requêtes (*query builder*)](db-query-builder.md) et l'[enregistrement actif (*active record*)](db-active-record.md). +Construits au-dessus des [objets de bases de données PHP (PDO – PHP Data Objects)](http://www.php.net/manual/en/book.pdo.php), les objets d'accès aux bases de données de Yii (DAO – Database Access Objects) fournissent une API orientée objets pour accéder à des bases de données relationnelles. C'est la fondation pour d'autres méthodes d'accès aux bases de données plus avancées qui incluent le [constructeur de requêtes (*query builder*)](db-query-builder.md) et l'[enregistrement actif (*active record*)](db-active-record.md). Lorsque vous utilisez les objets d'accès aux bases de données de Yii, vous manipulez des requêtes SQL et des tableaux PHP. En conséquence, cela reste le moyen le plus efficace pour accéder aux bases de données. Néanmoins, étant donné que la syntaxe du langage SQL varie selon le type de base de données, l'utilisation des objets d'accès aux bases de données de Yii signifie également que vous avez à faire un travail supplémentaire pour créer une application indifférente au type de base de données. -Les objets d'accès aux bases de données de Yii prennent en charge les bases de données suivantes sans installation supplémentaire : +Dans Yii 2.0, les objets d'accès aux bases de données prennent en charge les bases de données suivantes sans configuration supplémentaire : - [MySQL](http://www.mysql.com/) - [MariaDB](https://mariadb.com/) - [SQLite](http://sqlite.org/) -- [PostgreSQL](http://www.postgresql.org/): version 8.4 or higher. -- [CUBRID](http://www.cubrid.org/): version 9.3 or higher. +- [PostgreSQL](http://www.postgresql.org/): version 8.4 ou plus récente. +- [CUBRID](http://www.cubrid.org/): version 9.3 ou plus récente. - [Oracle](http://www.oracle.com/us/products/database/overview/index.html) -- [MSSQL](https://www.microsoft.com/en-us/sqlserver/default.aspx): version 2008 or higher. +- [MSSQL](https://www.microsoft.com/en-us/sqlserver/default.aspx): version 2008 ou plus récente. + +> Info: depuis Yii 2.1, la prise en charge des objets d'accès aux bases de données pour CUBRID, Oracle et MSSQL n'est plus fournie en tant que composants du noyau. Cette prise en charge nécessite l'installation d'[extensions](structure-extensions.md) séparées. +Parmi les [extensions officielles](https://www.yiiframework.com/extensions/official), on trouve [yiisoft/yii2-oracle](https://www.yiiframework.com/extension/yiisoft/yii2-oracle) et + [yiisoft/yii2-mssql](https://www.yiiframework.com/extension/yiisoft/yii2-mssql). + +> Note: la nouvelle version de pdo_oci pour PHP 7 n'existe pour le moment que sous forme de code source. Suivez les [instructions de la communauté](https://github.com/yiisoft/yii2/issues/10975#issuecomment-248479268) + pour la compiler ou utilisez [la couche d'émulation de PDO](https://github.com/taq/pdooci). ## Création de connexions à une base de données @@ -52,7 +59,7 @@ Vous pouvez ensuite accéder à la base de données via l'expression `Yii::$app- > Tip: vous pouvez configurer plusieurs composants d'application « base de données » si votre application a besoin d'accéder à plusieurs bases de données. -Lorsque vous conifigurez une connexion à une base de données, vous devez toujours spécifier le nom de sa source de données (DSN – Data Source Name) via la propriété [[yii\db\Connection::dsn|dsn]]. Les formats des noms de source de données varient selon le type de base de données. Reportez-vous au [manuel de PHP](http://www.php.net/manual/en/function.PDO-construct.php) pour plus de détails. Ci-dessous, nous donnons quelques exemples : +Lorsque vous configurez une connexion à une base de données, vous devez toujours spécifier le nom de sa source de données (DSN – Data Source Name) via la propriété [[yii\db\Connection::dsn|dsn]]. Les formats des noms de source de données varient selon le type de base de données. Reportez-vous au [manuel de PHP](http://www.php.net/manual/en/function.PDO-construct.php) pour plus de détails. Ci-dessous, nous donnons quelques exemples : * MySQL, MariaDB: `mysql:host=localhost;dbname=mydatabase` * SQLite: `sqlite:/path/to/database/file` @@ -183,6 +190,10 @@ $post2 = $command->queryOne(); Notez que vous devez lier la valeur à remplacer à la variable `$id` avant l'exécution, et ensuite changer la valeur de cette variable avant chacune des exécutions subséquentes (cela est souvent réalisé dans une boucle). L'exécution de requêtes de cette façon peut être largement plus efficace que d'exécuter une nouvelle requête pour chacune des valeurs du paramètre). +> Info: la liaison de paramètres n'est utilisée qu'en des endroits où les valeurs doivent être insérées dans des chaînes de caractères qui contiennent du langage SQL. +> Dans de nombreux endroits dans des couches plus abstraites comme le [query builder](db-query-builder.md) (constructeur de requêtes) et [active record](db-active-record.md) (enregistrement actif) +> vous spécifiez souvent un tableau de valeurs qui est transformé en SQL. À ces endroits, la liaison de paramètres est assurée par Yii en interne. Il n'est donc pas nécessaire de spécifier ces paramètres manuellement. + ### Exécution de requête sans sélection @@ -215,19 +226,32 @@ Vous pouvez aussi appeler [[yii\db\Command::batchInsert()|batchInsert()]] pour i ```php // noms de table, noms de colonne, valeurs de colonne -Yii::$app->db->createCommand()->batchInsert('user', ['name', 'age'], [ +Yii::$app->db->createCommand()->batchinsère('user', ['name', 'age'], [ ['Tom', 30], ['Jane', 20], ['Linda', 25], ])->execute(); ``` +Une autre méthode utile est [[yii\db\Command::upsert()|upsert()]]. Upsert est une opération atomique qui insère des lignes dans une table de base de données si elles n'existent pas déjà (répondant à une contrainte unique), ou les mets à jour si elles existent : + +```php +Yii::$app->db->createCommand()->upsert('pages', [ + 'name' => 'Front page', + 'url' => 'http://example.com/', // url is unique + 'visits' => 0, +], [ + 'visits' => new \yii\db\Expression('visits + 1'), +], $params)->execute(); +``` + +Le code ci-dessus, soit insère un enregistrement pour une nouvelle page, soit incrémente sont compteur de visite automatiquement. Notez que les méthodes mentionnées ci-dessus ne font que créer les requêtes, vous devez toujours appeler [[yii\db\Command::execute()|execute()]] pour les exécuter réellement. ## Entourage de noms de table et de colonne par des marque de citation -Lorsque l'on écrit du code indifférent au type de base de données, entourer correctement les noms table et de colonne avec des marques de citation et souvent un casse-tête parce que les différentes base de données utilisent des règles de marquage de citation différentes. Pour vous affranchir de cette difficulté, vous pouvez utiliser la syntaxe de citation introduite par Yii : +Lorsque l'on écrit du code indifférent au type de base de données, entourer correctement les noms table et de colonne avec des marques de citation (p. ex. guillemets ou simple apostrophe) et souvent un casse-tête parce que les différentes base de données utilisent des règles de marquage de citation différentes. Pour vous affranchir de cette difficulté, vous pouvez utiliser la syntaxe de citation introduite par Yii : * `[[column name]]`: entourez un nom de colonne qui doit recevoir les marques de citation par des doubles crochets ; * `{{table name}}`: entourez un nom de table qui doit recevoir les marques de citation par des doubles accolades ; @@ -288,24 +312,26 @@ Le code précédent est équivalent à celui qui suit, et qui vous donne plus de ```php $db = Yii::$app->db; $transaction = $db->beginTransaction(); - try { $db->createCommand($sql1)->execute(); $db->createCommand($sql2)->execute(); - // ... exécution des autres instruction SQL ... + // ... exécutions des autres instructions SQL ... $transaction->commit(); - } catch(\Exception $e) { - $transaction->rollBack(); - + throw $e; +} catch(\Throwable $e) { + $transaction->rollBack(); throw $e; } ``` En appelant la méthode [[yii\db\Connection::beginTransaction()|beginTransaction()]], une nouvelle transaction est démarrée. La transaction est représentée sous forme d'objet [[yii\db\Transaction]] stocké dans la variable `$transaction`. Ensuite, les requêtes à exécuter sont placées dans un bloc `try...catch...`. Si toutes les requêtes réussissent, la méthode [[yii\db\Transaction::commit()|commit()]] est appelée pour entériner la transaction. Autrement, si une exception a été levée et capturée, la méthode [[yii\db\Transaction::rollBack()|rollBack()]] est appelée pour défaire les changements faits par les requêtes de la transaction antérieures à celle qui a échoué. `throw $e` est alors à nouveau exécutée comme si l'exception n'avait jamais été capturée, ce qui permet au processus normal de gestion des erreurs de s'en occuper. +> Note: dans le code précédent nous avons deux blocs « catch » pour compatibilité +> avec PHP 5.x et PHP 7.x. `\Exception` met en œuvre l'[interface `\Throwable`](http://php.net/manual/en/class.throwable.php) +> depuis PHP 7.0, ainsi vous pouvez sauter la partie avec `\Exception` si votre application utilise seulement PHP 7.0 et plus récent. ### Spécification de niveaux d'isolation @@ -325,14 +351,14 @@ $transaction = Yii::$app->db->beginTransaction($isolationLevel); Yii fournit quatre constantes pour les niveaux d'isolation les plus courants : -- [[\yii\db\Transaction::READ_UNCOMMITTED]] – le niveau le plus faible, des lectures sales (*dirty reads*) , des lectures non répétables) (*non-repeatable reads*) et des lectures phantomes (*phantoms*) peuvent se produire. +- [[\yii\db\Transaction::READ_UNCOMMITTED]] – le niveau le plus faible, des lectures sales (*dirty reads*) , des lectures non répétables) (*non-repeatable reads*) et des lectures fantômes (*phantoms*) peuvent se produire. - [[\yii\db\Transaction::READ_COMMITTED]] – évite les lectures sales. - [[\yii\db\Transaction::REPEATABLE_READ]] – évite les lectures sales et les lectures non répétables. - [[\yii\db\Transaction::SERIALIZABLE]] – le niveau le plus élevé, évite tous les problèmes évoqués ci-dessus. -En plus de l'utilisation des constantes présentées ci-dessus pour spécifier un niveau d'isolation, vous pouvez également utiliser des chaînes de caractères avec une syntaxe valide prise en charges par le système de gestion de base de données que vous utilisez. Par exemple, dans PostgreSQL, vous pouvez utiliser `SERIALIZABLE READ ONLY DEFERRABLE`. +En plus de l'utilisation des constantes présentées ci-dessus pour spécifier un niveau d'isolation, vous pouvez également utiliser des chaînes de caractères avec une syntaxe valide prise en charges par le système de gestion de base de données que vous utilisez. Par exemple, dans PostgreSQL, vous pouvez utiliser `"SERIALIZABLE READ ONLY DEFERRABLE"`. Notez que quelques systèmes de gestion de base de données autorisent la définition des niveaux d'isolation uniquement au niveau de la connexion tout entière. Toutes les transactions subséquentes auront donc le même niveau d'isolation même si vous n'en spécifiez aucun. En utilisant cette fonctionnalité, vous avez peut-être besoin de spécifier le niveau d'isolation de manière explicite pour éviter les conflits de définition. Au moment d'écrire ces lignes, seules MSSQL et SQLite sont affectées par cette limitation. @@ -358,7 +384,6 @@ Yii::$app->db->transaction(function ($db) { ``` Ou en alternative, - ```php $db = Yii::$app->db; $outerTransaction = $db->beginTransaction(); @@ -372,12 +397,18 @@ try { } catch (\Exception $e) { $innerTransaction->rollBack(); throw $e; + } catch (\Throwable $e) { + $innerTransaction->rollBack(); + throw $e; } $outerTransaction->commit(); } catch (\Exception $e) { $outerTransaction->rollBack(); throw $e; +} catch (\Throwable $e) { + $outerTransaction->rollBack(); + throw $e; } ``` diff --git a/docs/guide-fr/db-migrations.md b/docs/guide-fr/db-migrations.md index 6498cdfeff0..51cf22d0af2 100644 --- a/docs/guide-fr/db-migrations.md +++ b/docs/guide-fr/db-migrations.md @@ -26,8 +26,13 @@ Yii fournit un jeu de commandes de migration en ligne de commande qui vous perme Tous ces outils sont accessibles via la commande `yii migrate`. Dans cette section nous décrivons en détails comment accomplir des tâches variées en utilisant ces outils. Vous pouvez aussi obtenir les conseils d'utilisation de chacun des outils via la commande d'aide `yii help migrate`. -> Tip: les migrations peuvent non seulement affecter le schéma de base de données mais aussi ajuster les données existantes pour s'adapter au nouveau schéma, créer la hiérarchie RBAC (Role Based Acces Control - Contrôle d'accès basé sur les rôles), ou vider le cache. +> Astuce : les migrations peuvent non seulement affecter le schéma de base de données mais aussi ajuster les données existantes pour s'adapter au nouveau schéma, créer la hiérarchie RBAC (Role Based Acces Control - Contrôle d'accès basé sur les rôles), ou vider le cache. +> Note : lors de la manipulation de données utilisant une migration, vous pouvez trouver qu'utiliser vos classes [Active Record](db-active-record.md) +> pour cela peut s'avérer utile parce qu'une partie de la logique y est déjà mise en œuvre. Soyez cependant conscient que, contrairement +> au code écrit dans les migrations, dont la nature est de rester constant à jamais, la logique d'application est sujette à modification. +> C'est pourquoi, lorsque vous utilisez des classes ActiveRecord dans le code d'une migration, des modifications de la logique de l'ActiveRecord peuvent accidentellement casser +> des migrations existantes. Pour cette raison, le code des migrations devrait être conservé indépendant d'autres logiques d'application telles que celles des classes ActiveRecord. ## Création de migrations @@ -81,7 +86,7 @@ class m150101_185401_create_news_table extends Migration Chaque migration de base de données est définie sous forme de classe PHP étendant la classe [[yii\db\Migration]]. Le nom de la classe de migration est généré automatiquement dans le format `m_`, dans lequel : -* `` fait référence à l'horodatage UTC auquel la commande de création de la migration a été exécutée. +* `` fait référence à l'horodate UTC à laquelle la commande de création de la migration a été exécutée. * `` est le même que la valeur que vous donnez à l'argument `name` dans la commande. Dans la classe de migration, vous devez écrire du code dans la méthode `up()` qui effectue les modifications dans la structure de la base de données. Vous désirez peut-être écrire du code dans la méthode `down()` pour défaire les changements apportés par `up()`. La méthode `up()` est invoquée lorsque vous mettez à jour la base de données avec la migration, tandis que la méthode `down()` est invoquée lorsque vous ramenez la base de données à l'état antérieur. Le code qui suit montre comment mettre en œuvre la classe de migration pour créer une table `news` : @@ -116,7 +121,7 @@ La classe de migration de base [[yii\db\Migration]] expose une connexion à une Plutôt que d'utiliser des types physiques, lors de la création d'une table ou d'une colonne, vous devez utiliser des *types abstraits* afin que vos migrations soient indépendantes d'un système de gestion de base de données en particulier. La classe [[yii\db\Schema]] définit une jeu de constantes pour représenter les types abstraits pris en charge. Ces constantes sont nommées dans le format `TYPE_`. Par exemple, `TYPE_PK` fait référence au type clé primaire à auto-incrémentation ; `TYPE_STRING` fait référence au type chaîne de caractères. Lorsqu'une migration est appliquée à une base de données particulière, le type abstrait est converti dans le type physique correspondant. Dans le cas de MySQL, `TYPE_PK` est transformé en `int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY`, tandis que `TYPE_STRING` est transformé en `varchar(255)`. -Vous pouvez ajouter des contraintes additionnelles lors de l'utilisation des types abstraits. Dans l'exemple ci-dessus,` NOT NULL` est ajouté à `Schema::TYPE_STRING` pour spécifier que la colonne ne peut être *null* (nulle). +Vous pouvez ajouter des contraintes additionnelles lors de l'utilisation des types abstraits. Dans l'exemple ci-dessus,` NOT NULL` est ajouté à `Schema::TYPE_STRING` pour spécifier que la colonne ne peut être `null` (nulle). > Info: la mise en correspondance entre les types abstraits et les types physiques est spécifiée par la propriété [[yii\db\QueryBuilder::$typeMap|$typeMap]] dans chacune des classes `QueryBuilder` concrètes. @@ -377,6 +382,13 @@ Le mot clé `foreignKey` accepte un paramètre entre parenthèses qui est le nom Dans l'exemple ci-dessus `author_id:integer:notNull:foreignKey(user)` génère une colonne nommée `author_id` avec une clé étrangère pointant sur la table `user`, tandis que `category_id:integer:defaultValue(1):foreignKey` génère une colonne `category_id` avec une clé étrangère pointant sur la table `category`. +Depuis la version 2.0.11, le mot clé `foreignKey` accepte un second paramètre, séparé par une espace. +Il accepte le nom de la colonne en relation pour la clé étrangère générée. +Si aucun second paramètre n'est passé, le nom de la colonne est retrouvé dans le schéma de table. +Si aucun schéma n'existe, la clé primaire n'est pas définie ou est composite, le nom par défaut `id` est utilisé. + + + ### Suppression de tables ```php @@ -430,6 +442,11 @@ class m150811_220037_add_position_column_to_post_table extends Migration } } ``` +Vous pouvez spécifier de multiples colonnes comme suit : + +``` +yii migrate/create add_xxx_column_yyy_column_to_zzz_table --fields="xxx:integer,yyy:text" +``` ### Supprimer une colonne @@ -557,6 +574,9 @@ class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migra } ``` +Depuis la version 2.0.1, les noms de colonne des clés étrangères pour les tables de jonction sont recherchées dans le schéma de table. +Dans le cas où la table n'est pas définie dans le schéma, ou quand la clé primaire n'est pas définie ou est composite, le nom par défaut `id` est utilisé. + ### Migrations transactionnelles En effectuant des migration de base de données complexes, il est important de garantir que chacune des migrations soit réussisse, soit échoue dans son ensemble, de manière à ce que la base de données reste cohérente et intègre. Pour atteindre ce but, il est recommandé que vous englobiez les opérations de base de données de chacune des migrations dans une [transaction](db-dao.md#performing-transactions). @@ -631,10 +651,16 @@ Ci-dessous, nous présentons la liste de toutes les méthodes d'accès aux bases * [[yii\db\Migration::addCommentOnTable()|addCommentOnTable()]]: ajoute un commentaire à une table * [[yii\db\Migration::dropCommentFromTable()|dropCommentFromTable()]]: supprime un commentaire d'une table -> Info: [[yii\db\Migration]] ne fournit pas une méthode de requête de base de données. C'est parce que, normalement, vous n'avez pas besoin d'afficher de messages supplémentaire à propos de l'extraction de données dans une base de données. C'est aussi parce que vous pouvez utiliser le puissant [constructeur de requêtes](db-query-builder.md) pour construire et exécuter des requêtes complexes. - -> Note: lors de la manipulation des données en utilisant une migration, vous pouvez trouver qu'utiliser vos classes d'[enregistrement actif](db-active-record.md) pour cela peut être utile parce qu'une partie de la logique y est déjà mise en œuvre. Soyez conscient cependant que, par contraste avec le code écrit dans les migrations, dont la nature est de rester constant à jamais, la logique d'application est sujette à des changements. Ainsi, en utilisant un enregistrement actif dans du code de migration, les changements apportés à la logique dans la couche enregistrement actif peuvent casser accidentellement des migrations existantes. Pour cette raison, le code doit être gardé indépendant de toute autre logique d'application telle que les classes d'enregistrement actif. - +> Info: [[yii\db\Migration]] +> ne fournit pas une méthode de requête de base de données. C'est parce que, normalement, vous n'avez pas besoin d'afficher de messages supplémentaire à propos de l'extraction de données dans une base de données. C'est aussi parce que vous pouvez utiliser le puissant [constructeur de requêtes](db-query-builder.md) pour construire et exécuter des requêtes complexes. +> L'utilisation du constructeur de requêtes dans une migration ressemble à ceci : +> +> ```php +> // update status field for all users +> foreach((new Query)->from('users')->each() as $user) { +> $this->update('users', ['status' => 1], ['id' => $user['id']]); +> } +> ``` ## Application des migrations @@ -644,13 +670,13 @@ Pour mettre une base de données à jour à sa dernière structure, vous devez a yii migrate ``` -Cette commande liste toutes les migrations qui n'ont pas encore été appliquées. Si vous confirmez que vous voulez appliquer ces migrations, cela provoque l'exécution des méthodes `up()` ou `safeUp()` de chacune des nouvelles migrations, l'une après l'autre, dans l'ordre de leur horodatage. Si l'une de ces migrations échoue, la commande se termine sans appliquer les migrations qui restent. +Cette commande liste toutes les migrations qui n'ont pas encore été appliquées. Si vous confirmez que vous voulez appliquer ces migrations, cela provoque l'exécution des méthodes `up()` ou `safeUp()` de chacune des nouvelles migrations, l'une après l'autre, dans l'ordre de leur horodate. Si l'une de ces migrations échoue, la commande se termine sans appliquer les migrations qui restent. -> Tip: dans le cas où votre serveur ne vous offre pas de ligne de commande, vous pouvez essayer [Web shell](https://github.com/samdark/yii2-webshell). +> Astuce : dans le cas où votre serveur ne vous offre pas de ligne de commande, vous pouvez essayer [Web shell](https://github.com/samdark/yii2-webshell). Pour chaque migration qui n'a pas été appliqué avec succès, la commande insère une ligne dans une table de base de données nommée `migration` pour enregistrer les applications réussies de la migration. Cela permet à l'outil de migration d'identifier les migrations qui ont été appliquées et celles qui ne l'ont pas été. -> Info: l'outil de migration crée automatiquement la table de `migration` dans la base de données spécifiée par l'option [[yii\console\controllers\MigrateController::db|db]] de la commande. Par défaut, la base de données est spécifiée dans le [composant d'application](structure-application-components.md) `db`. +> Info: l'outil de migration crée automatiquement la table `migration` dans la base de données spécifiée par l'option [[yii\console\controllers\MigrateController::db|db]] de la commande. Par défaut, la base de données est spécifiée dans le [composant d'application](structure-application-components.md) `db`. Parfois, vous désirez peut-être appliquer une ou quelques migrations plutôt que toutes les migrations disponibles. Vous pouvez le faire en spécifiant le nombre de migrations que vous voulez appliquer en exécutant la commande. Par exemple, la commande suivante essaye d'appliquer les trois prochaines migrations disponibles : @@ -680,6 +706,8 @@ Pour défaire une ou plusieurs migrations que ont été appliquées auparavant, yii migrate/down # défait la migration appliquée le plus récemment yii migrate/down 3 # défait les 3 migrations appliquées le plus récemment +``` + > Note: toutes les migrations ne sont PAS réversibles. Essayer de défaire de telles migrations provoque une erreur et arrête tout le processus de retour à l'état initial. @@ -690,10 +718,18 @@ Refaire (ré-appliquer) des migrations signifie d'abord défaire les migrations ``` yii migrate/redo # refait la dernière migration appliquée yii migrate/redo 3 # refait les 3 dernière migrations appliquées + ``` > Note: si une migration n'est pas réversible, vous ne serez pas en mesure de la refaire. +## Rafraîchir des Migrations + +Deepuis la version 2.0.13, vous pouvez supprimer toutes les tables et clés étrangères de la base de données et ré-appliquer toutes les migrations depuis le début. +``` +yii migrate/fresh # Tronçonne la base de données et applique toutes les migrations depuis le début + +``` ## Lister des migrations @@ -735,11 +771,11 @@ La commande de migration possède quelques options en ligne de commande qui peuv * `migrationPath`: string (valeur par défaut `@app/migrations`), spécifie le dossier qui stocke tous les fichiers de classe de migration. Cela peut être spécifié soit comme un chemin de dossier, soit comme un [alias](concept-aliases.md) de chemin. Notez que le dossier doit exister sinon la commande déclenche une erreur. -* `migrationTable`: string (valeur par défaut `migration`), spécifie le nom de la table de base de données pour stocker l'historique de migration. La table es créée automatiquement par la commande si elle n'existe pas encore. Vous pouvez aussi la créer à la main en utilisant la structure `version varchar(255) primary key, apply_time integer`. +* `migrationTable`: string (valeur par défaut `migration`), spécifie le nom de la table de base de données pour stocker l'historique de migration. La table est créée automatiquement par la commande si elle n'existe pas encore. Vous pouvez aussi la créer à la main en utilisant la structure `version varchar(255) primary key, apply_time integer`. * `db`: string (valeur par défaut `db`), spécifie l'identifiant du [composant d'application](structure-application-components.md) base de données. Il représente la base de données à laquelle les migrations sont appliquées avec cette commande. -* `templateFile`: string (valeur par défaut `@yii/views/migration.php`), spécifie le chemin vers le fichier modèle qui est utilisé pour générer le squelette des fichiers de classe de migration. Cela peut être spécifié soit sous forme de chemin de fichier, soit sous forme d'[alias](concept-aliases.md).de chemin. Le fichier modèle est un script PHP dans lequel vous pouvez utiliser une variable prédéfinie nommée `$className` pour obtenir le nom de la classe de migration. +* `templateFile`: string (valeur par défaut `@yii/views/migration.php`), spécifie le chemin vers le fichier modèle qui est utilisé pour générer le squelette des fichiers de classe de migration. Cela peut être spécifié soit sous forme de chemin de fichier, soit sous forme d'[alias](concept-aliases.md) de chemin. Le fichier modèle est un script PHP dans lequel vous pouvez utiliser une variable prédéfinie nommée `$className` pour obtenir le nom de la classe de migration. * `generatorTemplateFiles`: array (valeur par défaut `[ 'create_table' => '@yii/views/createTableMigration.php', @@ -749,14 +785,14 @@ La commande de migration possède quelques options en ligne de commande qui peuv 'create_junction' => '@yii/views/createTableMigration.php' ]`), spécifie les fichiers modèles pour générer le code de migration. Voir "[Génération des migrations](#generating-migrations)" pour plus de détails. -* `fields`: array (tableau) de chaîne de caractères de définition de colonnes utilisées pour créer le code de migration. Valeur par défaut `[]`. Le format de chacune des définitions est `COLUMN_NAME:COLUMN_TYPE:COLUMN_DECORATOR`. Par exemple, `--fields=name:string(12):notNull` produit une colonne chaîne de caractères de taille 12 qui n'est pas nulle. +* `fields`: array (tableau) de chaîne de caractères de définition de colonnes utilisées pour créer le code de migration. Valeur par défaut `[]`. Le format de chacune des définitions est `COLUMN_NAME:COLUMN_TYPE:COLUMN_DECORATOR`. Par exemple, `--fields=name:string(12):notNull` produit une colonne chaîne de caractères de taille 12 qui n'est pas `null` (nulle). L'exemple suivant montre comment vous pouvez utiliser ces options. Par exemple, si vous voulez appliquer des migrations à un module `forum` dont les fichiers de migration sont situés dans le dossier `migrations` du module, vous pouvez utiliser la commande suivante : ``` -# appliquer les migrations d'un module forum sans interactivité +# Appliquer les migrations d'un module forum sans interactivité yii migrate --migrationPath=@app/modules/forum/migrations --interactive=0 ``` @@ -778,7 +814,86 @@ return [ Avec la configuration ci-dessus, à chaque fois que vous exécutez la commande de migration, la table `backend_migration` est utilisée pour enregistrer l'historique de migration. Vous n'avez plus besoin de le spécifier via l'option en ligne de commande `migrationTable`. +### Migrations avec espaces de noms + +Depuis la version 2.0.10, vous pouvez utiliser les espaces de noms pour les classes de migration. Vous pouvez spécifier la liste des espaces de noms des migrations via +[[yii\console\controllers\MigrateController::migrationNamespaces|migrationNamespaces]]. L'utilisation des espaces de noms pour les classes de migration vous permet l'utilisation de plusieurs emplacement pour les sources des migrations. Par exemple : + +```php +return [ + 'controllerMap' => [ + 'migrate' => [ + 'class' => 'yii\console\controllers\MigrateController', + 'migrationPath' => null, // désactive les migration sans espace de noms si app\migrations est listé ci-dessous + 'migrationNamespaces' => [ + 'app\migrations', // Migration ordinaires pour l'ensemble de l'application + 'module\migrations', // Migrations pour le module de projet spécifique +                'some\extension\migrations', // Migrations pour l'extension spécifique + ], + ], + ], +]; +``` + +> Note : les migrations appliquées appartenant à des espaces de noms différent créent un historique de migration **unique**, p. ex. vous pouvez être incapable d'appliquer ou d'inverser des migrations d'un espace de noms particulier seulement. + +Lors des opérations sur les migrations avec espaces de noms : la création, l'inversion, etc. vous devez spécifier l'espace de nom complet avant le nom de la migration. +Notez que le caractère barre oblique inversée (`\`) est en général considéré comme un caractère spécial dans l'interprète de commandes, c'est pourquoi vous devez l'échapper correctement pour éviter des erreurs d'interprète de commandes ou des comportements incorrects. Par exemple : + +``` +yii migrate/create 'app\\migrations\\createUserTable' +``` + +> Note : les migrations spécifiées via [[yii\console\controllers\MigrateController::migrationPath|migrationPath]] +ne peuvent pas contenir un espace de noms, les migrations avec espaces de noms peuvent être appliquée via la propriété [[yii\console\controllers\MigrateController::migrationNamespaces]]. + +Depuis la version 2.0.12, la propriété [[yii\console\controllers\MigrateController::migrationPath|migrationPath]] +accepte également un tableau pour spécifier de multiples dossiers contenant des migrations sans espaces de noms. +Cela a été ajouté principalement pour être utilisé dans des projets existants qui utilisent des migrations provenant de différents emplacements. Ces migrations viennent principalement de +sources externes, comme les extensions à Yii développées par d'autres développeurs, +qui ne peuvent être facilement modifiées pour utiliser les espaces de noms lors du démarrage avec la nouvelle approche. + +### Migrations séparées + +Parfois, l'utilisation d'un historique unique de migration pour toutes les migrations du projet n'est pas souhaité. Par exemple : vous pouvez installer une extension 'blog', qui contient des fonctionnalités complètement séparées et contient ses propres migrations, qui ne devraient pas affecter celles dédiées aux fonctionnalités principales du projet. +Si vous voulez qui plusieurs migrations soient appliquées et complétement tracées séparément l'une de l'autre, vous pouvez configurer de multiples commandes de migration qui utilisent des espaces de noms différents et des tables d'historique de migration différentes : + + +```php +return [ + 'controllerMap' => [ + // Common migrations for the whole application + 'migrate-app' => [ + 'class' => 'yii\console\controllers\MigrateController', + 'migrationNamespaces' => ['app\migrations'], + 'migrationTable' => 'migration_app', + 'migrationPath' => null, + ], + // Migrations for the specific project's module + 'migrate-module' => [ + 'class' => 'yii\console\controllers\MigrateController', + 'migrationNamespaces' => ['module\migrations'], + 'migrationTable' => 'migration_module', + 'migrationPath' => null, + ], + // Migrations for the specific extension + 'migrate-rbac' => [ + 'class' => 'yii\console\controllers\MigrateController', + 'migrationPath' => '@yii/rbac/migrations', + 'migrationTable' => 'migration_rbac', + ], + ], +]; +``` + +Notez que pour synchroniser la base de données vous devez maintenant exécuter plusieurs commandes au lieu d'une seule : + +``` +yii migrate-app +yii migrate-module +yii migrate-rbac +``` ## Migration de multiples base de données Par défaut, les migrations sont appliquées à la même base de données spécifiée par le [composant d'application](structure-application-components.md) `db`. Si vous voulez que celles-ci soient appliquées à des bases de données différentes, vous pouvez spécifier l'option en ligne de commande `db` comme indiqué ci-dessous : @@ -810,7 +925,7 @@ La migration ci-dessus est appliquée à `db2`, même si vous spécifiez une aut Si vous avez de multiples migrations qui utilisent la même base de données, il est recommandé que vous créiez une classe de migration de base avec le code `init()` ci-dessus. Ensuite, chaque classe de migration peut étendre cette classe de base. -> Tip: en plus de définir la propriété [[yii\db\Migration::db|db]], vous pouvez aussi opérer sur différentes bases de données en créant de nouvelles connexions à ces bases de données dans vos classes de migration. Ensuite,vous utilisez les [méthodes des objets d'accès aux bases de données](db-dao.md) avec ces connexions pour manipuler différentes bases de données. +> Astuce : en plus de définir la propriété [[yii\db\Migration::db|db]], vous pouvez aussi opérer sur différentes bases de données en créant de nouvelles connexions à ces bases de données dans vos classes de migration. Ensuite,vous utilisez les [méthodes des objets d'accès aux bases de données](db-dao.md) avec ces connexions pour manipuler différentes bases de données. Une autre stratégie que vous pouvez adopter pour appliquer des migrations à de multiples bases de données est de tenir ces migrations de différentes bases de données dans des chemins différents. Ensuite vous pouvez appliquer les migrations à ces bases de données dans des commandes séparées comme ceci : diff --git a/docs/guide-fr/db-query-builder.md b/docs/guide-fr/db-query-builder.md index c9062fc1350..128f7e5598b 100644 --- a/docs/guide-fr/db-query-builder.md +++ b/docs/guide-fr/db-query-builder.md @@ -8,6 +8,8 @@ L'utilisation du constructeur de requêtes comprend ordinairement deux étapes  1. Construire un objet [[yii\db\Query]] pour représenter différentes parties (p. ex. `SELECT`, `FROM`) d'une instruction SQL. 2. Exécuter une méthode de requête (p. ex. `all()`) de [[yii\db\Query]] pour retrouver des données dans la base de données. + + Le code suivant montre une manière typique d'utiliser le constructeur de requêtes. ```php @@ -28,18 +30,28 @@ WHERE `last_name` = :last_name LIMIT 10 ``` -> Info: génélalement vous travaillez essentiellement avec [[yii\db\Query]] plutôt qu'avec [[yii\db\QueryBuilder]]. Le dernier est implicitement invoqué par le premier lorsque vous appelez une des méthodes de requête. [[yii\db\QueryBuilder]] est la classe en charge de la génération des instructions SQL dépendantes du système de gestion de base de données (p. ex. entourer les noms de table/colonne par des marques de citation différemment) à partir d'objets [[yii\db\Query]] indifférents au système de gestion de base de données. + +> Info: génélalement vous travaillez essentiellement avec [[yii\db\Query]] plutôt qu'avec [[yii\db\QueryBuilder]]. + Le dernier est implicitement invoqué par le premier lorsque vous appelez une des méthodes de requête. [[yii\db\QueryBuilder]] est la classe en charge de la génération des instructions SQL dépendantes du système de gestion de base de données (p. ex. entourer les noms de table/colonne par des marques de citation différemment) à partir d'objets [[yii\db\Query]] indifférents au système de gestion de base de données. + + ## Construction des requêtes -Pour construire un objet [[yii\db\Query]], vous appelez différentes méthodes de construction de requêtes pour spécifier différentes parties de la requête SQL. Les noms de ces méthodes ressemblent aux mots clés de SQL utilisés dans les parties correspondantes de l'instruction SQL. Par exemple, pour spécifier la partie `FROM` d'une requête SQL, vous appelez la méthode [[yii\db\Query::from()|from()]]. Toutes les méthodes de construction de requêtes retournent l'objet *query* lui-même, ce qui vous permet d'enchaîner plusieurs appels. +Pour construire un objet [[yii\db\Query]], vous appelez différentes méthodes de construction de requêtes pour spécifier différentes parties de la requête SQL. + Les noms de ces méthodes ressemblent aux mots clés de SQL utilisés dans les parties correspondantes de l'instruction SQL. +Par exemple, pour spécifier la partie `FROM` d'une requête SQL, vous appelez la méthode [[yii\db\Query::from()|from()]]. + Toutes les méthodes de construction de requêtes retournent l'objet *query* lui-même, ce qui vous permet d'enchaîner plusieurs appels. Dans ce qui suit, nous décrivons l'utilisation de chacune des méthodes de requête. + ### [[yii\db\Query::select()|select()]] -La méthode [[yii\db\Query::select()|select()]] spécifie le fragment `SELECT` d'une instruction SQL. Vous pouvez spécifier les colonnes à sélectionner soit sous forme de chaînes de caractères, soit sous forme de tableaux, comme ci-apès. Les noms de colonne sélectionnées sont automatiquement entourés des marques de citation lorsque l'instruction SQL est générée à partir de l'objet *query* (requête). +La méthode [[yii\db\Query::select()|select()]] spécifie le fragment `SELECT` d'une instruction SQL. Vous pouvez spécifier les colonnes à sélectionner soit sous forme de chaînes de caractères, soit sous forme de tableaux, comme ci-après. +Les noms des colonnes sélectionnées sont automatiquement entourés des marques de citation lorsque l'instruction SQL + est générée à partir de l'objet *query* (requête). ```php $query->select(['id', 'email']); @@ -49,7 +61,8 @@ $query->select(['id', 'email']); $query->select('id, email'); ``` -Les noms des colonnes sélectionnées peuvent inclure des préfixes de table et/ou de alias de colonne, comme vous le faites en écrivant une requête SQL brute. Par exemple : +Les noms des colonnes sélectionnées peuvent inclure des préfixes de table et/ou des alias de colonne, comme vous le faites en écrivant une requête SQL brute. +Par exemple : ```php $query->select(['user.id AS user_id', 'email']); @@ -59,23 +72,28 @@ $query->select(['user.id AS user_id', 'email']); $query->select('user.id AS user_id, email'); ``` -Si vous utilisez le format tableau pour spécifier les colonnes, vous pouvez aussi utiliser les clés du tableau pour spécifier les alias de colonne. Par exemple, le code ci-dessus peut être réécrit comme ceci : +Si vous utilisez le format tableau pour spécifier les colonnes, vous pouvez aussi utiliser les clés du tableau pour spécifier les alias de colonne. +Par exemple, le code ci-dessus peut être réécrit comme ceci : ```php $query->select(['user_id' => 'user.id', 'email']); ``` -Si vous n'appelez pas la méthode [[yii\db\Query::select()|select()]] en construisant une requête, `*` est sélectionné, ce qui signifie la sélection de *toutes* les colonnes. +Si vous n'appelez pas la méthode [[yii\db\Query::select()|select()]] en construisant une requête, `*` est sélectionné, +ce qui signifie la sélection de *toutes* les colonnes. -En plus des noms de colonne, vous pouvez aussi sélectionner des expression de base de données. Vous devez utiliser le format tableau en sélectionnant une expression de base de données qui contient des virgules pour éviter des entourages automatiques incorrects des noms par des marques de citation. Par exemple : +En plus des noms de colonne, vous pouvez aussi sélectionner des expression de base de données. Vous devez utiliser le format tableau en sélectionnant une expression de base de données qui contient des virgules pour éviter des entourages automatiques incorrects des noms par des marques de citation. +Par exemple : ```php $query->select(["CONCAT(first_name, ' ', last_name) AS full_name", 'email']); ``` -Comme en tout lieu où il est fait appel à du SQL brut, vous devez utiliser la [syntaxe des marques de citation indifférentes au système de gestion de base de données](db-dao.md#quoting-table-and-column-names) pour les noms de table et de colonne lorsque vous écrivez les expressions de base de données dans `select`. +Comme en tout lieu où il est fait appel à du SQL brut, vous devez utiliser la [syntaxe des marques de citation indifférentes au système de gestion de base de données](db-dao.md#quoting-table-and-column-names) pour les noms de table et +de colonne lorsque vous écrivez les expressions de base de données dans `select`. -Depuis la version 2.0.1, vous pouvez aussi sélectionner des sous-requêtes. Vous devez spécifier chacune des sous-requêtes en termes d'objet [[yii\db\Query]]. Par exemple : +Depuis la version 2.0.1, vous pouvez aussi sélectionner des sous-requêtes. Vous devez spécifier chacune des sous-requêtes en termes d'objet [[yii\db\Query]]. +Par exemple : ```php $subQuery = (new Query())->select('COUNT(*)')->from('user'); @@ -108,7 +126,8 @@ La méthode [[yii\db\Query::from()|from()]] spécifie le fragment `FROM`d'une in $query->from('user'); ``` -Vous pouvez spécifier les tables à sélectionner soit sous forme de chaînes de caractères, soit sous forme de tableaux. Les noms de table peuvent contenir des préfixes et/ou des alias de table. Par exemple : +Vous pouvez spécifier les tables à sélectionner soit sous forme de chaînes de caractères, soit sous forme de tableaux. Les noms de table peuvent contenir des préfixes et/ou des alias de table. +Par exemple : ```php $query->from(['public.user u', 'public.post p']); @@ -134,19 +153,23 @@ $subQuery = (new Query())->select('id')->from('user')->where('status=1'); $query->from(['u' => $subQuery]); ``` +#### Préfixes +Un [[yii\db\Connection::$tablePrefix|préfixe de table]] peut aussi être appliqué. Les instructions de mise en œuvre sont données à la section +["Entourage des noms de table et de colonne par des marques de citation" du guide sur les objets d'accès aux bases de données" ](guide-db-dao.html#quoting-table-and-column-names). ### [[yii\db\Query::where()|where()]] - -La méthode [[yii\db\Query::where()|where()]] spécifie le fragment `WHERE`d'une requête SQL. Vous pouvez utiliser un des trois formats suivants pour spécifier une condition `WHERE` : +La méthode [[yii\db\Query::where()|where()]] spécifie le fragment `WHERE`d'une requête SQL. Vous pouvez utiliser un des quatre formats suivants pour spécifier une condition `WHERE` : - format chaîne de caractères, p. ex. `'status=1'` - format haché, p. ex. `['status' => 1, 'type' => 2]` - format opérateur, p. ex. `['like', 'name', 'test']` +- format objet, p. ex. `new LikeCondition('name', 'LIKE', 'test')` #### Format chaîne de caractères -Le format chaîne de caractères est celui qui convient le mieux pour spécifier des conditions très simples ou si vous avez besoin d'utiliser les fonctions incorporées au système de gestion de base de données. Il fonctionne comme si vous écriviez une requête SQL brute. Par exemple : +Le format chaîne de caractères est celui qui convient le mieux pour spécifier des conditions très simples ou si vous avez besoin d'utiliser les fonctions incorporées au système de gestion de base de données. +Il fonctionne comme si vous écriviez une requête SQL brute. Par exemple : ```php $query->where('status=1'); @@ -155,16 +178,19 @@ $query->where('status=1'); $query->where('status=:status', [':status' => $status]); // SQL brute utilisant la fonction MySQL YEAR() sur un champ de date +$query->where('YEAR(somedate) = 2015'); ``` N'imbriquez PAS les variables directement dans la condition comme ce qui suit, spécialement si les valeurs des variables proviennent d'entrées utilisateur, parce que cela rendrait votre application SQL sujette aux attaques par injections SQL. + ```php // Dangereux! Ne faites PAS cela sauf si vous êtes tout à fait sûr que $status est un entier $query->where("status=$status"); ``` -Lorsque vous utilisez la liaison des paramètres, vous pouvez appeler [[yii\db\Query::params()|params()]] ou [[yii\db\Query::addParams()|addParams()]] pour spécifier les paramètres séparément. +Lorsque vous utilisez la `liaison des paramètres`, vous pouvez appeler [[yii\db\Query::params()|params()]] ou [[yii\db\Query::addParams()|addParams()]] pour spécifier les paramètres séparément. + ```php $query->where('status=:status') @@ -173,9 +199,12 @@ $query->where('status=:status') Comme dans tous les endroits ou il est fait appel à du SQL, vous pouvez utiliser la [syntaxe d'entourage par des marques de citation indifférente au système de gestion de base de données](db-dao.md#quoting-table-and-column-names) pour les noms de table et de colonne lorsque vous écrivez les conditions au format chaîne de caractères. + #### Format haché -Le format valeur de hachage convient le mieux pour spécifier de multiples sous-conditions `AND` concaténées, chacune étant une simple assertion d'égalité. Il se présente sous forme de tableau dont les clés sont les noms des colonnes et les valeurs les valeurs correspondantes que les valeurs des colonnes devraient avoir. Par exemple : +Le format valeur de hachage convient le mieux pour spécifier de multiples sous-conditions concaténées par `AND`, chacune étant une simple assertion d'égalité. +Il se présente sous forme de tableau dont les clés sont les noms des colonnes et les valeurs les valeurs correspondantes que les valeurs des colonnes devraient avoir. +Par exemple : ```php // ...WHERE (`status` = 10) AND (`type` IS NULL) AND (`id` IN (4, 8, 15)) @@ -197,12 +226,24 @@ $userQuery = (new Query())->select('id')->from('user'); $query->where(['id' => $userQuery]); ``` -En utilisant le format haché, Yii, en interne, utilise la liaison des paramètres de façon à ce que, contrairement au [format chaîne de caractères](#string-format), vous n'ayez pas à ajouter les paramètres à la main. +En utilisant le format haché, Yii, en interne, utilise la liaison des paramètres pour les valeurs de façon à ce que, contrairement au [format chaîne de caractères](#string-format), vous n'ayez pas à ajouter les paramètres à la main. +Cependant, notez que Yii ne procède pas à l'échappement des noms de colonne, c'est pourquoi si vous passez un nom de variable obtenu de l'utilisateur en tant que nom de colonne sans vérification, l'application devient vulnérable à l'injection SQL. +Afin de maintenir l'application sûre, soit n'utilisez pas de variables comme nom de colonne, soit filtrez les variables par une liste blanche. +Dans le cas où vous avez besoin d'obtenir un nom de colonne de l'utilisateur, lisez +l'article du guide [Filtrage des données](output-data-widgets.md#filtering-data). +Ainsi l'exemple de code suivant est vulnérable : +```php +// Vulnerable code: +$column = $request->get('column'); +$value = $request->get('value'); +$query->where([$column => $value]); +// $value est sûre, mais le nom de colonne n'est pas encodé! +``` #### Format opérateur -Le format opérateur vous permet de spécifier des conditions arbitraires par programmation. Il accepte les formats suivants : a +Le format opérateur vous permet de spécifier des conditions arbitraires par programmation. Il accepte les formats suivants : ```php [operator, operand1, operand2, ...] @@ -210,40 +251,127 @@ Le format opérateur vous permet de spécifier des conditions arbitraires par pr dans lequel chacun des opérandes peut être spécifié au format chaîne de caractères, au format haché ou au format opérateur de façon récursive, tandis que l'opérateur peut être un de ceux qui suivent : -- `and`: les opérandes doivent être concaténés en utilisant `AND`. Par exemple, `['and', 'id=1', 'id=2']` génère `id=1 AND id=2`. Si l'opérande est un tableau, il est converti en une chaîne de caractères en utilisant les règles décrites ici. Par exemple, `['and', 'type=1', ['or', 'id=1', 'id=2']]` génère `type=1 AND (id=1 OR id=2)`. La méthode ne procède à aucun entourage par des marques de citation, ni à aucun échappement. +- `and`: les opérandes doivent être concaténés en utilisant `AND`. Par exemple, `['and', 'id=1', 'id=2']` génère `id=1 AND id=2`. + Si un opérande est un tableau, il est converti en une chaîne de caractères en utilisant les règles décrites ici. + Par exemple, `['and', 'type=1', ['or', 'id=1', 'id=2']]` génère `type=1 AND (id=1 OR id=2)`. + La méthode ne procède à aucun entourage par des marques de citation, ni à aucun échappement. + + - `or`: similaire à l'opérateur `and` sauf que les opérandes sont concaténés en utilisant `OR`. +- `not`: ne réclame que l'opérande 1, qui est emballé dans `NOT()`. Par exemple, `['not', 'id=1']` génère `NOT (id=1)`. L'opérande 1 peut aussi être un tableau pour décrire des expressions multiples. Par exemple `['not', ['status' => 'draft', 'name' => 'example']]` génère `NOT ((status='draft') AND (name='example'))`. + - `between`: l'opérande 1 doit être le nom de la colonne, et les opérandes 2 et 3 doivent être les valeurs de départ et de fin de la plage dans laquelle la colonne doit être. Par exemple, `['between', 'id', 1, 10]` génère `id BETWEEN 1 AND 10`. + Dans le cas où vous avez besoin de construire une expression dans laquelle la valeur est entre deux colonnes (telle que `11 BETWEEN min_id AND max_id`), + vous devez utiliser [[yii\db\conditions\BetweenColumnsCondition|BetweenColumnsCondition]]. + Reportez-vous au chapitre [Conditions – Format d'objet](#object-format) pour en savoir plus sur la définition des conditions d'objet. + + -- `not between`: similaire à `between` sauf que `BETWEEN` est remplacé par `NOT BETWEEN` dans la condition générée. +- `not between`: similaire à `between` sauf que `BETWEEN` est remplacé par `NOT BETWEEN` + dans la condition générée. -- `in`: l'opérande 1 doit être une colonne ou une expression de base de données. L'opérande 2 peut être soit un tableau, soit un objet `Query`. Il génère une condition `IN`. Si l'opérande 2 est un tableau, il représente la plage des valeurs que la colonne ou l'expression de base de données peut prendre. Si l'opérande 2 est un objet `Query`, une sous-requête est générée et utilisée comme plage pour la colonne ou l'expression de base de données. Par exemple, `['in', 'id', [1, 2, 3]]` génère `id IN (1, 2, 3)`. La méthode assure correctement l'entourage des noms de colonnes par des marques de citation et l'échappement des valeurs de la plage. L'opérateur `in` prend aussi en charge les colonnes composites. Dans ce case, l'opérande 1 doit être un tableau des colonnes, tandis que l'opérateur 2 doit être un tableau de tableaux, ou un objet `Query` représentant la plage de colonnes. +- `in`: l'opérande 1 doit être une colonne ou une expression de base de données. +L'opérande 2 peut être soit un tableau, soit un objet `Query`. + Il génère une condition `IN`. Si l'opérande 2 est un tableau, il représente la plage des valeurs que la colonne ou l'expression de base de données peut prendre. + Si l'opérande 2 est un objet `Query`, une sous-requête est générée et utilisée comme plage pour la colonne ou l'expression de base de données. + Par exemple, `['in', 'id', [1, 2, 3]]` génère `id IN (1, 2, 3)`. + La méthode assure correctement l'entourage des noms de colonnes par des marques de citation et l'échappement des valeurs de la plage. + L'opérateur `in` prend aussi en charge les colonnes composites. + Dans ce cas, l'opérande 1 doit être un tableau des colonnes, tandis que l'opérateur 2 doit être un tableau de tableaux, ou un objet `Query` représentant la plage de colonnes. - `not in`: similaire à l'opérateur `in` sauf que `IN` est remplacé par `NOT IN` dans la condition générée. -- `like`: l'opérande 1 doit être une colonne ou une expression de base de données, tandis que l'opérande 2 doit être une chaîne de caractères ou un tableau représentant les valeurs que cette colonne ou cette expression de base de données peuvent être. Par exemple, `['like', 'name', 'tester']` génère `name LIKE '%tester%'`. Lorsque la plage de valeurs est donnée sous forme de tableau, de multiples prédicats `LIKE` sont générés et concaténés en utilisant `AND`. Par exemple, `['like', 'name', ['test', 'sample']]` génère `name LIKE '%test%' AND name LIKE '%sample%'`. Vous pouvez également fournir un troisième paramètre facultatif pour spécifier comment échapper les caractères spéciaux dans les valeurs. Les opérandes doivent être un tableau de correspondance entre les caractères spéciaux et les contre-parties échappées. Si cet opérande n'est pas fourni, une mise en correspondance par défaut est utilisée. Vous pouvez utiliser `false` ou un tableau vide pour indiquer que les valeurs sont déjà échappées et qu'aucun échappement ne doit être appliqué. Notez que lorsqu'un tableau de mise en correspondance pour l'échappement est utilisé (ou quand le troisième opérande n'est pas fourni), les valeurs sont automatiquement entourées par une paire de caractères `%`. +- `like`: l'opérande 1 doit être une colonne ou une expression de base de données, tandis que l'opérande 2 doit être une chaîne de caractères ou + un tableau représentant les valeurs que cette colonne ou cette expression de base de données peuvent être. + Par exemple, `['like', 'name', 'tester']` génère `name LIKE '%tester%'`. + Lorsque la plage de valeurs est donnée sous forme de tableau, de multiples prédicats `LIKE` sont générés et concaténés + en utilisant `AND`. + Par exemple, `['like', 'name', ['test', 'sample']]` génère `name LIKE '%test%' AND name LIKE '%sample%'`. + Vous pouvez également fournir un troisième paramètre facultatif pour spécifier comment échapper les caractères spéciaux dans les valeurs. + Les opérandes doivent être un tableau de correspondance + entre les caractères spéciaux et les contre-parties échappées. + Si cet opérande n'est pas fourni, une mise en correspondance par défaut est utilisée. + Vous pouvez utiliser `false` ou un tableau vide pour indiquer que les valeurs sont déjà échappées et qu'aucun échappement ne doit être appliqué. + Notez que lorsqu'un tableau de mise en correspondance pour l'échappement est utilisé (ou quand le troisième opérande n'est pas fourni), les valeurs sont automatiquement entourées par une paire de caractères `%`. - > Note: lors de l'utilisation de PostgreSQL vous pouvez aussi utiliser [`ilike`](http://www.postgresql.org/docs/8.3/static/functions-matching.html#FUNCTIONS-LIKE) à la place de `like` pour une mise en correspondance insensible à la casse. + > Note: lors de l'utilisation de PostgreSQL vous pouvez aussi utiliser [`ilike`](http://www.postgresql.org/docs/8.3/static/functions-matching.html#FUNCTIONS-LIKE) + >à la place de `like` pour une mise en correspondance insensible à la casse. -- `or like`: similaire à l'opérateur `like` sauf que `OR`est utilisé pour concaténer les prédicats `LIKE` quand l'opérande 2 est un tableau. +- `or like`: similaire à l'opérateur `like` sauf que `OR`est utilisé pour concaténer les prédicats `LIKE` + quand l'opérande 2 est un tableau. -- `not like`: similaire à l'opérateur `like` sauf que `LIKE` est remplacé par `NOT LIKE` dans la condition générée. +- `not like`: similaire à l'opérateur `like` sauf que `LIKE` est remplacé par `NOT LIKE` + dans la condition générée. -- `or not like`: similaire à l'opérateur `not like` sauf que `OR` est utilisé pour concaténer les prédicats `NOT LIKE`. +- `or not like`: similaire à l'opérateur `not like` sauf que `OR` est utilisé pour concaténer + les prédicats `NOT LIKE`. -- `exists`: requiert un opérande que doit être une instance de [[yii\db\Query]] représentant la sous-requête. Il construit une expression `EXISTS (sub-query)`. +- `exists`: requiert un opérande que doit être une instance de [[yii\db\Query]] représentant la sous-requête. + Il construit une expression `EXISTS (sub-query)`. - `not exists`: similaire à l'opérateur `exists` et construit une expression `NOT EXISTS (sub-query)`. -- `>`, `<=`, ou tout autre opérateur de base de données valide qui accepte deux opérandes : le premier opérande doit être un nom de colonne, tandis que le second doit être une valeur. Par exemple, `['>', 'age', 10]` génère `age>10`. +- `>`, `<=`, ou tout autre opérateur de base de données valide qui accepte deux opérandes : + le premier opérande doit être un nom de colonne, tandis que le second doit être une valeur. Par exemple, `['>', 'age', 10]` génère `age>10`. En utilisant le format opérateur, Yii, en interne, utilise la liaison des paramètres afin, que contrairement au [format chaîne de caractères](#string-format), ici, vous n'avez pas besoin d'ajouter les paramètres à la main. +Cependant, notez que Yii ne procède pas à l'échappement des noms de colonne, c'est pourquoi si vous passez un nom de variable obtenu de l'utilisateur en tant que nom de colonne sans vérification, l'application devient vulnérable à l'injection SQL. +Afin de maintenir l'application sûre, soit n'utilisez pas de variables comme nom de colonne, soit filtrez les variables par une liste blanche. +Dans le cas où vous avez besoin d'obtenir un nom de colonne de l'utilisateur, lisez +l'article du guide [Filtrage des données](output-data-widgets.md#filtering-data). +Ainsi l'exemple de code suivant est vulnérable : + +```php +// Code vulnérable: +$column = $request->get('column'); +$value = $request->get('value); +$query->where(['=', $column, $value]); +// $value est sûre, mais le nom $column n'est pas encodé ! +``` + +#### Format objet + +Le format objet est disponible depuis 2.0.14 et est à la fois le moyen plus puissant et le plus complexe pour définir des conditions. +Vous devez le suivre si vous voulez construire votre propre abstraction au-dessus du constructeur de requêtes (query builder) ou si vous voulez mettre en œuvre vos propres conditions complexes. + + +Les instances de classes de condition sont immuables. +Le seul but est de stocker des données de condition et de fournir des obtenteurs (getters) pour les constructeurs de conditions. +La classe « constructeur de condition » (condition builder) est une classe qui contient la logique qui transforme les données stockées en condition dans une expression SQL. + +En interne, les formats décrits plus haut sont implicitement convertis en format objet avant de construire le SQL brut, + aussi est-il possible de combiner les formats en une condition unique : + +```php +$query->andWhere(new OrCondition([ + new InCondition('type', 'in', $types), + ['like', 'name', '%good%'], + 'disabled=false' +])) +``` + +La conversion du format opérateur au format objet est accomplie en fonction de la propriété +[[yii\db\QueryBuilder::conditionClasses|QueryBuilder::conditionClasses]] , +qui fait correspondre des noms d'opérateurs à des nom de classe représentatives : + +- `AND`, `OR` -> `yii\db\conditions\ConjunctionCondition` +- `NOT` -> `yii\db\conditions\NotCondition` +- `IN`, `NOT IN` -> `yii\db\conditions\InCondition` +- `BETWEEN`, `NOT BETWEEN` -> `yii\db\conditions\BetweenCondition` + +Et ainsi de suite. + +L'utilisation du format objet rend possible de créer vos propres conditions ou de changer la manière dont celles par défaut sont construites. +Reportez-vous au chapitre [Ajout de conditions et d'expressions personnalisées](#adding-custom-conditions-and-expressions) pour en savoir plus. #### Ajout de conditions -Vous pouvez utiliser [[yii\db\Query::andWhere()|andWhere()]] ou [[yii\db\Query::orWhere()|orWhere()]] pour ajouter des conditions supplémentaires à une condition existante. Vous pouvez les appeler plusieurs fois pour ajouter plusieurs conditions séparément. Par exemple : +Vous pouvez utiliser [[yii\db\Query::andWhere()|andWhere()]] ou [[yii\db\Query::orWhere()|orWhere()]] pour ajouter des conditions supplémentaires à une condition existante. +Vous pouvez les appeler plusieurs fois pour ajouter plusieurs conditions séparément. +Par exemple : ```php $status = 10; @@ -263,9 +391,12 @@ WHERE (`status` = 10) AND (`title` LIKE '%yii%') ``` -#### Filtrage des conditions +#### Conditions de filtrage -Lors de la construction de conditions `WHERE` basées sur des entrées de l'utilisateur final, vous voulez généralement ignorer les valeurs entrées qui sont vides. Par exemple, dans un formulaire de recherche par nom d'utilisateur ou par adresse de courriel, vous aimeriez ignorer la condition nom d'utilisateur/adresse de courriel si l'utilisateur n'a rien saisi les champs correspondants. Vous pouvez faire cela en utilisant la méthode [[yii\db\Query::filterWhere()|filterWhere()]] : +Lors de la construction de conditions `WHERE` basées sur des entrées de l'utilisateur final, +vous voulez généralement ignorer les valeurs entrées qui sont vides. +Par exemple, dans un formulaire de recherche par nom d'utilisateur ou par adresse de courriel, vous aimeriez ignorer la condition nom d'utilisateur/adresse de courriel si l'utilisateur n'a rien saisi dans les champs correspondants. +Vous pouvez faire cela en utilisant la méthode [[yii\db\Query::filterWhere()|filterWhere()]] : ```php // $username et $email sont entrées par l'utilisateur @@ -275,13 +406,18 @@ $query->filterWhere([ ]); ``` -La seule différence entre [[yii\db\Query::filterWhere()|filterWhere()]] et [[yii\db\Query::where()|where()]] est que la première ignore les valeurs vides fournies dans la condition au [format haché](#hash-format). Ainsi si `$email` est vide alors que `$username` ne l'est pas, le code ci dessus produit la condition SQL `WHERE username=:username`. +La seule différence entre [[yii\db\Query::filterWhere()|filterWhere()]] et [[yii\db\Query::where()|where()]] est que la première ignore les valeurs vides fournies dans la condition au [format haché](#hash-format). +Ainsi si `$email` est vide alors que `$username` ne l'est pas, +le code ci dessus produit la condition SQL `WHERE username=:username`. > Info: une valeur est considérée comme vide si elle est nulle, un tableau vide, ou un chaîne de caractères vide, ou un chaîne de caractères constituée d'espaces uniquement. -Comme avec [[yii\db\Query::andWhere()|andWhere()]] et [[yii\db\Query::orWhere()|orWhere()]], vous pouvez utiliser [[yii\db\Query::andFilterWhere()|andFilterWhere()]] et [[yii\db\Query::orFilterWhere()|orFilterWhere()]] pour ajouter des conditions de filtrage supplémentaires à une condition existante. +Comme avec [[yii\db\Query::andWhere()|andWhere()]] et [[yii\db\Query::orWhere()|orWhere()]], +vous pouvez utiliser [[yii\db\Query::andFilterWhere()|andFilterWhere()]] et [[yii\db\Query::orFilterWhere()|orFilterWhere()]] +pour ajouter des conditions de filtrage supplémentaires à une condition existante. -En outre, il y a [[yii\db\Query::andFilterCompare()]] qui peut déterminer intelligemment l'opérateur en se basant sur ce qu'il y a dans les valeurs : +En outre, il y a [[yii\db\Query::andFilterCompare()]] qui peut déterminer intelligemment l'opérateur +en se basant sur ce qu'il y a dans les valeurs : ```php $query->andFilterCompare('name', 'John Doe'); @@ -295,6 +431,12 @@ Vous pouvez aussi utiliser un opérateur explicitement : $query->andFilterCompare('name', 'Doe', 'like'); ``` +Depuis Yii 2.0.1, il existe des méthodes similaires pour la condition `HAVING` : + +- [[yii\db\Query::filterHaving()|filterHaving()]] +- [[yii\db\Query::andFilterHaving()|andFilterHaving()]] +- [[yii\db\Query::orFilterHaving()|orFilterHaving()]] + ### [[yii\db\Query::orderBy()|orderBy()]] La méthode [[yii\db\Query::orderBy()|orderBy()]] spécifie le fragment `ORDER BY` d'une requête SQL. Par exemple : @@ -307,9 +449,11 @@ $query->orderBy([ ]); ``` -Dans le code ci-dessus, les clés du tableau sont des noms de colonnes, tandis que les valeurs sont les instructions de direction de tri. La constante PHP `SORT_ASC` spécifie un tri ascendant et `SORT_DESC`, un tri descendant. +Dans le code ci-dessus, les clés du tableau sont des noms de colonnes, tandis que les valeurs sont les instructions de direction de tri. +La constante PHP `SORT_ASC` spécifie un tri ascendant et `SORT_DESC`, un tri descendant. -Si `ORDER BY` ne fait appel qu'à des noms de colonnes simples, vous pouvez le spécifier en utilisant une chaîne de caractères, juste comme vous le faites en écrivant des instructions SQL brutes. Par exemple : +Si `ORDER BY` ne fait appel qu'à des noms de colonnes simples, vous pouvez le spécifier en utilisant une chaîne de caractères, juste comme vous le faites en écrivant des instructions SQL brutes. +Par exemple : ```php $query->orderBy('id ASC, name DESC'); @@ -317,7 +461,8 @@ $query->orderBy('id ASC, name DESC'); > Note: vous devez utiliser le format tableau si `ORDER BY` fait appel à une expression de base de données. -Vous pouvez appeler [[yii\db\Query::addOrderBy()|addOrderBy()]] pour ajouter des colonnes supplémentaires au fragment `ORDER BY`. Par exemple : +Vous pouvez appeler [[yii\db\Query::addOrderBy()|addOrderBy()]] pour ajouter des colonnes supplémentaires au fragment `ORDER BY`. +Par exemple : ```php $query->orderBy('id ASC') @@ -334,7 +479,8 @@ La méthode [[yii\db\Query::groupBy()|groupBy()]] spécifie le fragment `GROUP B $query->groupBy(['id', 'status']); ``` -Si `GROUP BY` ne fait appel qu'à des noms de colonnes simples, vous pouvez le spécifier en utilisant un chaîne de caractères, juste comme vous le faîtes en écrivant des instructions SQL brutes. Par exemple : +Si `GROUP BY` ne fait appel qu'à des noms de colonnes simples, vous pouvez le spécifier en utilisant un chaîne de caractères, juste comme vous le faîtes en écrivant des instructions SQL brutes. +Par exemple : ```php $query->groupBy('id, status'); @@ -342,7 +488,8 @@ $query->groupBy('id, status'); > Note: vous devez utiliser le format tableau si `GROUP BY` fait appel à une expression de base de données. -Vous pouvez appeler [[yii\db\Query::addGroupBy()|addGroupBy()]] pour ajouter des colonnes au fragment `GROUP BY`. Par exemple : +Vous pouvez appeler [[yii\db\Query::addGroupBy()|addGroupBy()]] pour ajouter des colonnes au fragment `GROUP BY`. +Par exemple : ```php $query->groupBy(['id', 'status']) @@ -352,7 +499,8 @@ $query->groupBy(['id', 'status']) ### [[yii\db\Query::having()|having()]] -La méthode [[yii\db\Query::having()|having()]] spécifie le fragment `HAVING` d'un requête SQL. Elle accepte une condition qui peut être spécifiée de la même manière que celle pour [where()](#where). Par exemple : +La méthode [[yii\db\Query::having()|having()]] +spécifie le fragment `HAVING` d'un requête SQL. Elle accepte une condition qui peut être spécifiée de la même manière que celle pour [where()](#where). Par exemple : ```php // ... HAVING `status` = 1 @@ -361,7 +509,8 @@ $query->having(['status' => 1]); Reportez-vous à la documentation de [where()](#where) pour plus de détails sur la manière de spécifier une condition. -Vous pouvez appeler [[yii\db\Query::andHaving()|andHaving()]] ou [[yii\db\Query::orHaving()|orHaving()]] pour ajouter des conditions supplémentaires au fragment `HAVING` fragment. Par exemple : +Vous pouvez appeler [[yii\db\Query::andHaving()|andHaving()]] ou [[yii\db\Query::orHaving()|orHaving()]] pour ajouter des conditions supplémentaires au fragment `HAVING` fragment. +Par exemple : ```php // ... HAVING (`status` = 1) AND (`age` > 30) @@ -372,7 +521,8 @@ $query->having(['status' => 1]) ### [[yii\db\Query::limit()|limit()]] et [[yii\db\Query::offset()|offset()]] -Les méthodes [[yii\db\Query::limit()|limit()]] et [[yii\db\Query::offset()|offset()]] spécifient les fragments `LIMIT` et `OFFSET` d'une requête SQL. Par exemple : +Les méthodes [[yii\db\Query::limit()|limit()]] et [[yii\db\Query::offset()|offset()]] spécifient les fragments `LIMIT` et `OFFSET` d'une requête SQL. +Par exemple : ```php // ... LIMIT 10 OFFSET 20 @@ -381,7 +531,8 @@ $query->limit(10)->offset(20); Si vous spécifiez une limite ou un décalage (p. ex. une valeur négative), il est ignoré. -> Info: pour les systèmes de gestion de base de données qui prennent en charge `LIMIT` et `OFFSET` (p. ex. MSSQL), le constructeur de requêtes génère une instruction SQL qui émule le comportement `LIMIT`/`OFFSET`. +> Info: pour les systèmes de gestion de base de données qui ne prennent pas en charge `LIMIT` et `OFFSET` (p. ex. MSSQL), +le constructeur de requêtes génère une instruction SQL qui émule le comportement `LIMIT`/`OFFSET`. ### [[yii\db\Query::join()|join()]] @@ -397,7 +548,11 @@ La méthode [[yii\db\Query::join()|join()]] accepte quatre paramètres : - `$type`: type de jointure , p. ex. `'INNER JOIN'`, `'LEFT JOIN'`. - `$table`: le nom de la table à joindre. -- `$on`: facultatif, la condition de jointure, c.-à-d. le fragment `ON`. Reportez-vous à [where()](#where) pour des détails sur la manière de spécifier une condition. Notez, que la syntaxe tableau ne fonctionne **PAS** pour spécifier une condition basée sur une colonne, p. ex. `['user.id' => 'comment.userId']` conduit à une condition où l'identifiant utilisateur doit être égal à la chaîne de caractères `'comment.userId'`. Vous devez utiliser la syntaxe chaîne de caractères à la place et spécifier la condition `'user.id = comment.userId'`. +- `$on`: facultatif, la condition de jointure, c.-à-d. le fragment `ON`. + Reportez-vous à [where()](#where) pour des détails sur la manière de spécifier une condition. + Notez, que la syntaxe tableau ne fonctionne **PAS** pour spécifier une condition basée sur une colonne, p. ex. `['user.id' => 'comment.userId']` conduit à une condition + où l'identifiant utilisateur doit être égal à la chaîne de caractères `'comment.userId'`. + Vous devez utiliser la syntaxe chaîne de caractères à la place et spécifier la condition `'user.id = comment.userId'`. - `$params`: facultatif, les paramètres à lier à la condition de jointure. Vous pouvez utiliser les méthodes raccourcies suivantes pour spécifier `INNER JOIN`, `LEFT JOIN` et `RIGHT JOIN`, respectivement. @@ -414,7 +569,8 @@ $query->leftJoin('post', 'post.user_id = user.id'); Pour joindre plusieurs tables, appelez les méthodes join ci-dessus plusieurs fois, une fois pour chacune des tables. -En plus de joindre des tables, vous pouvez aussi joindre des sous-requêtes. Pour faire cela, spécifiez les sous-requêtes à joindre sous forme d'objets [[yii\db\Query]]. Par exemple : +En plus de joindre des tables, vous pouvez aussi joindre des sous-requêtes. Pour faire cela, spécifiez les sous-requêtes à joindre sous forme d'objets [[yii\db\Query]]. +Par exemple : ```php $subQuery = (new \yii\db\Query())->from('post'); @@ -455,7 +611,9 @@ L'objet [[yii\db\Query]] fournit un jeu complet de méthodes pour différents ob - [[yii\db\Query::scalar()|scalar()]]: retourne une valeur scalaire située au croisement de la première ligne et de la première colonne du résultat. - [[yii\db\Query::exists()|exists()]]: retourne une valeur précisant si le résultat de la requête contient un résultat. - [[yii\db\Query::count()|count()]]: retourne le résultat d'une requête `COUNT`.. -- D'autres méthodes d'agrégation de requêtes, y compris [[yii\db\Query::sum()|sum($q)]], [[yii\db\Query::average()|average($q)]], [[yii\db\Query::max()|max($q)]], [[yii\db\Query::min()|min($q)]]. Le paramètre `$q` est obligatoire pour ces méthodes et peut être soit un nom de colonne, soit une expression de base de données. +- D'autres méthodes d'agrégation de requêtes, y compris [[yii\db\Query::sum()|sum($q)]], [[yii\db\Query::average()|average($q)]], [[yii\db\Query::max()|max($q)]], [[yii\db\Query::min()|min($q)]]. + Le paramètre `$q` est obligatoire pour ces méthodes + et peut être soit un nom de colonne, soit une expression de base de données. Par exemple : @@ -473,9 +631,15 @@ $row = (new \yii\db\Query()) ->one(); ``` -> Note: la méthode [[yii\db\Query::one()|one()]] retourne seulement la première ligne du résultat de la requête. Elle n'ajoute PAS `LIMIT 1` à l'instruction SQL générée. Cela est bon et préférable si vous savez que la requête ne retourne qu'une seule ou quelques lignes de données (p. ex. si vous effectuez une requête avec quelques clés primaires). Néanmoins, si la requête peut potentiellement retourner de nombreuses lignes de données, vous devriez appeler `limit(1)` explicitement pour améliorer la performance, p. ex. `(new \yii\db\Query())->from('user')->limit(1)->one()`. +> Note: la méthode [[yii\db\Query::one()|one()]] retourne seulement la première ligne du résultat de la requête. + Elle n'ajoute PAS `LIMIT 1` à l'instruction SQL générée. + Cela est bon et préférable si vous savez que la requête ne retourne qu'une seule + ou quelques lignes de données (p. ex. si vous effectuez une requête avec quelques clés primaires). + Néanmoins, si la requête peut potentiellement retourner de nombreuses lignes de données, vous devriez appeler `limit(1)` explicitement pour améliorer la performance, p. ex. `(new \yii\db\Query())->from('user')->limit(1)->one()`. -Toutes ces méthodes de requête accepte un paramètre supplémentaire `$db` représentant la [[yii\db\Connection|connexion à la base de données]] qui doit être utilisée pour effectuer la requête. Si vous omettez ce paramètre, le [composant d'application](structure-application-components.md) `db` est utilisé en tant que connexion à la base de données. Ci-dessous, nous présentons un autre exemple utilisant la méthode [[yii\db\Query::count()|count()]] : +Toutes ces méthodes de requête acceptent un paramètre supplémentaire `$db` représentant la [[yii\db\Connection|connexion à la base de données]] +qui doit être utilisée pour effectuer la requête. +Si vous omettez ce paramètre, le [composant d'application](structure-application-components.md) `db` est utilisé en tant que connexion à la base de données. Ci-dessous, nous présentons un autre exemple utilisant la méthode [[yii\db\Query::count()|count()]] : ```php // exécute SQL: SELECT COUNT(*) FROM `user` WHERE `last_name`=:last_name @@ -493,6 +657,7 @@ Lorsque vous appelez une méthode de requête de [[yii\db\Query]], elle effectue Parfois, vous voulez peut-être examiner ou utiliser une instruction SQL construite à partir d'un objet [[yii\db\Query]]. Vous pouvez faire cela avec le code suivant : + ```php $command = (new \yii\db\Query()) ->select(['id', 'email']) @@ -513,7 +678,10 @@ $rows = $command->queryAll(); ### Indexation des résultats de la requête -Lorsque vous appelez [[yii\db\Query::all()|all()]], elle retourne un tableau de lignes qui sont indexées par des entiers consécutifs. Parfois, vous désirez peut-être les indexer différemment, comme les indexer par une colonne particulière ou par des expressions donnant une valeur. Vous pouvez le faire en appelant [[yii\db\Query::indexBy()|indexBy()]] avant [[yii\db\Query::all()|all()]]. Par exemple : +Lorsque vous appelez [[yii\db\Query::all()|all()]], elle retourne un tableau de lignes qui sont indexées par des entiers consécutifs. +Parfois, vous désirez peut-être les indexer différemment, comme les indexer par une colonne particulière ou par des expressions donnant une valeur. +Vous pouvez le faire en appelant [[yii\db\Query::indexBy()|indexBy()]] avant [[yii\db\Query::all()|all()]]. +Par exemple : ```php // retourne [100 => ['id' => 100, 'username' => '...', ...], 101 => [...], 103 => [...], ...] @@ -534,14 +702,24 @@ $query = (new \yii\db\Query()) })->all(); ``` -Le fonction anonyme accepte un paramètre `$row` qui contient les données de la ligne courante et retourne une valeur scalaire qui est utilisée comme la valeur d'index de la ligne courante. +Le fonction anonyme accepte un paramètre `$row` qui contient les données de la ligne courante +et retourne une valeur scalaire qui est utilisée comme la valeur d'index de la ligne courante. -> Note: contrairement aux méthodes de requête telles que [[yii\db\Query::groupBy()|groupBy()]] ou [[yii\db\Query::orderBy()|orderBy()]] qui sont converties en SQL et font partie de la requête, cette méthode ne fait son travail qu'après que les données ont été retrouvées dans la base de données. Cela signifie que seules les noms de colonne qui on fait partie du fragement SELECT dans votre requête peuvent être utilisés. De plus, si vous avez sélectionné une colonne avec un préfixe de table, p. ex. `customer.id`, le jeu de résultats ne contient que `id` c'est pourquoi vous devez appeler `->indexBy('id')` sans préfixe de table. +> Note: contrairement aux méthodes de requête telles que [[yii\db\Query::groupBy()|groupBy()]] ou [[yii\db\Query::orderBy()|orderBy()]] +qui sont converties en SQL et font partie de la requête, cette méthode ne fait son travail qu'après que les données ont été retrouvées dans la base de données. +> Cela signifie que seuls les noms de colonne qui on fait partie du fragment SELECT dans votre requête peuvent être utilisés. +> De plus, si vous avez sélectionné une colonne avec un préfixe de table, p. ex. `customer.id`, le jeu de résultats ne contient que `id` c'est pourquoi vous devez appeler +> `->indexBy('id')` sans préfixe de table. ### Requêtes par lots -Lorsque vous travaillez sur de grandes quantités de données, des méthodes telles que [[yii\db\Query::all()]] ne conviennent pas car elles requièrent le chargement de toutes les données en mémoire. Pour conserver l'exigence de capacité mémoire basse, Yii fournit la prise en charge appelé requêtes par lots. +Lorsque vous travaillez sur de grandes quantités de données, des méthodes telles que [[yii\db\Query::all()]] ne conviennent pas car elles requièrent le chargement de toutes les données en mémoire du client. + Pour résoudre cet problème Yii assure la prise en charge de requêtes par lots. +Le serveur conserve les résultats de la requête, et le client utilise un curseur pour itérer sur le jeu de résultats un lot à la fois. + + +> Attention : il existe des limitations connues et des solutions de contournement pour la mise en œuvre des requêtes par lots par MySQL. Les requêtes par lots peuvent être utilisées comme suit : @@ -553,20 +731,28 @@ $query = (new Query()) ->orderBy('id'); foreach ($query->batch() as $users) { - // $users est dans un tableau de 100 ou moins lignes du la table user. + // $users est dans un tableau de 100 ou moins lignes de la table user. } // ou si vous voulez itérer les lignes une par une foreach ($query->each() as $user) { + //les données sont retrouvées du serveur en lots de 100, // $user représente une ligne de données de la table user. +} ``` -Les méthodes [[yii\db\Query::batch()]] et [[yii\db\Query::each()]] retournent un objet [[yii\db\BatchQueryResult]] qui implémente l'interface `Iterator` et qui, par conséquent, peut être utilisé dans une construction `foreach`. -Durant la première iteration, une requête SQL est faite à la base de données. Les données sont retrouvées en lots dans les itérations suivantes. Par défaut, la taille du lot est 100, ce qui signifie que 100 lignes sont retrouvées dans chacun des lots. Vous pouvez changer la taille du lot en passant le premier paramètre des méthodes `batch()` ou `each()`. +Les méthodes [[yii\db\Query::batch()]] et [[yii\db\Query::each()]] retournent un objet [[yii\db\BatchQueryResult]] +qui implémente l'interface `Iterator` et qui, par conséquent, peut être utilisé dans une construction `foreach`. +Durant la première itération, une requête SQL est faite à la base de données. Les données sont retrouvées en lots dans les itérations suivantes. +Par défaut, la taille du lot est 100, ce qui signifie que 100 lignes sont retrouvées dans chacun des lots. +Vous pouvez changer la taille du lot en passant le premier paramètre des méthodes `batch()` ou `each()`. Comparée à la requête [[yii\db\Query::all()]], la requête par lots ne charge que 100 lignes de données à la fois en mémoire. Si vous traitez les données et les détruisez tout de suite, la requête par lots réduit l'utilisation de la mémoire. -Si vous spécifiez l'indexation du résultat de la requête par une colonne via [[yii\db\Query::indexBy()]], la requête par lots conserve l'index approprié. Par exemple : +Si vous spécifiez l'indexation du résultat de la requête par une colonne via [[yii\db\Query::indexBy()]], +la requête par lots conserve l'index approprié. Par exemple : + +Par exemple : ```php $query = (new \yii\db\Query()) @@ -581,3 +767,238 @@ foreach ($query->each() as $username => $user) { // ... } ``` + +#### Limitations des requêtes par lots dans MySQL + +La mise en œuvre des requêtes par lots de MySQL s'appuie sur la bibliothèque du pilote PDO. Par défaut, les requêtes MySQL sont +[`mises en tampon`](http://php.net/manual/en/mysqlinfo.concepts.buffering.php). +Cela empêche d'utiliser le curseur pour obtenir les données, parce que cela n'empêche pas le jeu résultant complet d'être chargé dans la mémoire du client par le pilote. + + +> Note: lorsque `libmysqlclient` est utilisé (typique de PHP5), la limite mémoire de PHP ne compte pas la mémoire utilisée par les jeux de résultats. +Il peut sembler que les requêtes par lot fonctionnent correctement, mais en réalité l'intégralité du jeu de données est chargé dans la mémoire du client. + + +Pour désactiver la mise en tampon et réduire les exigences en mémoire client, la propriété connexion à PDOT +`PDO::MYSQL_ATTR_USE_BUFFERED_QUERY` doit être définie à `false`. Cependant, jusqu'à ce que l'intégralité du jeu de données ait été retrouvé, aucune autre requête ne peut être faite via la même connexion. Cela peut empêcher `ActiveRecord` +d'effectuer une requête pour obtenir le schéma de table lorsqu'il le doit. +Si cela n'est pas un problème (le schéma de table est déjà mis en cache), il est possible de commuter la connexion originale en mode sans mise en tampon, +et de revenir en arrière lorsque la requête par lots est terminée. + + +```php +Yii::$app->db->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + +// Effectue la requête par lots + +Yii::$app->db->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); +``` + +> Note: dans le cas de MyISAM, pour toute la durée de la requête par lots, la table peut devenir verrouillée, retardant ainsi ou refusant l'accès en écriture pour une autre connexion. Lors de l'utilisation de requêtes sans mise en tampon, essayez de conserver le curseur ouvert pour un temps aussi court que possible. + +Si le schéma n'est pas mis en cache, ou s'il est nécessaire d'effectuer d'autres requêtes alors que la requête par lots est en cours de traitement, vous pouvez créer une connexion à la base de données séparée sans mise en tampon : + +```php +$unbufferedDb = new \yii\db\Connection([ + 'dsn' => Yii::$app->db->dsn, + 'username' => Yii::$app->db->username, + 'password' => Yii::$app->db->password, + 'charset' => Yii::$app->db->charset, +]); +$unbufferedDb->open(); +$unbufferedDb->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); +``` + +Si vous voulez garantir que la `$unbufferedDb` a exactement les mêmes attributs PDO gue la `$db` originale avec mise en tampon mais que `PDO::MYSQL_ATTR_USE_BUFFERED_QUERY` est `false`, +[envisagez une copie profonde de `$db`](https://github.com/yiisoft/yii2/issues/8420#issuecomment-301423833), +définissez le à `false` manuellement. + +Ensuite, les requêtes sont créées normalement. La nouvelle connexion est utilisée pour exécuter les requêtes par lots et retrouver des résultats soit par lots, soit un par un : + +```php +// obtention des données par lots de 1000 +foreach ($query->batch(1000, $unbufferedDb) as $users) { + // ... +} + + +// les données sont retrouvées dans le serveur par lots de 1000, mais elles sont itérées une à une +foreach ($query->each(1000, $unbufferedDb) as $user) { + // ... +} +``` + +Lorsque la connexion n'est plus nécessaire et que le jeu de résultats a été retrouvé, on peut le fermer : + +```php +$unbufferedDb->close(); +``` + +> Note: une requête sans mise en tampon utilise moinsde mémoire du côté PHP, mais peut augmenter la charge du serveur MySQL. +> Il est recommandé de concevoir votre propre code avec votre pratique en production pour des données massives supplémentaires, +> [par exemple, divisez la plage pour les clés entières, itérez sur elles avec des requêtes sans mise en tampon](https://github.com/yiisoft/yii2/issues/8420#issuecomment-296109257). + + + + + + +### Ajout de conditions et expressions personnalisées + +Comme cela a été mentionné au chapitre [Conditions – Format Object](#object-format), il est possible de créer des classe de condition personnalisées. +Pour l'exemple, créons une condition qui vérifie que des colonnes spécifiques sont inférieures à une valeur donnée. +En utilisant le format opérateur, ça devrait ressembler à ce qui suit : + +```php +[ + 'and', + '>', 'posts', $minLimit, + '>', 'comments', $minLimit, + '>', 'reactions', $minLimit, + '>', 'subscriptions', $minLimit +] +``` + +Lorsqu'une telle condition est utilisée une seule fois, tout va bien. Dans le cas où elle est utilisée de multiples fois dans une unique requête, cela peut être grandement optimisé. +Créons un objet condition personnalisé pour le démontrer. + +Yii dispose d'une classe [[yii\db\conditions\ConditionInterface|ConditionInterface]], qui peut être utilisée pour marquer des classes qui représentent une condition. +Elle nécessite la mise en œuvre de la méthode `fromArrayDefinition()`, afin de rendre possible la création d'une condition à partir du format tableau. +Dans le cas où vous n'en n'avez pas besoin, vous pouvez mettre cette méthode en œuvre avec lancement d'une exception. + +Comme nous créons notre classe de condition personnalisée, nous pouvons construire une API qui s'adapte au mieux à notre tâche. + +```php +namespace app\db\conditions; + +class AllGreaterCondition implements \yii\db\conditions\ConditionInterface +{ + private $columns; + private $value; + + /** + * @param string[] $columns tableau de colonnes qui doivent être plus grande que $value + * @param mixed $value la valeur à laquelle comparer chaque $column + */ + public function __construct(array $columns, $value) + { + $this->columns = $columns; + $this->value = $value; + } + + public static function fromArrayDefinition($operator, $operands) + { + throw new InvalidArgumentException('Not implemented yet, but we will do it later'); + } + + public function getColumns() { return $this->columns; } + public function getValue() { return $this->vaule; } +} +``` + +Ainsi nous pouvons créer un objet condition : + +```php +$conditon = new AllGreaterCondition(['col1', 'col2'], 42); +``` + +Mais `QueryBuilder` (le constructeur de requêtes) ne sait toujours pas comment élaborer une condition SQL à partir de cet objet. +Maintenant nous devons créer un constructeur pour cette condition. Il doit mettre en œuvre une méthode `build()`. + +```php +namespace app\db\conditions; + +class AllGreaterConditionBuilder implements \yii\db\ExpressionBuilderInterface +{ + use \yii\db\Condition\ExpressionBuilderTrait; // Contient le constructeur et la propriété `queryBuilder`. + + /** + * @param AllGreaterCondition $condition la condition à élaborer + * @param array $params les paramètres de liaison. + */ + public function build(ConditionInterface $condition, &$params) + { + $value = $condition->getValue(); + + $conditions = []; + foreach ($condition->getColumns() as $column) { + $conditions[] = new SimpleCondition($column, '>', $value); + } + + return $this->queryBuider->buildCondition(new AndCondition($conditions), $params); + } +} +``` + +Ensuite, laissons simplement [[yii\db\QueryBuilder|QueryBuilder]] prendre connaissance de notre nouvelle condition — établissons une correspondance entre lui et notre tableau `expressionBuilders`. Cela peut se faire directement à partir de la configuration de l'application : + +```php +'db' => [ + 'class' => 'yii\db\mysql\Connection', + // ... + 'queryBuilder' => [ + 'expressionBuilders' => [ + 'app\db\conditions\AllGreaterCondition' => 'app\db\conditions\AllGreaterConditionBuilder', + ], + ], +], +``` + +Maintenant nous sommes en mesure d'utiliser notre condition dans `where()`: + +```php +$query->andWhere(new AllGreaterCondition(['posts', 'comments', 'reactions', 'subscriptions'], $minValue)); +``` + +Si nous voulons rendre possible la création de notre condition personnalisée en utilisant le format opérateur, nous devons le déclarer dans +[[yii\db\QueryBuilder::conditionClasses|QueryBuilder::conditionClasses]]: + +```php +'db' => [ + 'class' => 'yii\db\mysql\Connection', + // ... + 'queryBuilder' => [ + 'expressionBuilders' => [ + 'app\db\conditions\AllGreaterCondition' => 'app\db\conditions\AllGreaterConditionBuilder', + ], + 'conditionClasses' => [ + 'ALL>' => 'app\db\conditions\AllGreaterCondition', + ], + ], +], +``` + +Et créer une mise en œuvre réelle de la méthode `AllGreaterCondition::fromArrayDefinition()` +dans `app\db\conditions\AllGreaterCondition`: + +```php +namespace app\db\conditions; + +class AllGreaterCondition implements \yii\db\conditions\ConditionInterface +{ + // ... see the implementation above + + public static function fromArrayDefinition($operator, $operands) + { + return new static($operands[0], $operands[1]); + } +} +``` + +À la suite de cela, nous pouvons créer notre condition personnalisée en utilisant un format opérateur plus court : + +```php +$query->andWhere(['ALL>', ['posts', 'comments', 'reactions', 'subscriptions'], $minValue]); +``` + +Vous pouvez noter que deux conceptes ont été utilisés : Expressions et Conditions. Il y a une [[yii\db\ExpressionInterface]] qui doit être utilisée pour marquer les objets qui requièrent une classe constructrice d'expression qui met en œuvre +[[yii\db\ExpressionBuilderInterface]] pour être construite. Il existe également une [[yii\db\condition\ConditionInterface]], qui étend +[[yii\db\ExpressionInterface|ExpressionInterface]] et doit être utilisée pour des objets qui peuvent être créés à partir d'un tableau de définition comme cela a été expliqué plus haut, mais qui peuvent aussi bien nécessiter le constructeur. + +Pour résumer: + +- Expression – est un objet de transfert de donnèes — Data Transfer Object (DTO) — pour un jeu de données, qui peut être compilé en une instruction SQL (un opérateur, une chaîne de caractères, un tableau, JSON, etc). +- Condition – est un super jeu d'expressions, qui agrège de multiples expressions (ou valeurs scalaires) qui peut être compilé en une unique condition SQL. + +Vous pouvez créer votre propre classe qui met en œuvre l'interface [[yii\db\ExpressionInterface|ExpressionInterface]] pour cacher la complexité de la transformation de données en instructions SQL. Vous en apprendrez plus sur d'autres exemples d'expressions dans le +[prochain article](db-active-record.md); diff --git a/docs/guide-fr/intro-upgrade-from-v1.md b/docs/guide-fr/intro-upgrade-from-v1.md index d7a77d164c4..40337a2ce83 100644 --- a/docs/guide-fr/intro-upgrade-from-v1.md +++ b/docs/guide-fr/intro-upgrade-from-v1.md @@ -61,7 +61,7 @@ Composants et objets Yii 2.0 décompose la classe `CComponent` 1.1 en deux classes: [[yii\base\BaseObject]] et [[yii\base\Component]]. Le classe [[yii\base\BaseObject|BaseObject]] est une classe de base légère qui permet de définir les [Propriétés de l'objet](concept-properties.md) via des accesseurs. La classe [[yii\base\Component|Component]] est une -sous classe de [[yii\base\BaseObject|BaseObject]] et prend en charge les [Evénements](concept events.md) et les +sous classe de [[yii\base\BaseObject|BaseObject]] et prend en charge les [Événements](concept events.md) et les [Comportements](concept-behaviors.md). Si votre classe n'a pas besoin des événements et des comportements, vous devriez envisager d'utiliser @@ -134,7 +134,7 @@ $component->on($eventName, $handler); // Pour détacher le gestionnaire, utilisez : // $component->off($eventName, $handler); ``` -Il y a de nombreuses améliorations dans la gestion des événements. Pour plus de détails, reportez-vous à la section [Evénements](concept-events.md). +Il y a de nombreuses améliorations dans la gestion des événements. Pour plus de détails, reportez-vous à la section [Événements](concept-events.md). Alias @@ -503,7 +503,7 @@ Au lieu de cela, vous devez implémenter [[yii\web\IdentityInterface]] qui est b Le modèle de projet avancé fournit un exemple. Reportez-vous aux sections [Authentification](security-authentication.md), [Authorisation](security-authorization.md), et -[Modèle de projet avancé](tutorial-advanced-app.md) pour en savoir plus. +[Modèle de projet avancé](https://www.yiiframework.com/extension/yiisoft/yii2-app-advanced/doc/guide) pour en savoir plus. Gestion des URL diff --git a/docs/guide-fr/intro-yii.md b/docs/guide-fr/intro-yii.md index 6cb94cf2f8f..32ce2e5d073 100644 --- a/docs/guide-fr/intro-yii.md +++ b/docs/guide-fr/intro-yii.md @@ -1,32 +1,32 @@ -Qu'est ce que Yii +Qu'est ce que Yii ? ================= Yii est un framework PHP hautes performances à base de composants qui permet de développer rapidement des applications Web modernes. -Le nom Yii (pronnoncée `Yee` ou `[ji:]`) signifie "simple et évolutif" en Chinois. Il peut également +Le nom Yii (prononcer `Yee` ou `[ji:]`) signifie "simple et évolutif" en Chinois. Il peut également être considéré comme un acronyme de **Yes It Is**! -Pour quel usage Yii est il optimal? +Pour quel usage Yii est il optimal ? ----------------------------------- Yii est un framework Web générique, c'est à dire qu'il peut être utilisé pour développer tous types d'applications Web basées sur PHP. De par son architecture à base de composants et son système de cache sophistiqué, il est particulièrement adapté au développement d'applications à forte audience telles que des portails, des forums, -des systèmes de gestion de contenu (CMS), des sites e-commerce, services Web RESTFul, etc. +des systèmes de gestion de contenu (CMS), des sites e-commerce, des services Web RESTFul, etc. -Comment se positionne Yii vis-à-vis des autres Frameworks? +Comment se positionne Yii vis-à-vis des autres Frameworks ? ---------------------------------------------------------- -- Comme la plupart des frameworks PHP, Yii est basé sur le modèle de conception MVC et encourage une +- Comme la plupart des frameworks PHP, Yii est basé sur le modèle de conception MVC (Modèle-Vue-Contrôleur) et encourage à une organisation du code basée sur ce modèle. - Yii repose sur l'idée que le code doit être écrit de façon simple et élégante. Il ne sera jamais question de -surcharger le code de Yii uniquement pour respecter un modèle de conception. +compliquer le code de Yii uniquement pour respecter un modèle de conception. - Yii est un framework complet offrant de nombreuses caractéristiques éprouvées et prêtes à l'emploi, telles que: -constructeur de requêtes et ActiveRecord, à la fois pour les bases de données relationnelles et NoSQL; support RESTful API; -support cache multi-niveaux; et plus. +constructeur de requêtes et ActiveRecord, à la fois pour les bases de données relationnelles et NoSQL; prise en charge RESTful API; +prise en charge de caches multi-niveaux; et plus. - Yii est extrêmement flexible. Vous pouvez personnaliser ou remplacer presque chaque partie du code du noyau. Vous pouvez également -profiter de son architecture extensible solide, afin d'utiliser ou développer des extensions redistribuables. +profiter de son architecture extensible solide, afin d'utiliser ou développer des extensions distribuables. - La haute performance est toujours un des principaux objectifs de Yii. Yii n'est pas un one-man show, il est soutenu par une [solide équipe de développement du noyau][about_yii] ainsi que d'une grande communauté @@ -40,9 +40,7 @@ via des interfaces simples et élégantes. Versions de Yii --------------- -Yii a actuellement deux versions majeures disponibles : 1.1 et 2.0. La version 1.1 est l'ancienne génération et est maintenant en mode maintenance. La version 2.0 est une réécriture complète de Yii, adoptant les dernières -technologies et protocoles, y compris Composer, PSR, les espaces de noms, les traits, et ainsi de suite. la version 2.0 est la dernière -génération du framework et recevra nos principaux efforts de développement dans les prochaines années. +Yii est actuellement disponible en deux versions majeures : 1.1 et 2.0. La version 1.1, l'ancienne génération, est désormais en mode maintenance. La version 2.0 est une réécriture complète de Yii, adoptant les dernières technologies et protocoles, y compris Composer, PSR, les espaces de noms, les traits, et ainsi de suite. La version 2.0 est la dernière génération du framework et recevra nos principaux efforts de développement dans les prochaines années. Ce guide est principalement pour la version 2.0. diff --git a/docs/guide-fr/runtime-logging.md b/docs/guide-fr/runtime-logging.md index 8cd79ceabc3..2095f80f15a 100644 --- a/docs/guide-fr/runtime-logging.md +++ b/docs/guide-fr/runtime-logging.md @@ -1,7 +1,7 @@ Enregistrements des messages ============================ -Yii fournit une puissante base structurée d'enregistrement des messages qui est très personnalisable et extensible. En utilisant cette base structurée, vous pouvez facilement enregistrer des types variés de messages, les filtrer et les rassembler dans différentes cibles comme les bases de données et les courriels. +Yii fournit une puissante base structurée (framework) d'enregistrement des messages qui est très personnalisable et extensible. En utilisant cette base structurée, vous pouvez facilement enregistrer des types variés de messages, les filtrer et les rassembler dans différentes cibles comme les bases de données et les courriels. L'utilisation de la base structurée d'enregistrement des messages de Yii nécessite de suivre les étapes suivantes : @@ -50,6 +50,8 @@ Vous pouvez enregistrer plusieurs cibles d'enregistrement dans votre application return [ // le composant "log" doit être chargé lors de la période d'amorçage 'bootstrap' => ['log'], + // le composant "log" traite les messages avec un horodatage (timestamp). Définissez le fuseau horaire PHP pour créer l'horodate correcte : + 'timeZone' => 'America/Los_Angeles', 'components' => [ 'log' => [ @@ -277,6 +279,8 @@ return [ La création d'une classe de cible d'enregistrement est très simple. Vous devez essentiellement implémenter [[yii\log\Target::export()]] en envoyant le contenu du tableau des [[yii\log\Target::messages]] vers un média désigné. Vous pouvez appeler la méthode [[yii\log\Target::formatMessage()]] pour formater chacun des messages. Pour plus de détails, reportez-vous à n'importe quelle classe de cible de messages incluse dans la version de Yii. +> Tip: au lieu de créer vos propres journaliseurs, vous pouvez essayez n'importe quel journaliseur compatible PSR-3 tel que [Monolog](https://github.com/Seldaek/monolog) en utilisant + [PSR log target extension](https://github.com/samdark/yii2-psr-log-target). ## Profilage de la performance diff --git a/docs/guide-fr/runtime-requests.md b/docs/guide-fr/runtime-requests.md index 4870ef2dec5..03315cdc8fe 100644 --- a/docs/guide-fr/runtime-requests.md +++ b/docs/guide-fr/runtime-requests.md @@ -1,12 +1,16 @@ Requêtes ======== -Les requêtes faites à l'application sont représentées en terme d'objets [[yii\web\Request]] qui fournissent des informations telles que les paramètres de requête, les entêtes HTTP, les cookies, etc. Pour une requête donnée, vous avez accès au [composant d'application](structure-application-components.md)`request` qui, par défaut, est une instance de [[yii\web\Request]]. Dans cette section, nous décrivons comment utiliser ce composant dans vos applications. +Les requêtes faites à l'application sont représentées en terme d'objets [[yii\web\Request]] qui fournissent des informations telles que les paramètres de requête, les entêtes HTTP, les cookies, etc. +Pour une requête donnée, vous avez accès au [composant d'application](structure-application-components.md)`request` qui, par défaut, est une instance de [[yii\web\Request]]. +Dans cette section, nous décrivons comment utiliser ce composant dans vos applications. + ## Paramètres de requête -Pour obtenir les paramètres de requête, vous pouvez appeler les méthodes [[yii\web\Request::get()|get()]] et [[yii\web\Request::post()|post()]] du composant `request` component. Elles retournent les valeurs de `$_GET` et `$_POST`, respectivement. Pas exemple : +Pour obtenir les paramètres de requête, vous pouvez appeler les méthodes [[yii\web\Request::get()|get()]] et [[yii\web\Request::post()|post()]] du composant `request` component. +Elles retournent les valeurs de `$_GET` et `$_POST`, respectivement. Pas exemple : ```php $request = Yii::$app->request; @@ -30,9 +34,13 @@ $name = $request->post('name', ''); // équivalent à : $name = isset($_POST['name']) ? $_POST['name'] : ''; ``` -> Info: plutôt que d'accéder directement à `$_GET` et `$_POST` pour récupérer les paramètres de requête, il est recommandé de les obtenir via le composant `request` comme indiqué ci-dessus. Cela rend l'écriture des tests plus facile parce que vous pouvez créer un simulacre de composant request avec des données de requête factices. +> Info: plutôt que d'accéder directement à `$_GET` et `$_POST` pour récupérer les paramètres de requête, il est recommandé de les obtenir via le composant `request` comme indiqué ci-dessus. +Cela rend l'écriture des tests plus facile parce que vous pouvez créer un simulacre de composant 'request' avec des données de requête factices. + + +Lorsque vous mettez en œuvre des [API pleinement REST](rest-quick-start.md), vous avez souvent besoin de récupérer les paramètres qui sont soumis via les [méthodes de requête](#request-methods) PUT, PATCH ou autre . +Vous pouvez obtenir ces paramètres en appelant la méthode [[yii\web\Request::getBodyParam()]]. par exemple : -Lorsque vous mettez en œuvre des [API pleinement REST](rest-quick-start.md), vous avez souvent besoin de récupérer les paramètres qui sont soumis via les [méthodes de requête](#request-methods) PUT, PATCH ou autre . Vous pouvez obtenir ces paramètres en appelant la méthode [[yii\web\Request::getBodyParam()]]. par exemple : ```php $request = Yii::$app->request; @@ -44,13 +52,16 @@ $params = $request->bodyParams; $param = $request->getBodyParam('id'); ``` -> Info: à la différence des paramètres de `GET`, les paramètres soumis via `POST`, `PUT`, `PATCH` etc. sont envoyés dans le corps de la requête. Le composant `request` analyse ces paramètres lorsque vous y accédez via les méthodes décrites ci-dessus. Vous pouvez personnaliser la manière dont ces paramètres sont analysés en configurant la propriété [[yii\web\Request::parsers]]. +> Info: à la différence des paramètres de `GET`, les paramètres soumis via `POST`, `PUT`, `PATCH` etc. sont envoyés dans le corps de la requête. +Le composant `request` analyse ces paramètres lorsque vous y accédez via les méthodes décrites ci-dessus. +Vous pouvez personnaliser la manière dont ces paramètres sont analysés en configurant la propriété [[yii\web\Request::parsers]]. ## Méthodes de requête -Vous pouvez obtenir la méthode HTTP utilisée par la requête courante via l'expression `Yii::$app->request->method`. Un jeu entier de propriétés booléennes est également fourni pour que vous puissiez déterminer le type de la méthode courante. Par exemple : -For example, +Vous pouvez obtenir la méthode HTTP utilisée par la requête courante via l'expression `Yii::$app->request->method`. +Un jeu entier de propriétés booléennes est également fourni pour que vous puissiez déterminer le type de la méthode courante. Par exemple : + ```php $request = Yii::$app->request; @@ -67,17 +78,21 @@ Le composant `request` fournit plusieurs manières d'inspecter l'URL couramment En supposant que l'URL requise soit `http://example.com/admin/index.php/product?id=100`, vous pouvez obtenir différentes parties de cette URL comme c'est résumé ci-dessous : + * [[yii\web\Request::url|url]]: retourne`/admin/index.php/product?id=100`, qui est l'URL sans la partie hôte. * [[yii\web\Request::absoluteUrl|absoluteUrl]]: retourne `http://example.com/admin/index.php/product?id=100`, qui est l'URL complète y compris la partie hôte. * [[yii\web\Request::hostInfo|hostInfo]]: retourne `http://example.com`, qui est la partie hôte de l'URL. -* [[yii\web\Request::pathInfo|pathInfo]]: retourne `/product`, qui est la partie après le script d'entrée et avant le point d'interrogation (chaîne de requête). +* [[yii\web\Request::pathInfo|pathInfo]]: retourne `/product`, qui est la partie après le script d'entrée +et avant le point d'interrogation (chaîne de requête). * [[yii\web\Request::queryString|queryString]]: retourne `id=100`, qui est la partie après le point d'interrogation. -* [[yii\web\Request::baseUrl|baseUrl]]: retourne `/admin`, qui est la partie après l'hôte et avant le nom du script d'entrée. +* [[yii\web\Request::baseUrl|baseUrl]]: retourne `/admin`, qui est la partie après l'hôte +et avant le nom du script d'entrée. * [[yii\web\Request::scriptUrl|scriptUrl]]: retourne `/admin/index.php`, qui set l'URL sans le chemin et la chaîne de requête. * [[yii\web\Request::serverName|serverName]]: retourne `example.com`, qui est le nom d'hôte dans l'URL. * [[yii\web\Request::serverPort|serverPort]]: retourne 80, qui est le numéro de port utilisé par le serveur Web. + ## Enntêtes HTTP Vous pouvez obtenir les entêtes HTTP via la [[yii\web\HeaderCollection|collection d'entêtes]] qui est retournée par la propriété [[yii\web\Request::headers]]. Par exemple : @@ -92,22 +107,96 @@ $accept = $headers->get('Accept'); if ($headers->has('User-Agent')) { /* il existe un entête User-Agent */ } ``` + Le composant `request` fournit aussi la prise en charge de l'accès rapide à quelques entêtes couramment utilisés. Cela inclut : * [[yii\web\Request::userAgent|userAgent]]: retourne la valeur de l'entête `User-Agent`. * [[yii\web\Request::contentType|contentType]]: retourne la valeur de l'entête `Content-Type` qui indique le type MIME des données dans le corps de la requête. -* [[yii\web\Request::acceptableContentTypes|acceptableContentTypes]]: retourne les types MIME acceptés par l'utilisateur. Les types retournés sont classés par ordre de score de qualité. Les types avec les plus hauts scores sont retournés en premier. -* [[yii\web\Request::acceptableLanguages|acceptableLanguages]]: retourne les langues acceptées par l'utilisateur. Les langues retournées sont classées par niveau de préférence. Le premier élément représente la langue préférée. Si votre application prend en charge plusieurs langues et que vous voulez afficher des pages dans la langue préférée de l'utilisateur, vous pouvez utiliser la méthode de négociation de la langue [[yii\web\Request::getPreferredLanguage()]]. -Cette méthode accepte une liste des langues prises en charge par votre application, la compare avec les [[yii\web\Request::acceptableLanguages (langues acceptées)|acceptableLanguages]], et retourne la langue la plus appropriée. +* [[yii\web\Request::acceptableContentTypes|acceptableContentTypes]]: retourne les types MIME acceptés par l'utilisateur. +Les types retournés sont classés par ordre de score de qualité. Les types avec les plus hauts scores sont retournés en premier. +* [[yii\web\Request::acceptableLanguages|acceptableLanguages]]: retourne les langues acceptées par l'utilisateur. +Les langues retournées sont classées par niveau de préférence. +Le premier élément représente la langue préférée. Si votre application prend en charge plusieurs langues et que vous voulez afficher des pages dans la langue préférée de l'utilisateur, vous pouvez utiliser la méthode de négociation de la langue [[yii\web\Request::getPreferredLanguage()]]. +Cette méthode accepte une liste des langues prises en charge par votre application, la compare avec les [[yii\web\Request::acceptableLanguages (langues acceptées)|acceptableLanguages]], + et retourne la langue la plus appropriée. + + +> Tip: vous pouvez également utiliser le filtre [[yii\filters\ContentNegotiator|ContentNegotiator]] pour déterminer dynamiquement quel type de contenu +et quelle langue utiliser dans la réponse. +Le filtre met en œuvre la négociation de contenu en plus des propriétés +et méthodes décrites ci-dessus. -> Tip: vous pouvez également utiliser le filtre [[yii\filters\ContentNegotiator|ContentNegotiator]] pour déterminer dynamiquement quel type de contenu et quelle langue utiliser dans la réponse. Le filtre met en œuvre la négociation de contenu en plus des propriétés et méthodes décrites ci-dessus. ## Informations sur le client -Vous pouvez obtenir le nom d'hôte et l'adresse IP de la machine cliente via [[yii\web\Request::userHost|userHost]] et [[yii\web\Request::userIP|userIP]], respectivement. Par exemple : +Vous pouvez obtenir le nom d'hôte et l'adresse IP de la machine cliente via [[yii\web\Request::userHost|userHost]] +et [[yii\web\Request::userIP|userIP]], respectivement. +Par exemple : + ```php $userHost = Yii::$app->request->userHost; $userIP = Yii::$app->request->userIP; + +## Mandataires de confiance et entêtes + +Dans la section précédente, vous avez vu comment obtenir des informations sur l'utilisateur comme le nom d'hôte et l'adresse IP. +Cela fonctionne sans aucune configuration complémentaire dans une configuration normale dans laquelle une unique serveur Web est utilisé pour servir le site. +Cependant, si votre application s'exécute derrière un mandataire inverse, vous devez compléter la configuration pour retrouver ces informations car le client direct est désormais le mandataire +et l'adresse IP de l'utilisateur est passée à l'application Yii par une entête établie par le mandataire. + + +Vous ne devez pas faire confiance aveuglément aux entêtes fournies par un mandataire sauf si vous faites explicitement confiance à ce mandataire. +Depuis sa version 2.0.13, Yii prend en charge la configuration des mandataires de confiance via les propriétés +[[yii\web\Request::trustedHosts|trustedHosts]], +[[yii\web\Request::secureHeaders|secureHeaders]], +[[yii\web\Request::ipHeaders|ipHeaders]] and +[[yii\web\Request::secureProtocolHeaders|secureProtocolHeaders]] +du composant `request`. + +Ce qui suit est la configuration d'une requête pour une application qui s'exécute derrière une tableau de mandataires inverses +situés dans le réseau IP `10.0.2.0/24` IP network: + +```php +'request' => [ + // ... + 'trustedHosts' => [ + '10.0.2.0/24', + ], +], +``` + +L'adresse IP est envoyée par défaut par le mandataire dans l'entête `X-Forwarded-For` , et le protocole (`http` ou `https`) est envoyé dans `X-Forwarded-Proto`. + +Dans le cas où vos mandataires utilisent différentes entêtes, vous pouvez utiliser la configuration de la requête pour les ajuster, p. ex. : + +```php +'request' => [ + // ... + 'trustedHosts' => [ + '10.0.2.0/24' => [ + 'X-ProxyUser-Ip', + 'Front-End-Https', + ], + ], + 'secureHeaders' => [ + 'X-Forwarded-For', + 'X-Forwarded-Host', + 'X-Forwarded-Proto', + 'X-Proxy-User-Ip', + 'Front-End-Https', + ], + 'ipHeaders' => [ + 'X-Proxy-User-Ip', + ], + 'secureProtocolHeaders' => [ + 'Front-End-Https' => ['on'] + ], +], +``` + +Avec la configuration précédente, toutes les entêtes listées dans `secureHeaders` sont filtrées de la requête à l'exception des entêtes `X-ProxyUser-Ip` et `Front-End-Https` pour le cas où la requête est élaborée par le mandataire. +Dans un tel cas, le précédent est utilisé pour retrouver l'adresse IP de l'utilisateur comme configuré dans `ipHeaders` et le dernier est utilisé pour déterminer le résultat de [[yii\web\Request::getIsSecureConnection()]]. + ``` diff --git a/docs/guide-fr/runtime-responses.md b/docs/guide-fr/runtime-responses.md index 7768416e045..bbc13fab839 100644 --- a/docs/guide-fr/runtime-responses.md +++ b/docs/guide-fr/runtime-responses.md @@ -3,14 +3,16 @@ Réponses Quand une application a terminé la prise en charge d'une [requête](runtime-requests.md), elle génère un objet [[yii\web\Response|response]] et l'envoie à l'utilisateur final. L'objet `response` contient des informations telles que le code d'état HTTP, les entêtes HTTP et le corps. Le but ultime du développement d'applications Web est essentiellement du construire de tels objets `response` pour des requêtes variées. -Dans la plupart des cas, vous devez travailler avec le [composant d'application](structure-application-components.md) `response` qui, par défaut, est une instance de [[yii\web\Response]]. Néanmoins, Yii vous permet également de créer vos propres objets `response` et de les envoyer à l'utilisateur final comme nous l'exliquons dans ce qui suit. +Dans la plupart des cas, vous devez travailler avec le [composant d'application](structure-application-components.md) `response` qui, par défaut, est une instance de [[yii\web\Response]]. Néanmoins, Yii vous permet également de créer vos propres objets `response` et de les envoyer à l'utilisateur final comme nous l'expliquons dans ce qui suit. -Dans cette section, nous décrivons comment composer et enovoyer des réponses à l'utilisateur final. +Dans cette section, nous décrivons comment composer et envoyer des réponses à l'utilisateur final. ## Code d'état -Une de première chose que vous devez faire lorsque vous construisez une réponse est de déclarer si la requête a été correctement prise en charge ou pas. Cela se fait en définissant la propriété [[yii\web\Response::statusCode (code d'état)]] qui peut prendre un des [code d'état HTTP](https://tools.ietf.org/html/rfc2616#section-10) valides. Par exemple, pour indiquer que la requête a été prise en charge avec succès, vous pouvez définir le code à 200, comme ceci : +Une des premières choses que vous devez faire lorsque vous construisez une réponse est de déclarer si la requête a été correctement prise en charge ou pas. Cela se fait en définissant la propriété +[[yii\web\Response::statusCode|code d'état]] +qui peut prendre un des [codes d'état HTTP](https://tools.ietf.org/html/rfc2616#section-10) valides. Par exemple, pour indiquer que la requête a été prise en charge avec succès, vous pouvez définir le code à 200, comme ceci : ```php Yii::$app->response->statusCode = 200; @@ -158,6 +160,7 @@ Dans des endroits autres que les méthodes d'action, vous devez appeler la méth Lorsque la requête courante est une requête AJAX, l'envoi d'un entête `Location` ne provoque pas automatiquement une redirection du navigateur. Pour pallier ce problème, la méthode [[yii\web\Response::redirect()]] définit un entête `X-Redirect` avec l'URL de redirection comme valeur. Du côté client, vous pouvez écrire un code JavaScript pour lire l'entête et rediriger le navigateur sur l'URL transmise. > Info: Yii est fourni avec un fichier JavaScript `yii.js` qui fournit un jeu d'utilitaires JavaScript, y compris l'utilitaire de redirection basé sur l'entête `X-Redirect`. Par conséquent, si vous utilisez ce fichier JavaScript (en enregistrant le paquet de ressources [[yii\web\YiiAsset]] ), vous n'avez rien à écrire pour prendre en charge la redirection AJAX. +De l'information complémentaire sur `yii.js` est disponible à la [section Scripts client](output-client-scripts.md#yii.js). ## Envoi de fichiers diff --git a/docs/guide-fr/runtime-routing.md b/docs/guide-fr/runtime-routing.md index 4cba00384ff..310e4695d8c 100644 --- a/docs/guide-fr/runtime-routing.md +++ b/docs/guide-fr/runtime-routing.md @@ -1,13 +1,23 @@ Routage et création d'URL ========================= -Lorsqu'une application Yii commence à traiter une URL objet d'une requête, sa première étape consiste à analyser cette URL pour la résoudre en une [route](structure-controllers.md#routes). La route est ensuite utilisée pour instancier l'[action de contrôleur](structure-controllers.md) correspondante pour la prise en charge de la requête. Ce processus est appelé *routage*. +Lorsqu'une application Yii commence à traiter une URL objet d'une requête, sa première étape consiste à analyser cette URL +pour la résoudre en une [route](structure-controllers.md#routes). +La route est ensuite utilisée pour instancier l'[action de contrôleur](structure-controllers.md) correspondante pour la prise en charge de la requête. Ce processus est appelé *routage*. -Le processus inverse du routage, qui consiste à créer une URL à partir d'une route et des paramètres associés de la requête, est appelé *création d'URL*. Lorsque l'URL créée est ensuite requise, le processus de routage est capable de la résoudre en la route originale avec les paramètres de requête. +Le processus inverse du routage, qui consiste à créer une URL à partir d'une route et des paramètres associés de la requête, +est appelé *création d'URL*. Lorsque l'URL créée est ensuite requise, le processus de routage est capable de la résoudre en la route originale + avec les paramètres de requête. -L'élément central en charge du routage et de la création d'URL est le [[yii\web\UrlManager|gestionnaire d'URL]], qui est enregistré en tant que [composant d'application](structure-application-components.md) sous le nom `urlManager`. Le [[yii\web\UrlManager|gestionnaire d'URL]] fournit la méthode [[yii\web\UrlManager::parseRequest()|parseRequest()]] pour analyser une requête entrante et la résoudre en une route et les paramètres de requête associés, et la méthode [[yii\web\UrlManager::createUrl()|createUrl()]] pour créer une URL en partant d'une route avec ses paramètres de requête associés. +L'élément central en charge du routage et de la création d'URL est le [[yii\web\UrlManager|gestionnaire d'URL]], qui est enregistré en tant que [composant d'application](structure-application-components.md) sous le nom `urlManager`. +Le [[yii\web\UrlManager|gestionnaire d'URL]] fournit la méthode [[yii\web\UrlManager::parseRequest()|parseRequest()]] pour analyser une requête entrante et la résoudre en +une route et les paramètres de requête associés, +et la méthode [[yii\web\UrlManager::createUrl()|createUrl()]] pour +créer une URL en partant d'une route avec ses paramètres de requête associés. -En configurant le composant `urlManager` dans la configuration de l'application, vous pouvez laisser votre application reconnaître les formats d'URL arbitraires sans modifier le code existant de votre application. Par exemple, vous pouvez utiliser le code suivant pour créer une URL pour l'action `post/view` : +En configurant le composant `urlManager` dans la configuration de l'application, vous pouvez laisser votre application reconnaître les formats d'URL arbitraires sans modifier le code existant de votre application. +Par exemple, vous pouvez utiliser le code suivant pour créer une URL pour l'action `post/view` : + ```php use yii\helpers\Url; @@ -16,7 +26,8 @@ use yii\helpers\Url; $url = Url::to(['post/view', 'id' => 100]); ``` -Selon la configuration de `urlManager`, l'URL créée peut ressenmbler à l'une des URL suivantes (ou autre formats). Et si l'URL est requise plus tard, elle sera toujours analysée pour revenir à la route originale et aux valeurs des paramètres de la requête. +Selon la configuration de `urlManager`, l'URL créée peut ressembler à l'une des URL suivantes (ou autre formats). +Et si l'URL est requise plus tard, elle sera toujours analysée pour revenir à la route originale et aux valeurs des paramètres de la requête. ``` /index.php?r=post%2Fview&id=100 @@ -27,37 +38,70 @@ Selon la configuration de `urlManager`, l'URL créée peut ressenmbler à l'une ## Formats d'URL -Le [[yii\web\UrlManager|gestionnaire d'URL]] prend en charge deux formats d'URL : le format d'URL par défaut et le format d'URL élégantes. +Le [[yii\web\UrlManager|gestionnaire d'URL]] prend en charge deux formats d'URL : + +- le format d'URL par défaut, +- le format d'URL élégantes. -Le format d'URL par défaut utilise un paramètre de requête nommé `r` qui représente la route et les paramètres de requête normaux associés à la route. Par exemple, l'URL `/index.php?r=post/view&id=100` represente la route `post/view` et le paramètre de requête `id` dont la valeur est 100. Le format d'URL par défaut ne requiert aucune configuration du [[yii\web\UrlManager|gestionnaire d'URL] et fonctionne dans toutes les configurations de serveur Web. +Le format d'URL par défaut utilise un [[yii\web\UrlManager::$routeParam|paramètre de requête]] nommé `r` qui représente la route et les paramètres de requête normaux associés à la route. +Par exemple, l'URL `/index.php?r=post/view&id=100` represente la route `post/view` et le paramètre de requête `id` dont la valeur est 100. +Le format d'URL par défaut ne requiert aucune configuration du [[yii\web\UrlManager|gestionnaire d'URL] +et fonctionne dans toutes les configurations de serveur Web. -Le format d'URL élégantes utilise le chemin additionnel qui suit le nom du script d'entrée pour représenter la route et les paramètres de requête associés. Par exemple, le chemin additionnel dans l'URL `/index.php/post/100` est `/post/100` qui, avec une [[yii\web\UrlManager::rules|règle d'URL]] appropriée, peut représenter la route `post/view` et le paramètre des requête `id` avec une valeur de 100 . Pour utiliser le format d'URL élégantes, vous devez définir un jeu de [[yii\web\UrlManager::rules|règles d'URL]] en cohérence avec les exigences réelles sur la présentation d'une URL. +Le format d'URL élégantes utilise le chemin additionnel qui suit le nom du script d'entrée pour représenter la route et les paramètres de requête associés. +Par exemple, le chemin additionnel dans l'URL `/index.php/post/100` est `/post/100` qui, avec une [[yii\web\UrlManager::rules|règle d'URL]] appropriée, peut représenter la route `post/view` et le paramètre des requête `id` avec une valeur de 100 . +Pour utiliser le format d'URL élégantes, +vous devez définir un jeu de [[yii\web\UrlManager::rules|règles d'URL]] +en cohérence avec les exigences réelles sur la présentation d'une URL. -Vous pouvez passer d'un format d'URL à l'autre en inversant la propriété [[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] du [[yii\web\UrlManager|gestionnaire d'URL]] sans changer quoi que ce soit au code de votre application. +Vous pouvez passer d'un format d'URL à l'autre en inversant la propriété [[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] du [[yii\web\UrlManager|gestionnaire d'URL]] +sans changer quoi que ce soit au code de votre application. ## Routage -Le routage se fait en deux étapes. Dans la première étape, la requête entrante est analysée et résolue en une route et les paramètres de requête associés. Dans la seconde étape, l'[action de contrôleur](structure-controllers.md#actions) correspondant à la route analysée est créée pour prendre la requête en charge. +Le routage se fait en deux étapes : -Lors de l'utilisation du format d'URL par défaut, la résolution d'une requête en route est aussi simple que d'obtenir le paramètre nommé `r` de la méthode `GET`. +- La requête entrante est analysée et résolue en une route et les paramètres de requête associés. +- L'[action de contrôleur](structure-controllers.md#actions) +correspondant à la route analysée est créée pour prendre la requête en charge. -Lors de l'utilisation du format d'URL élégantes, le [[yii\web\UrlManager|gestionnaire d'URL] examine les [[yii\web\UrlManager::rules|règles d'URL]] enregistrées pour trouver une règle qui correspond et résoudre la requête en une route. Si une telle règle n'est pas trouvée, une exception [[yii\web\NotFoundHttpException]] est levée. +Lors de l'utilisation du format d'URL par défaut, +la résolution d'une requête en route est aussi simple que d'obtenir le paramètre nommé `r` de la méthode `GET`. -Une fois que la requête est résolue en une route, il est temps de créer l'action de contrôleur identifiée par la route. La route est éclatée en de multiples parties par des barres oblique de division. Par exemple, `site/index` est éclatée en `site` et `index`. Chacune des parties est considérée comme un identifiant qui peut faire référence à un module, un contrôleur ou une action. En partant de la première partie dans la route, l'application entreprend les étapes suivantes pour créer un module (s'il en existe un), un contrôleur et une action. +Lors de l'utilisation du format d'URL élégantes, le [[yii\web\UrlManager|gestionnaire d'URL] examine les [[yii\web\UrlManager::rules|règles d'URL]] enregistrées pour trouver une règle qui correspond et résoudre la requête en une route. +Si une telle règle n'est pas trouvée, une exception [[yii\web\NotFoundHttpException]] +est levée. + +Une fois que la requête est résolue en une route, il est temps de créer l'action de contrôleur identifiée par la route. +La route est éclatée en de multiples parties par des barres obliques de division. +Par exemple, `site/index` est éclatée en `site` et `index`. +Chacune des parties est considérée comme un identifiant qui peut faire référence à un module, un contrôleur ou une action. +En partant de la première partie dans la route, l'application entreprend les étapes suivantes pour créer un module (s'il en existe un), un contrôleur et une action : 1. Définit l'application comme étant le module courant. -2. Vérifie si la [[yii\base\Module::controllerMap|table de mise en correspondance des contrôleurs]] du module courant contient l'identifiant courant. Si c'est le cas, un objet *controller* est créé en respectant la configuration du contrôleur trouvé dans la table de mise en correspondance, et on passe à l'étape 5 pour prendre en compte le reste de la route. -3. Vérifie si l'identifiant fait référence à un module listé dans la propriété [[yii\base\Module::modules|modules]] du module courant. Si c'est le cas, un module est créé en respectant la configuration trouvée dans la liste des modules et on passe à l'étape 2 pour prendre en compte le reste de la route dans le contexte du nouveau module. -4. Traite l'identifiant comme un [identifiant de contrôleur](structure-controllers.md#controller-ids), crée un objet *controller* et passe à l'étape suivante avec le reste de la route. -5. Le contrôleur recherche l'identifiant courant dans sa [[yii\base\Controller::actions()|table de mise en correspondance des actions]]. s'il le trouve, il crée une action respectant la configuration trouvée dans la table de mise en correspondance. Autrement, le contrôleur essaye de créer une action en ligne dont le nom de méthode correspond à l' [identifiant d'action](structure-controllers.md#action-ids) courant. +2. Vérifie si la [[yii\base\Module::controllerMap|table de mise en correspondance des contrôleurs]] du module courant contient l'identifiant courant. +Si c'est le cas, un objet *controller* est créé en respectant la configuration du contrôleur trouvé dans la table de mise en correspondance, +et on passe à l'étape 5 pour prendre en compte le reste de la route. +3. Vérifie si l'identifiant fait référence à un module listé dans la propriété [[yii\base\Module::modules|modules]] du module courant. +Si c'est le cas, un module est créé en respectant la configuration trouvée dans la liste des modules et on passe à l'étape 2 +pour prendre en compte le reste de la route dans le contexte du nouveau module. +4. Traite l'identifiant comme un [identifiant de contrôleur](structure-controllers.md#controller-ids), crée un objet *controller* +et passe à l'étape suivante avec le reste de la route. +5. Le contrôleur recherche l'identifiant courant dans sa [[yii\base\Controller::actions()|table de mise en correspondance des actions]]. S'il le trouve, il crée une action respectant la configuration trouvée dans la table de mise en correspondance. +Autrement, le contrôleur essaye de créer une action en ligne dont le nom de méthode correspond à l' [identifiant d'action](structure-controllers.md#action-ids) courant. + Si une erreur se produit dans l'une des étapes décrites ci-dessus, une exception [[yii\web\NotFoundHttpException]] est levée, indiquant l'échec du processus de routage. + ### Route par défaut -Quand une requête est analysée et résolue en une route vide, la route dite *route par défaut* est utilisée à sa place. Par défaut, la route par défaut est `site/index`, qui fait référence à l'action `index` du contrôleur `site`. Vous pouvez la personnaliser en configurant la propriété [[yii\web\Application::defaultRoute|defaultRoute]] de l'application dans la configuration de l'application comme indiqué ci-dessous : +Quand une requête est analysée et résolue en une route vide, la route dite *route par défaut* est utilisée à sa place. +Par défaut, la route par défaut est `site/index`, qui fait référence à l'action `index` du contrôleur `site`. +Vous pouvez la personnaliser en configurant la propriété [[yii\web\Application::defaultRoute|defaultRoute]] de l'application dans la configuration de l'application comme indiqué ci-dessous : + ```php [ @@ -66,10 +110,18 @@ Quand une requête est analysée et résolue en une route vide, la route dite *r ]; ``` +De façon similaire à la route par défaut de l'application, il existe aussi une route par défaut pour les modules. +Ainsi s'il existe un module `user` (utilisateur) et que la requête est résolue en la route `user`, la propriété [[yii\base\Module::defaultRoute|defaultRoute]] du module est utilisée pour déterminer le contrôleur. +Par défaut, le nom du contrôleur est `default`. Si aucune action n'est spécifiée dans la propriété [[yii\base\Module::defaultRoute|defaultRoute]], +la propriété [[yii\base\Controller::defaultAction|defaultAction]] du contrôleur est utilisée pour déterminer l'action. +Dans cet exemple, la route complète serait `user/default/index`. + ### La route `attrape-tout` -Parfois, vous désirez mettre votre application Web en mode maintenance temporairement et afficher la même page d'information pour toutes les requêtes. Il y a plusieurs moyens de faire cela. L'une des manières les plus simples est de configurer la propriété [[yii\web\Application::catchAll]] dans la configuration de l'application comme indiqué ci-dessous : +Parfois, vous désirez mettre votre application Web en mode maintenance temporairement +et afficher la même page d'information pour toutes les requêtes. Il y a plusieurs moyens de faire cela. +L'une des manières les plus simples est de configurer la propriété [[yii\web\Application::catchAll]] dans la configuration de l'application comme indiqué ci-dessous : ```php [ @@ -80,14 +132,17 @@ Parfois, vous désirez mettre votre application Web en mode maintenance temporai Avec la configuration ci-dessus, l'action `site/offline` est utilisée pour prendre toutes les requêtes entrantes en charge. -La propriété `catchAll` accepte un tableau dont le premier élément spécifie une route et le reste des éléments des couples clé-valeur pour les paramètres [liés à l'action](structure-controllers.md#action-parameters). +La propriété `catchAll` accepte un tableau dont le premier élément spécifie une route +et le reste des éléments des couples clé-valeur pour les paramètres [liés à l'action](structure-controllers.md#action-parameters). -> Info: le paneau de débogage de l'environnement de développement ne fonctionne pas lorsque cette propriété est activée. +> Info: le [panneau de débogage] ](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide/README.md) de l'environnement de développement + ne fonctionne pas lorsque cette propriété est activée. ## Création d'URL -Yii fournit une méthode d'aide [[yii\helpers\Url::to()]] pour créer différentes sortes d'URL à partir de routes données et de leurs paramètres de requête associés. Par exemple : +Yii fournit une méthode d'aide [[yii\helpers\Url::to()]] pour créer différentes sortes d'URL à partir de routes données et de leurs paramètres de requête associés. +Par exemple : ```php use yii\helpers\Url; @@ -104,19 +159,25 @@ echo Url::to(['post/view', 'id' => 100, '#' => 'content']); // crée une URL absolue : http://www.example.com/index.php?r=post%2Findex echo Url::to(['post/index'], true); -// crée une URL absolue en utilisant le schéam https : https://www.example.com/index.php?r=post%2Findex +// crée une URL absolue en utilisant le schéma https : https://www.example.com/index.php?r=post%2Findex echo Url::to(['post/index'], 'https'); ``` -Notez que dans l'exemple ci-dessus, nous supposons que le format d'URL est le format par défaut. Si le format d'URL élégantes est activé, les URL créées sont différentes et respectent les [[yii\web\UrlManager::rules|règles d'URL]] en cours d'utilisation. +Notez que dans l'exemple ci-dessus, nous supposons que le format d'URL est le format par défaut. +Si le format d'URL élégantes est activé, les URL créées sont différentes et respectent les [[yii\web\UrlManager::rules|règles d'URL]] en cours d'utilisation. -La route passée à la méthode [[yii\helpers\Url::to()]] est sensible au contexte. Elle peut être soit *relative*, soit *absolue* et normalisée en respect des règles suivantes : +La route passée à la méthode [[yii\helpers\Url::to()]] est sensible au contexte. +Elle peut être soit *relative*, soit *absolue* et normalisée en respect des règles suivantes : - Si la route est une chaîne vide, la [[yii\web\Controller::route|route]] couramment requise est utilisée ; -- Si la route ne contient aucune barre oblique de division, elle est considérée comme un identifiant d'action du contrôleur courant et est préfixée par la valeur de l'identifiant [[\yii\web\Controller::uniqueId|uniqueId]] du contrôleur courant ; -- Si la route n'a pas de barre oblique de division, elle est considérée comme une route relative au module courant et préfixée par la valeur de l'identifiant [[\yii\base\Module::uniqueId|uniqueId]] du module courant. +- Si la route ne contient aucune barre oblique de division, elle est considérée comme un identifiant d'action du contrôleur courant +et est préfixée par la valeur de l'identifiant [[\yii\web\Controller::uniqueId|uniqueId]] du contrôleur courant ; +- Si la route n'a pas de barre oblique de division en tête, elle est considérée comme une route relative au module courant +et préfixée par la valeur de l'identifiant [[\yii\base\Module::uniqueId|uniqueId]] du module courant. + +À partir de la version 2.0.2, vous pouvez spécifier une route en terme d'[alias](concept-aliases.md). Si c'est le cas, +l'alias est d'abord converti en la route réelle qui est ensuite transformée en route absolue dans le respect des règles précédentes. -À partir de la version 2.0.2, vous pouvez spécifier une route en terme d'[alias](concept-aliases.md). Si c'est le cas, l'alias est d'abord converti en la route réelle qui est ensuite transformée en route absolue dans le respect des règles précédentes. Par exemple, en supposant que le module courant est `admin` et que le contrôleur courant est `post`, @@ -139,9 +200,13 @@ echo Url::to(['/post/index']); echo Url::to(['@posts']); ``` -La méthode [[yii\helpers\Url::to()]] est mise en œuvre en appelant les méthodes [[yii\web\UrlManager::createUrl()|createUrl()]] et [[yii\web\UrlManager::createAbsoluteUrl()|createAbsoluteUrl()]] du [[yii\web\UrlManager|gestionnaire d'URL]]. Dans les quelques sous-sections suivantes, nous expliquons comment configurer le [[yii\web\UrlManager|gestionnaire d'URL]] pour personnaliser le format des URL créées. +La méthode [[yii\helpers\Url::to()]] est mise en œuvre en appelant les méthodes [[yii\web\UrlManager::createUrl()|createUrl()]] +et [[yii\web\UrlManager::createAbsoluteUrl()|createAbsoluteUrl()]] +du [[yii\web\UrlManager|gestionnaire d'URL]]. +Dans les quelques sous-sections suivantes, nous expliquons comment configurer le [[yii\web\UrlManager|gestionnaire d'URL]] pour personnaliser le format des URL créées. -La méthode [[yii\helpers\Url::to()]] prend aussi en charge la création d'URL qui n'ont PAS de relation avec des routes particulières. Au lieu de passer un tableau comme premier paramètre, vous devez, dans ce cas, passer une chaîne de caractères. Par exemple : +La méthode [[yii\helpers\Url::to()]] prend aussi en charge la création d'URL qui n'ont **pas** de relation avec des routes particulières. +Au lieu de passer un tableau comme premier paramètre, vous devez, dans ce cas, passer une chaîne de caractères. Par exemple : ```php use yii\helpers\Url; @@ -157,7 +222,8 @@ echo Url::to('@example'); echo Url::to('/images/logo.gif', true); ``` -En plus de la méthode `to()`, la classe d'aide [[yii\helpers\Url]] fournit aussi plusieurs méthode pratiques de création d'URL. Par exemple : +En plus de la méthode `to()`, la classe d'aide [[yii\helpers\Url]] fournit aussi plusieurs méthode pratiques de création d'URL. +Par exemple : ```php use yii\helpers\Url; @@ -169,10 +235,10 @@ echo Url::home(); echo Url::base(); // l'URL canonique de l'URL couramment requise -// see https://en.wikipedia.org/wiki/Canonical_link_element +// voir https://en.wikipedia.org/wiki/Canonical_link_element echo Url::canonical(); -// mémories l'URL couramment requise et la retrouve dans les requêtes subséquentes +// mémorise l'URL couramment requise et la retrouve dans les requêtes subséquentes Url::remember(); echo Url::previous(); ``` @@ -197,23 +263,47 @@ Pour utiliser les URL élégantes, configurez le composant `urlManager` dans la ] ``` -La propriété [[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] est obligatoire car elle active/désactive le format d'URL élégantes. Le reste des propriétés est facultatif. Néanmoins, leur configuration montrée plus haut est couramment utilisée. +La propriété [[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] est obligatoire car elle active/désactive le format d'URL élégantes. Le reste des propriétés est facultatif. +Néanmoins, leur configuration montrée plus haut est couramment utilisée. -* [[yii\web\UrlManager::showScriptName|showScriptName]]: cette propriété détermine si le script d'entrée doit être inclus dans l'URL créée. Par exemple, au lieu de créer une URL `/index.php/post/100`, en définissant cette propriété à `false`, l'URL `/post/100` est générée. -* [[yii\web\UrlManager::enableStrictParsing|enableStrictParsing]]: cette propriété détermine si l'analyse stricte est activée . Si c'est le cas, l'URL entrante doit correspondre à au moins une des [[yii\web\UrlManager::rules|règles]] afin d'être traitée comme une requête valide, sinon une exception [[yii\web\NotFoundHttpException]] est levée. Si l'analyse stricte est désactivée, lorsqu'aucune [[yii\web\UrlManager::rules|règle]] ne correspond à l'URL requise, la partie chemin de l'URL est considérée comme étant la route requise. -* [[yii\web\UrlManager::rules|rules]]: cette propriété contient une liste de règles spécifiant comme analyser et créer des URL. C'est la propriété principale avec laquelle vous devez travailler afin de créer des URL dont le format satisfait les exigences particulières de votre application. +* [[yii\web\UrlManager::showScriptName|showScriptName]]: cette propriété détermine si le script d'entrée doit être inclus dans l'URL créée. +Par exemple, au lieu de créer une URL `/index.php/post/100`, +en définissant cette propriété à `false`, l'URL `/post/100` est générée. +* [[yii\web\UrlManager::enableStrictParsing|enableStrictParsing]]: cette propriété détermine si l'analyse stricte est activée . +Si c'est le cas, l'URL entrante doit correspondre à au moins une des [[yii\web\UrlManager::rules|règles]] afin d'être traitée comme une requête valide, sinon une exception [[yii\web\NotFoundHttpException]] est levée. +Si l'analyse stricte est désactivée, lorsqu'aucune +[[yii\web\UrlManager::rules|règle]] ne correspond à l'URL requise, +la partie chemin de l'URL est considérée comme étant la route requise. +* [[yii\web\UrlManager::rules|rules]]: cette propriété contient une liste de règles spécifiant comme analyser et créer des URL. +C'est la propriété principale avec laquelle vous devez travailler afin de créer des URL dont le format satisfait les exigences particulières de votre application. + + +> Note: afin de cacher le nom du script d'entrée dans l'URL créée, en plus de définir la propriété +[[yii\web\UrlManager::showScriptName|showScriptName]] +à `false`, vous pouvez aussi configurer votre serveur Web de manière à ce qu'il puisse identifier correctement quel script PHP doit être exécuté lorsqu'une URL requise n'en précise aucun explicitement. +Si vous utilisez un serveur Apache ou nginx, vous pouvez vous reporter à la configuration recommandée décrite dans la section [Installation](start-installation.md#recommended-apache-configuration). -> Note: afin de cacher le nom du script d'entrée dans l'URL créée, en plus de définir la propriété [[yii\web\UrlManager::showScriptName|showScriptName]] à `false`, vous pouvez aussi configurer votre serveur Web de manière à ce qu'il puisse identifier correctement quel script PHP doit être exécuté lorsqu'une URL requise n'en précise aucun explicitement. Si vous utilisez le serveur Apache, vous pouvez vous reporter à la configuration recommandée décrite dans la section [Installation](start-installation.md#recommended-apache-configuration). ### Règles d'URL -Une règle d'URL est une instance de la classe [[yii\web\UrlRule]] ou de ses classes filles. Chaque règle d'URL consiste en un motif utilisé pour être mis en correspondance avec la partie chemin de l'URL, une route, et quelques paramètres de requête. Une règle d'URL peut être utilisée pour analyser une requête si son motif correspond à l'URL requise. Une règle d'URL peut être utilisée pour créer une URL si sa route et le nom de ses paramètres de requête correspondent à ceux qui sont fournis. +Une règle d'URL est une classe mettant en œuvre l'interface [[yii\web\UrlRuleInterface]], généralement une instance de la classe [[yii\web\UrlRule]]. +Chaque règle d'URL consiste en un motif utilisé pour être mis en correspondance avec la partie chemin de l'URL, une route, et quelques paramètres de requête. +Une règle d'URL peut être utilisée pour analyser une requête si son motif correspond à l'URL requise. +Une règle d'URL peut être utilisée pour créer une URL si sa route et le nom de ses paramètres de requête correspondent à ceux qui sont fournis. Quand le format d'URL élégantes est activé, le [[yii\web\UrlManager|gestionnaire d'URL]] utilise les règles d'URL déclarées dans sa propriété -[[yii\web\UrlManager::rules|rules]] pour analyser les requêtes entrantes et créer des URL. En particulier, pour analyser une requête entrante, le [[yii\web\UrlManager|gestionnaire d'URL]] examine les règles dans l'ordre de leur déclaration et cherche la *première* règle qui correspond à l'URL requise. La règle correspondante est ensuite utilisée pour analyser l'URL et la résoudre en une route et ses paramètres de requête associés. De façon similaire, pour créer une URL, le [[yii\web\UrlManager|gestionnaire d'URL]] cherche la première règle qui correspond à la route donnée et aux paramètres et l'utilise pour créer l'URL. +[[yii\web\UrlManager::rules|rules]] pour analyser les requêtes entrantes et créer des URL. +En particulier, pour analyser une requête entrante, le [[yii\web\UrlManager|gestionnaire d'URL]] examine les règles dans l'ordre de leur déclaration et cherche la *première* règle qui correspond à l'URL requise. +La règle correspondante est ensuite utilisée pour analyser l'URL et la résoudre en une route et ses paramètres de requête associés. +De façon similaire, pour créer une URL, le [[yii\web\UrlManager|gestionnaire d'URL]] cherche la première règle qui correspond à la route donnée et aux paramètres et l'utilise pour créer l'URL. -Vous pouvez configurer la propriété [[yii\web\UrlManager::rules]] sous forme de tableau dont les clés sont les motifs et les valeurs, les routes correspondantes. Chacune des paires motif-route construit une règle d'URL. Par exemple, la configuration des [[yii\web\UrlManager::rules|règles]] suivantes déclare deux règles d'URL. La première correspond à l'URL `posts` et la met en correspondance avec la route `post/index`. La seconde correspond à une URL qui correspond à l'expression régulière `post/(\d+)` et la met en correspondance avec la route `post/view` et le paramètre nommé `id`. + +Vous pouvez configurer la propriété [[yii\web\UrlManager::rules]] sous forme de tableau dont les clés sont les [[yii\web\UrlRule::$pattern|motifs]] +et les valeurs, les [[yii\web\UrlRule::$route|routes]] correspondantes. +Chacune des paires motif-route construit une règle d'URL. +Par exemple, la configuration des [[yii\web\UrlManager::rules|règles]] suivante déclare deux règles d'URL. +La première correspond à l'URL `posts` et la met en correspondance avec la route `post/index`. La seconde correspond à une URL qui correspond à l'expression régulière `post/(\d+)` et la met en correspondance avec la route `post/view` et le paramètre nommé `id`. ```php [ @@ -222,14 +312,17 @@ Vous pouvez configurer la propriété [[yii\web\UrlManager::rules]] sous forme d ] ``` -> Info: le motif dans une règle est utilisé pour correspondre à la partie chemin d'une URL. Par exemple, la partie chemin de `/index.php/post/100?source=ad` est `post/100` (les barres obliques de division de début et de fin sont ignorées) et correspond au motif `post/(\d+)`. +> Info: le motif dans une règle est utilisé pour correspondre à la partie chemin d'une URL. +Par exemple, la partie chemin de `/index.php/post/100?source=ad` est `post/100` (les barres obliques de division de début et de fin sont ignorées) et correspond au motif `post/(\d+)`. + -En plus de déclarer des règles d'URL sous forme de paires motif-route, vous pouvez aussi les déclarer sous forme de tableaux de configuration. Chacun des tableaux de configuration est utilisé pour configurer un simple objet règle d'URL. C'est souvent nécessaire lorsque vous voulez configurer d'autres propriétés d'une règle d'URL. Par exemple : +En plus de déclarer des règles d'URL sous forme de paires motif-route, vous pouvez aussi les déclarer sous forme de tableaux de configuration. +Chacun des tableaux de configuration est utilisé pour configurer un simple objet règle d'URL. +C'est souvent nécessaire lorsque vous voulez configurer d'autres propriétés d'une règle d'URL. Par exemple : ```php -[ - // ...autres règels d'url ... - +'rules' => [ + // ...autres règles d'URL... [ 'pattern' => 'posts', 'route' => 'post/index', @@ -238,16 +331,24 @@ En plus de déclarer des règles d'URL sous forme de paires motif-route, vous po ] ``` -Par défaut, si vous ne spécifiez pas l'option `class` pour une configuration de règle, elle prend la valeur par défaut [[yii\web\UrlRule]]. +Par défaut, si vous ne spécifiez pas l'option `class` pour une configuration de règle, +elle prend la valeur par défaut [[yii\web\UrlRule]] qui est la valeur par défaut définie dans +[[yii\web\UrlManager::$ruleConfig]]. ### Paramètres nommés -Une règle d'URL peut être associée à quelques paramètres de requête nommés qui sont spécifiés dans le motif et respectent le format ``, où `ParamName` spécifie le nom du paramètre et `RegExp` est une expression régulière facultative utilisée pour établir la correspondance avec une valeur de paramètre. Si `RegExp` n'est pas spécifié, cela signifie que la valeur du paramètre doit être une chaîne de caractères sans aucune barre oblique de division. +Une règle d'URL peut être associée à quelques paramètres de requête nommés qui sont spécifiés dans le motif et respectent le format ``, +dans lequel `ParamName` spécifie le nom du paramètre et `RegExp` est une expression régulière facultative utilisée pour établir la correspondance avec une valeur de paramètre. +Si `RegExp` n'est pas spécifié, cela signifie que la valeur du paramètre doit être une chaîne de caractères sans aucune barre oblique de division. + > Note: vous pouvez seulement spécifier des expressions régulières pour les paramètres. La partie restante du motif est considérée être du texte simple. -Lorsqu'une règle est utilisée pour analyser une URL, elle remplit les paramètres associés avec les valeurs des parties de l'URL qui leur correspondent, et ces paramètres sont rendus disponibles dans `$_GET` et plus tard dans le composant d'application `request`. Lorsque la règle est utilisée pour créer une URL, elle prend les valeurs des paramètres fournis et les insère à l'endroit où ces paramètres sont déclarés. +Lorsqu'une règle est utilisée pour analyser une URL, +elle remplit les paramètres associés avec les valeurs des parties de l'URL qui leur correspondent, +et ces paramètres sont rendus disponibles dans `$_GET` et plus tard dans le composant d'application `request`. +Lorsque la règle est utilisée pour créer une URL, elle prend les valeurs des paramètres fournis et les insère à l'endroit où ces paramètres sont déclarés. Prenons quelques exemples pour illustrer comment les paramètres nommés fonctionnent. Supposons que nous ayons déclaré les règles d'URL suivantes : @@ -262,10 +363,13 @@ Prenons quelques exemples pour illustrer comment les paramètres nommés fonctio Lorsque les règles sont utilisées pour analyser des URL : - `/index.php/posts` est analysée et résolue en la route `post/index` en utilisant la deuxième règle ; -- `/index.php/posts/2014/php` est analysée et résolue en la route `post/index`, le paramètre `year` dont la valeur est 2014 et le paramètre `category` dont la valeur est `php` en utilisant la première règle ; -- `/index.php/post/100` est analysée et résolue en la route `post/view` et le paramètre `id` dont la valeur est 100 en utilisant la troisième règle ; +- `/index.php/posts/2014/php` est analysée et résolue en la route `post/index`, le paramètre `year` dont la valeur est 2014 +et le paramètre `category` dont la valeur est `php` en utilisant la première règle ; +- `/index.php/post/100` est analysée et résolue en la route `post/view` +et le paramètre `id` dont la valeur est 100 en utilisant la troisième règle ; - `/index.php/posts/php` provoque la levée d'une exception [[yii\web\NotFoundHttpException]] quand la propriété [[yii\web\UrlManager::enableStrictParsing]] - est définie à `true`, parce qu'elle ne correspond à aucun des motifs. Si [[yii\web\UrlManager::enableStrictParsing]] est définie à `false` (la valeur par défaut), la partie chemin `posts/php` est retournée en tant que route. + est définie à `true`, parce qu'elle ne correspond à aucun des motifs. +Si [[yii\web\UrlManager::enableStrictParsing]] est définie à `false` (la valeur par défaut), la partie chemin `posts/php` est retournée en tant que route. Cela provoque l'exécution de l'action correspondante si elle existe, ou lève une exception [[yii\web\NotFoundHttpException]] autrement. Et quand les règles sont utilisées pour créer des URL : @@ -275,29 +379,41 @@ Et quand les règles sont utilisées pour créer des URL : - `Url::to(['post/view', 'id' => 100, 'source' => 'ad'])` crée `/index.php/post/100?source=ad` en utilisant la troisième règle. Comme le paramètre `source` n'est pas spécifié dans la règle, il est ajouté en tant que paramètre de requête à l'URL créée. - `Url::to(['post/index', 'category' => 'php'])` crée `/index.php/post/index?category=php` en utilisant aucune des règles. - Notez que, aucune des règles n'étant utilisée, l'URL est créée en ajoutant simplement la route en tant que partie chemin et tous les paramètres en tant que partie de la chaîne de requête. + Notez que, aucune des règles n'étant utilisée, l'URL est créée en ajoutant simplement la route en tant que partie chemin +et tous les paramètres en tant que partie de la chaîne de requête. + ### Paramétrage des routes -Vous pouvez inclure les noms des paramètres dans la route d'une règle d'URL. Cela permet à une règle d'URL d'être utilisée pour correspondre à de multiples routes. Par exemple, les règles suivantes incluent les paramètres `controller` et `action` dans les routes. +Vous pouvez inclure les noms des paramètres dans la route d'une règle d'URL. Cela permet à une règle d'URL d'être utilisée pour correspondre à de multiples routes. +Par exemple, les règles suivantes incluent les paramètres `controller` et `action` dans les routes. ```php -[ - '//' => '/', +'rules' => [ + '/create' => '/create', + '//' => '/', '/' => '/view', 's' => '/index', ] ``` -Pour analyser l'URL `/index.php/comment/100/create`, la première règle s'applique et définit le paramètre `controller` comme étant `comment` et le paramètre `action` comme étant `create`. La route `/` est par conséquent résolue comme `comment/create`. +Pour analyser l'URL `/index.php/comment/100/update`, la deuxième règle s'applique et définit le paramètre `controller` +comme étant `comment` et le paramètre `action` comme étant `create`. La route `/` est par conséquent résolue comme `comment/update`. -De façon similaire, pour créer une URL à partir de la route `comment/index`, la troisième règle s'applique, ce qui donne l'URL `/index.php/comments`. +De façon similaire, pour créer une URL à partir de la route `comment/index`, la dernière règle s'applique, ce qui donne l'URL `/index.php/comments`. -> Info: en paramétrant les routes, il est possible de réduire grandement le nombre de règles d'URL, ce qui peut accroître significativement la performance du [[yii\web\UrlManager|gestionnaire d'URL]]. +> Info: en paramétrant les routes, il est possible de réduire grandement le nombre de règles d'URL, +ce qui peut accroître significativement la performance du [[yii\web\UrlManager|gestionnaire d'URL]]. -Par défaut, tous les paramètres déclarés dans une règle sont requis. Si une URL requise ne contient pas un paramètre particulier, ou si une URL est créée sans un paramètre particulier, la règle ne s'applique pas. Pour rendre certains paramètres facultatifs, vous pouvez configurer la propriété [[yii\web\UrlRule::defaults|defaults]] de la règle. Les paramètres listés dans cette propriété sont facultatifs et prennent les valeurs spécifiées lorsqu'elles ne sont pas fournies. +### Valeur par défaut des paramètres -Dans la déclaration suivante d'une règle, les paramètres `page` et `tag` sont tous les deux facultatifs et prennent la valeur 1 et vide, respectivement quand ils ne sont pas fournis. +Par défaut, tous les paramètres déclarés dans une règle sont requis. +Si une URL requise ne contient pas un paramètre particulier, ou si une URL est créée sans un paramètre particulier, la règle ne s'applique pas. +Pour rendre certains paramètres facultatifs, vous pouvez configurer la propriété [[yii\web\UrlRule::defaults|defaults]] de la règle. +Les paramètres listés dans cette propriété sont facultatifs et prennent les valeurs spécifiées lorsqu'elles ne sont pas fournies. + +Dans la déclaration suivante d'une règle, les paramètres `page` et `tag` sont tous les deux facultatifs +et prennent la valeur 1 et vide, respectivement quand ils ne sont pas fournis. ```php [ @@ -319,10 +435,15 @@ La règle ci-dessus peut être utilisée pour analyser ou créer l'une quelconqu Sans les paramètres facultatifs, vous devriez créer quatre règles pour arriver au même résultat. +> Note: si [[yii\web\UrlRule::$pattern|pattern]] (motif) ne contient que des paramètres facultatifs et des barres obliques de division, +le premier paramètre peut être omis seulement si tous les autres paramètres le sont. + ### Règles avec des noms de serveur -Il est possible d'inclure des noms de serveur Web dans le motif d'une règle d'URL. Cela est principalement utilisé lorsque votre application doit se comporter différemment selon le nom du serveur Web. Par exemple, les règles suivantes analysent et résolvent l'URL `http://admin.example.com/login` en la route `admin/user/login` et `http://www.example.com/login` en la route `site/login`. +Il est possible d'inclure des noms de serveur Web dans le motif d'une règle d'URL. Cela est principalement utilisé lorsque votre application doit se comporter différemment selon le nom du serveur Web. +Par exemple, les règles suivantes analysent et résolvent l'URL `http://admin.example.com/login` en la route `admin/user/login` +et `http://www.example.com/login` en la route `site/login`. ```php [ @@ -331,7 +452,8 @@ Il est possible d'inclure des noms de serveur Web dans le motif d'une règle d'U ] ``` -Vous pouvez aussi inclure des paramètres dans les noms de serveurs pour en extraire de l'information dynamique. Par exemple, la règle suivante analyse et résout l'URL `http://en.example.com/posts` en la route `post/index` et le paramètre `language=en`. +Vous pouvez aussi inclure des paramètres dans les noms de serveurs pour en extraire de l'information dynamique. +Par exemple, la règle suivante analyse et résout l'URL `http://en.example.com/posts` en la route `post/index` et le paramètre `language=en`. ```php [ @@ -339,19 +461,28 @@ Vous pouvez aussi inclure des paramètres dans les noms de serveurs pour en ext ] ``` -> Note: les règles avec des noms de serveur ne doivent pas comprendre le sous-dossier du script d'entrée dans leur motif. Par exemple, si l'application est sous `http://www.example.com/sandbox/blog`, alors vous devez utiliser le motif `http://www.example.com/posts` au lieu de `http://www.example.com/sandbox/blog/posts`. Cela permet à votre application d'être déployée sous n'importe quel dossier sans avoir à changer son code. +Depuis la version 2.0.11, vous pouvez également utiliser des motifs relatifs au protocole qui marchent à la fois pour `http` et `https`. +La syntaxe est la même que ci-dessus mais en sautant la partie `http`, p. ex. `'//www.example.com/login' => 'site/login'`. + +> Note: les règles avec des noms de serveur ne doivent **pas** comprendre le sous-dossier du script d'entrée dans leur motif. +Par exemple, si l'application est sous `http://www.example.com/sandbox/blog`, alors vous devez utiliser le motif `http://www.example.com/posts` au lieu de `http://www.example.com/sandbox/blog/posts`. +Cela permet à votre application d'être déployée sous n'importe quel dossier sans avoir à changer son code. +Yii détecte automatiquement l'URL de base de l'application. ### Suffixes d'URL -Vous désirez peut-être ajouter des suffixes aux URL pour des raisons variées. Par exemple, vous pouvez ajouter `.html` aux URL de manière à ce qu'elles ressemblent à des URL de pages HTML statiques. Vous pouvez aussi y ajouter `.json` pour indiquer le type de contenu attendu pour la réponse. Vous pouvez faire cela en configurant la propriété [[yii\web\UrlManager::suffix]] dans la configuration de l'application comme ceci : +Vous désirez peut-être ajouter des suffixes aux URL pour des raisons variées. +Par exemple, vous pouvez ajouter `.html` aux URL de manière à ce qu'elles ressemblent à des URL de pages HTML statiques. +Vous pouvez aussi y ajouter `.json` pour indiquer le type de contenu attendu pour la réponse. +Vous pouvez faire cela en configurant la propriété [[yii\web\UrlManager::suffix]] dans la configuration de l'application comme ceci : ```php [ + // ... 'components' => [ 'urlManager' => [ 'enablePrettyUrl' => true, - 'showScriptName' => false, - 'enableStrictParsing' => true, + // ... 'suffix' => '.html', 'rules' => [ // ... @@ -361,21 +492,25 @@ Vous désirez peut-être ajouter des suffixes aux URL pour des raisons variées. ] ``` -La configuration ci-dessus permet au [[yii\web\UrlManager|gestionnaire d'URL]] de reconnaître les URL requises et aussi de créer des URL avec le suffixe `.html`. +La configuration ci-dessus permet au [[yii\web\UrlManager|gestionnaire d'URL]] de reconnaître les URL requises +et aussi de créer des URL avec le suffixe `.html`. > Tip: vous pouvez définir `/` en tant que suffixe des URL de manière à ce que tous les URL se terminent par la barre oblique de division. -> Note: lorsque vous configurez un suffixe d'URL, si une URL requise ne contient pas ce suffixe, elle est considérée comme une URL non reconnue. Cela est une pratique recommandée pour l'optimisation des moteurs de recherche (SE0 – Search Engine Optimization). +> Note: lorsque vous configurez un suffixe d'URL, si une URL requise ne contient pas ce suffixe, elle est considérée comme une URL non reconnue. +Cela est une pratique recommandée pour l'optimisation des moteurs de recherche (SE0 – Search Engine Optimization). -Parfois vous désirez utiliser des suffixes différents pour différentes URL. Cela peut être fait en configurant la propriété [[yii\web\UrlRule::suffix|suffix]] des règles d'URL individuelles. Lorsqu'une URL a cette propriété définie, elle écrase la valeur définie au niveau du [[yii\web\UrlManager|gestionnaire d'URL]]. Par exemple, la configuration suivante contient une règle d'URL personnalisée qui utilise `.json` en tant que suffixe à la place du suffixe défini globalement `.html`. +Parfois vous désirez utiliser des suffixes différents pour différentes URL. +Cela peut être fait en configurant la propriété [[yii\web\UrlRule::suffix|suffix]] des règles d'URL individuelles. +Lorsqu'une URL a cette propriété définie, elle écrase la valeur définie au niveau du [[yii\web\UrlManager|gestionnaire d'URL]]. +Par exemple, la configuration suivante contient une règle d'URL personnalisée qui utilise `.json` en tant que suffixe à la place du suffixe défini globalement `.html`. ```php [ 'components' => [ 'urlManager' => [ 'enablePrettyUrl' => true, - 'showScriptName' => false, - 'enableStrictParsing' => true, + // ... 'suffix' => '.html', 'rules' => [ // ... @@ -390,45 +525,37 @@ Parfois vous désirez utiliser des suffixes différents pour différentes URL. C ] ``` - ### Méthodes HTTP -En mettant en œuvre des API pleinement REST, il est couramment nécessaire que la même URL puisse être résolue en différentes routes selon la méthode HTTP utilisée par la requête. Cela peut être fait facilement en préfixant les motifs des règles avec les méthodes HTTP prises en charge. Si une règle prend en charge plusieurs méthodes HTTP, il faut séparer les noms de méthode par une virgule. Par exemple, les règles suivantes ont le même motif `post/` mais des méthodes HTTP différentes. Un requête de `PUT post/100` est résolue en la route `post/create`, tandis que la requête de `GET post/100` en la route `post/view`. +En mettant en œuvre des API pleinement REST, il est couramment nécessaire que la même URL puisse être résolue en différentes routes selon la méthode HTTP utilisée par la requête. +Cela peut être fait facilement en préfixant les motifs des règles avec les méthodes HTTP prises en charge. +Si une règle prend en charge plusieurs méthodes HTTP, il faut séparer les noms de méthode par une virgule. +Par exemple, les règles suivantes ont le même motif `post/` mais des méthodes HTTP différentes. +Une requête de `PUT post/100` est résolue en la route `post/update`, tandis que la requête de `GET post/100` en la route `post/view`. ```php -[ - 'PUT,POST post/' => 'post/create', +'rules' => [ + 'PUT,POST post/' => 'post/update', 'DELETE post/' => 'post/delete', 'post/' => 'post/view', ] ``` -> Note: si une règle d'URL contient des méthodes HTTP dans son motif, la règle n'est utilisée qu'à des fins d'analyse résolution. Elle est ignorée quand le [[yii\web\UrlManager|gestionnaire d'URL]] est sollicité pour créer une URL. +> Note: si une règle d'URL contient des méthodes HTTP dans son motif, la règle n'est utilisée qu'à des fins d'analyse sauf si `GET` fait partie des verbes spécifiés. +Elle est ignorée quand le [[yii\web\UrlManager|gestionnaire d'URL]] est sollicité pour créer une URL. -> Tip: pour simplifier le routage des API pleinement REST, Yii fournit la classe spéciale de règle d'URL [[yii\rest\UrlRule]] qui est très efficace et prend en charge quelques fonctionnalités originales comme la pluralisation automatique des identifiants de contrôleur. Pour plus de détails, reportez-vous à la section [Routage](rest-routing.md) sur le développement d'API pleinement REST. +> Tip: pour simplifier le routage des API pleinement REST, Yii fournit la classe spéciale de règle d'URL [[yii\rest\UrlRule]] +qui est très efficace et prend en charge quelques fonctionnalités originales comme la pluralisation automatique des identifiants de contrôleur. +Pour plus de détails, reportez-vous à la section [Routage](rest-routing.md) dans le chapitre API pleinement REST. -### Personnalisation des règles - -Dans l'exemple précédent, les règles d'URL sont essentiellement déclarées en terme de paires motif-route. Cela est un format raccourci communément utilisé. Dans certains scénarios, vous désirez personnaliser une règle d'URL en configurant ses autres propriétés, telles que [[yii\web\UrlRule::suffix]]. Cela peut être fait en utilisant un tableau complet de configuration pour spécifier une règle. L'exemple suivant est tiré de la sous-section [suffixes d'URL](#url-suffixes) : - -```php -[ - // ...other url rules... - - [ - 'pattern' => 'posts', - 'route' => 'post/index', - 'suffix' => '.json', - ], -] -``` - -> Info: Par défaut, si vous ne spécifiez pas l'option `class` dans la configuration d'une règle, elle prend la valeur par défaut [[yii\web\UrlRule]]. - ### Ajout dynamique de règles -Des règles d'URL peuvent être ajoutées dynamiquement au [[yii\web\UrlManager|gestionnaire d'URL]]. Cela est souvent nécessaire pour les [modules](structure-modules.md) distribuables qui veulent gérer leurs propres règles d'URL. Pour que les règles ajoutées dynamiquement prennent effet dans de processus de routage, vous devez les ajouter dans l'étape d'[amorçage](runtime-bootstrapping.md). Pour les modules, cela signifie qu'ils doivent implémenter l'interface [[yii\base\BootstrapInterface]] et ajouter les règles dans leur méthode [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]] comme l'exemple suivant le montre : +Des règles d'URL peuvent être ajoutées dynamiquement au [[yii\web\UrlManager|gestionnaire d'URL]]. +Cela est souvent nécessaire pour les [modules](structure-modules.md) distribuables qui veulent gérer leurs propres règles d'URL. +Pour que les règles ajoutées dynamiquement prennent effet dans de processus de routage, vous devez les ajouter dans l'étape d'[amorçage](runtime-bootstrapping.md). +Pour les modules, cela signifie qu'ils doivent implémenter l'interface [[yii\base\BootstrapInterface]] +et ajouter les règles dans leur méthode [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]] comme l'exemple suivant le montre : ```php public function bootstrap($app) @@ -439,16 +566,22 @@ public function bootstrap($app) } ``` -Notez que vous devez également lister ces modules dans la propriété [[yii\web\Application::bootstrap]] afin qu'ils puissent participer au processus d'[amorçage](runtime-bootstrapping.md). +Notez que vous devez également lister ces modules dans la propriété [[yii\web\Application::bootstrap]] +afin qu'ils puissent participer au processus d'[amorçage](runtime-bootstrapping.md). ### Création des classes règles -En dépit du fait que la classe par défaut [[yii\web\UrlRule]] est suffisamment flexible pour la majorité des projets, il y a des situations dans lesquelles vous devez créer votre propres classes de règle. Par exemple, dans un site Web de vendeur de voitures, vous désirerez peut-être prendre en charge des formats d'URL du type `/Manufacturer/Model`, où `Manufacturer` et `Model` doivent correspondre à quelques données stockées dans une base de données. La classe de règle par défaut ne fonctionne pas dans ce cas car elle s'appuie sur des motifs déclarés de manière statique. +En dépit du fait que la classe par défaut [[yii\web\UrlRule]] est suffisamment flexible pour la majorité des projets, +il y a des situations dans lesquelles vous devez créer votre propres classes de règle. +Par exemple, dans un site Web de vendeur de voitures, vous désirerez peut-être prendre en charge des formats d'URL du type `/Manufacturer/Model`, où `Manufacturer` et `Model` doivent correspondre à quelques données stockées dans une base de données. +La classe de règle par défaut ne fonctionne pas dans ce cas car elle s'appuie sur des motifs déclarés de manière statique. Vous pouvez créer les classes de règle d'URL suivantes pour résoudre ce problème : ```php + + +Depuis la version 2.0.10, le [[yii\web\UrlManager|gestionnaire d'URL]] peut être configuré pour utiliser le [[yii\web\UrlNormalizer|normalisateur d'URL]] pour prendre en compte les variations de la même URL, p. ex. avec et sans la barre oblique de division de fin. + + +Parce que, techniquement, `http://example.com/path` +et `http://example.com/path/` sont des URL différentes, servir le même contenu pour chacune d'elles peut dégrader le classement SEO. +Par défaut, le normalisateur fusionne les barres obliques de division consécutives, ajoute ou retire des barres de division de fin selon que le suffixe comporte une barre de division de fin ou pas, et redirige vers la version normalisée de l'URL en utilisant la [redirection permanente](https://en.wikipedia.org/wiki/HTTP_301). +Le normalisateur peut être configuré globalement pour le gestionnaire d'URL ou individuellement pour chacune des règles — par défaut, chacune des règles utilise le normalisateur du gestionnaire d'URL. +Vous pouvez définir [[yii\web\UrlRule::$normalizer|UrlRule::$normalizer]] à `false` pour désactiver la normalisation pour une règle d'URL particulière. + +Ce qui suit est un exemple de configuration pour le [[yii\web\UrlNormalizer|normalisateur d'URL]]: + +```php +'urlManager' => [ + 'enablePrettyUrl' => true, + 'showScriptName' => false, + 'enableStrictParsing' => true, + 'suffix' => '.html', + 'normalizer' => [ + 'class' => 'yii\web\UrlNormalizer', + // utilise la redirection temporaire au lieu de la redirection permanente pour le débogage + 'action' => UrlNormalizer::ACTION_REDIRECT_TEMPORARY, + ], + 'rules' => [ + // ...autres règles... + [ + 'pattern' => 'posts', + 'route' => 'post/index', + 'suffix' => '/', + 'normalizer' => false, // désactive le normalisateur pour cette règle + ], + [ + 'pattern' => 'tags', + 'route' => 'tag/index', + 'normalizer' => [ + // ne fusionne pas les barres obliques de division consécutives pour cette règle + 'collapseSlashes' => false, + ], + ], + ], +] +``` + +> Note: par défaut [[yii\web\UrlManager::$normalizer|UrlManager::$normalizer]] est désactivé. +Vous devez le configure explicitement pour activer la normalisation d'URL. + + ## Considérations de performance -Lors du développement d'une application Web, il est important d'optimiser les règles d'URL afin que l'analyse des requêtes et la création d'URL prennent moins de temps. +Lors du développement d'une application Web complexe, il est important d'optimiser les règles d'URL afin que l'analyse des requêtes et la création d'URL prennent moins de temps. + En utilisant les routes paramétrées, vous pouvez réduire le nombre de règles d'URL, ce qui accroît significativement la performance. -Lors de l'analyse d'URL ou de la création d'URL, le [[yii\web\UrlManager|gestionnaire d'URL]] examine les règles d'URL dans l'ordre de leur déclaration. En conséquence, vous devez envisager d'ajuster cet ordre afin que les règles les plus spécifiques et/ou utilisées couramment soient placée avant les règles les moins utilisées. +Lors de l'analyse d'URL ou de la création d'URL, le [[yii\web\UrlManager|gestionnaire d'URL]] examine les règles d'URL dans l'ordre de leur déclaration. En conséquence, vous devez envisager d'ajuster cet ordre afin que les règles les plus spécifiques et/ou utilisées couramment soient placées avant les règles les moins utilisées. + -Si quelques règles d'URL partagent le même préfixe dans leur motif ou dans leur route, vous pouvez envisager d'utiliser [[yii\web\GroupUrlRule]] pour qu'elles puissent être examinées plus efficacement par le [[yii\web\UrlManager|gestionnaire d'URL]] en tant que groupe. Cela est souvent le cas quand votre application est composée de modules, chacun ayant son propre jeu de règles d'URL avec l'identifiant de module comme préfixe commun. +Si quelques règles d'URL partagent le même préfixe dans leur motif ou dans leur route, vous pouvez envisager d'utiliser [[yii\web\GroupUrlRule]] pour qu'elles puissent être examinées plus efficacement par le [[yii\web\UrlManager|gestionnaire d'URL]] en tant que groupe. +Cela est souvent le cas quand votre application est composée de modules, chacun ayant son propre jeu de règles d'URL avec l'identifiant de module comme préfixe commun. diff --git a/docs/guide-fr/runtime-sessions-cookies.md b/docs/guide-fr/runtime-sessions-cookies.md index 9586e552664..d9a31753c5f 100644 --- a/docs/guide-fr/runtime-sessions-cookies.md +++ b/docs/guide-fr/runtime-sessions-cookies.md @@ -5,12 +5,12 @@ Les sessions et les témoins de connexion permettent à des données d'être con ## Sessions -Comme pour les [requêtes](runtime-requests.md) et les [réponses](runtime-responses.md), vous pouvez accéder aux sessions via le [composant d'application component](structure-application-components.md) `session` qui, par défaut, est une instance de la classe [[yii\web\Session]]. +Comme pour les [requêtes](runtime-requests.md) et les [réponses](runtime-responses.md), vous pouvez accéder aux sessions via le [composant d'application](structure-application-components.md) `session` qui, par défaut, est une instance de la classe [[yii\web\Session]]. ### Ouverture et fermeture d'une session -Pour ouvrir et fermer une session, vous pouvez procéder comme ceci : +Pour ouvrir et fermer une session, vous pouvez procéder comme suit : ```php $session = Yii::$app->session; @@ -24,7 +24,7 @@ $session->open(); // ferme une session $session->close(); -// détruit toutes les données enregistrée dans une session. +// détruit toutes les données enregistrées dans une session. $session->destroy(); ``` @@ -127,6 +127,10 @@ Toutes ces classes de session prennent en charge le même jeu de méthodes d'API > Note: si vous voulez accéder aux données de session via `$_SESSION` quand vous êtes en train d'utiliser une session à stockage personnalisé, vous devez vous assurer que cette session a été préalablement démarrée via [[yii\web\Session::open()]]. Cela est dû au fait que les gestionnaires de stockage des sessions personnalisées sont enregistrés à l'intérieur de cette méthode. +> Note : si vous utilisez un stockage de session personnalisé, vous devez configurer le collecteur de déchets de session explicitement. +Quelques installations de PHP (p. ex. Debian) utilisent une probabilité de collecteur de déchets de 0 et nettoient les fichiers de session hors ligne dans une tâche de cron. Ce processus ne s'applique pas à votre stockage personnalisé, c'est pourquoi vous devez configurer + [[yii\web\Session::$GCProbability]] pour utiliser une valeur non nulle. + Pour savoir comment configurer et utiliser ces classes de composant, reportez-vous à leur documentation d'API. Ci-dessous, nous présentons un exemple de configuration de [[yii\web\DbSession]] dans la configuration de l'application pour utiliser une base de données en tant que support de stockage d'une session : @@ -153,12 +157,38 @@ CREATE TABLE session ) ``` -où 'BLOB' fait référence au type de grand objet binaire (binary large objet — BLOB) de votre système de gestion de base de données (DBMS) préféré. Ci-dessous, vous trouverez les types de BLOB qui peuvent être utilisés par quelques DBMS populaires : +où 'BLOB' fait référence au type « grand objet binaire » (binary large objet — BLOB) de votre système de gestion de base de données (DBMS) préféré. Ci-dessous, vous trouverez les types de BLOB qui peuvent être utilisés par quelques DBMS populaires : - MySQL: LONGBLOB - PostgreSQL: BYTEA - MSSQL: BLOB > Note: en fonction des réglages de `session.hash_function` dans votre fichier php.ini, vous devez peut-être ajuster la longueur de la colonne `id`. Par exemple, si `session.hash_function=sha256`, vous devez utiliser une longueur de 64 au lieu de 40. + +Cela peut être accompli d'une façon alternative avec la migration suivante : + +```php +createTable('{{%session}}', [ + 'id' => $this->char(64)->notNull(), + 'expire' => $this->integer(), + 'data' => $this->binary() + ]); + $this->addPrimaryKey('pk-id', '{{%session}}', 'id'); + } + + public function down() + { + $this->dropTable('{{%session}}'); + } +} +``` ### Donnés flash diff --git a/docs/guide-fr/start-databases.md b/docs/guide-fr/start-databases.md index 666b9d132be..23e4158983b 100644 --- a/docs/guide-fr/start-databases.md +++ b/docs/guide-fr/start-databases.md @@ -1,4 +1,4 @@ -Travailler avec les bases de données +Travailler avec des bases de données ====================== Cette section décrit comment créer une nouvelle page qui affiche des données pays récupérées dans une table de base @@ -10,22 +10,21 @@ Au long de ce tutoriel, vous apprendrez comment : * Configurer une connexion à une base de données * Définir une classe Active Record -* Requêter des données en utilisant la classe Active Record +* Demander des données en utilisant la classe Active Record (enregistrement actif) * Afficher des données dans une vue paginée -Notez que pour finir cette section, vous aurez besoin d'avoir une connaissance basique des bases de données. -En particulier, vous devez savoir créer une base de données, et exécuter des déclarations SQL en utilisant un client de +Notez que, pour finir cette section, vous aurez besoin d'avoir une connaissance basique des bases de données. +En particulier, vous devez savoir créer une base de données et exécuter des déclarations SQL en utilisant un client de gestion de bases de données. Préparer la Base de Données -------------------- -Pour commencer, créez une base de données appelée `yii2basic`, depuis laquelle vous irez chercher les données dans -votre application. -Vous pouvez créer une base de données SQLite, MySQL, PostgreSQL, MSSQL ou Oracle, car Yii gère nativement de nombreuses -applications de base de données. Par simplicité, nous supposerons que vous utilisez MySQL dans les descriptions qui -suivent. +Pour commencer, créez une base de données appelée `yii2basic`, depuis laquelle vous irez chercher les données dans votre application. +Vous pouvez créer une base de données SQLite, MySQL, PostgreSQL, MSSQL ou Oracle, car Yii gère nativement de nombreuses applications de base de données. Pour simplifier, nous supposerons que vous utilisez MySQL dans les descriptions qui suivent. + +>Note : bien que MariaDB a été un remplacement direct de MySQL, cela n'est plus complètement vrai. Dans le cas où vous auriez besoin de fonctionnalités avancées telles que la prise en charge de `JSON`, jetez un coup d'œil à la liste des extensions de MariaDB ci-dessous. Créez maintenant une table nommée `country` dans la base de données et insérez-y quelques données exemples. Vous pouvez exécuter l'instruction SQL suivante pour le faire : @@ -48,15 +47,14 @@ INSERT INTO `country` VALUES ('RU','Russia',146519759); INSERT INTO `country` VALUES ('US','United States',322976000); ``` -Vous avez désormais une base de données appelée `yii2basic` conmprenant une table `country` comportant trois colonnes et contenant dix lignes de données. +Vous avez désormais une base de données appelée `yii2basic` comprenant une table `country` comportant trois colonnes et contenant dix lignes de données. Configurer une Connexion à la BDD --------------------------- Avant de continuer, vérifiez que vous avez installé à la fois l'extension PHP [PDO](http://www.php.net/manual/fr/book.pdo.php) et le pilote PDO pour la base de données que vous utilisez (c'est -à dire `pdo_mysql` pour MySQL). C'est une exigence de base si votre application utilise une base de données -relationnelle. +à dire `pdo_mysql` pour MySQL). C'est une exigence de base si votre application utilise une base de données relationnelle. Une fois ces éléments installés, ouvrez le fichier `config/db.php` et modifiez les paramètres pour qu'ils correspondent à votre base de données. Par défaut, le fichier contient ce qui suit : @@ -72,18 +70,20 @@ return [ ]; ``` -Le fichier `config/db.php` est un exemple type d'outil de [configuration](concept-configurations.md) basé sur un -fichier. Ce fichier de configuration en particulier spécifie les paramètres nécessaires à la création et -l'initialisation d'une instance de [[yii\db\Connection]] grâce à laquelle vous pouvez effectuer des requêtes SQL -dans la base de données sous-jacente. +Le fichier `config/db.php` est un exemple type d'outil de [configuration](concept-configurations.md) basé sur un fichier. Ce fichier de configuration en particulier spécifie les paramètres nécessaires à la création et l'initialisation d'une instance de [[yii\db\Connection]] grâce à laquelle vous pouvez effectuer des requêtes SQL dans la base de données sous-jacente. -On peut accéder à connexion à la BDD configurée ci-dessus depuis le code de l'application vial'expression -`Yii::$app->db`. +On peut accéder à connexion à la BDD configurée ci-dessus depuis le code de l'application via l'expression `Yii::$app->db`. > Info: le fichier `config/db.php` sera inclus par la configuration principale de l'application `config/web.php`, - qui spécifie comment l'instante d'[application](structure-applications.md) doit être initialisée. + qui spécifie comment l'instance d'[application](structure-applications.md) doit être initialisée. Pour plus d'informations, reportez-vous à la section [Configurations](concept-configurations.md). +Si vous avez besoin de fonctionnalités de base de données dont la prise en charge n'est pas comprise dans Yii, examinez les extensions suivantes: + +- [Informix](https://github.com/edgardmessias/yii2-informix) +- [IBM DB2](https://github.com/edgardmessias/yii2-ibm-db2) +- [Firebird](https://github.com/edgardmessias/yii2-firebird) +- [MariaDB](https://github.com/sam-it/yii2-mariadb) Créer un Active Record ------------------------- @@ -102,8 +102,7 @@ class Country extends ActiveRecord } ``` -La classe `Country` étend [[yii\db\ActiveRecord]]. Vous n'avez pas besoin d'y écrire le moindre code ! Simplement, avec -le code ci-dessus, Yii devine le nom de la table associée au nom de la classe. +La classe `Country` étend [[yii\db\ActiveRecord]]. Vous n'avez pas besoin d'y écrire le moindre code ! Simplement, avec le code ci-dessus, Yii devine le nom de la table associée au nom de la classe. > Info: si aucune correspondance directe ne peut être faite à partir du nom de la classe, vous pouvez outrepasser la méthode [[yii\db\ActiveRecord::tableName()]] pour spécifier explicitement un nom de table. @@ -126,10 +125,8 @@ $country->name = 'U.S.A.'; $country->save(); ``` -> Info: Active Record est un moyen puissant pour accéder et manipuler des données d'une base de manière orientée objet. -Vous pouvez trouver plus d'informations dans la section [Active Record](db-active-record.md). Sinon, vous pouvez -également interagir avec une base de données en utilisant une méthode de plus bas niveau d'accès aux données appelée -[Data Access Objects](db-dao.md). +> Info: Active Record (enregistrement actif) est un moyen puissant pour accéder et manipuler des données d'une base de manière orientée objet. +Vous pouvez trouver plus d'informations dans la section [Active Record](db-active-record.md). Sinon, vous pouvez également interagir avec une base de données en utilisant une méthode de plus bas niveau d'accès aux données appelée [Database Access Objects](db-dao.md). Créer une Action @@ -204,7 +201,7 @@ use yii\widgets\LinkPager;
  • - name} ({$country->code})") ?>: + code} ({$country->name})") ?>: population ?>
  • @@ -243,13 +240,13 @@ En coulisse, [[yii\data\Pagination|Pagination]] fournit toutes les fonctionnalit * Au départ, [[yii\data\Pagination|Pagination]] représente la première page, qui reflète la requête SELECT de country avec la clause `LIMIT 5 OFFSET 0`. Il en résulte que les cinq premiers pays seront trouvés et affichés. -* L'objet graphique [[yii\widgets\LinkPager|LinkPager]] effectue le rendu des boutons de pages en utilisant les URLs créées par - [[yii\data\Pagination::createUrl()|Pagination]]. Les URLs contiendront le paramètre de requête `page`, qui représente +* L'objet graphique [[yii\widgets\LinkPager|LinkPager]] effectue le rendu des boutons de pages en utilisant les URL créées par + [[yii\data\Pagination::createUrl()|Pagination]]. Les URL contiendront le paramètre de requête `page`, qui représente les différents numéros de pages. * Si vous cliquez sur le bouton de page "2", une nouvelle requête pour la route `country/index` sera déclenchée et traitée. [[yii\data\Pagination|Pagination]] lit le paramètre de requête `page` dans l'URL et met le numéro de page à 2. - La nouvelle requête de pays aura donc la clause `LIMIT 5 OFFSET 5` et retournera le cinq pays suivants pour être + La nouvelle requête de pays aura donc la clause `LIMIT 5 OFFSET 5` et retournera les cinq pays suivants pour être affichés. @@ -260,7 +257,7 @@ Dans cette section, vous avez appris comment travailler avec une base de donnée chercher et afficher des données dans des pages avec l'aide de [[yii\data\Pagination]] et de [[yii\widgets\LinkPager]]. Dans la prochaine section, vous apprendrez comment utiliser le puissant outil de génération de code, appelé -[Gii](tool-gii.md), pour vous aider à implémenter rapidement des fonctionnalités communément requises, telles que les +[Gii](https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide), pour vous aider à rapidement mettre en œuvre des fonctionnalités communément requises, telles que les opérations Créer, Lire, Mettre à Jour et Supprimer (CRUD : Create-Read-Update-Delete) pour travailler avec les données dans une table de base de données. En fait, le code que vous venez d'écrire peut être généré automatiquement dans Yii en utilisant l'outil Gii. diff --git a/docs/guide-fr/start-gii.md b/docs/guide-fr/start-gii.md index 30dc24fffba..5c99e6ffd0f 100644 --- a/docs/guide-fr/start-gii.md +++ b/docs/guide-fr/start-gii.md @@ -1,25 +1,21 @@ Générer du code avec Gii ======================== -Cette section décrit comment utiliser [Gii](tool-gii.md) pour générer du code qui implémente des fonctionnalités -courantes de sites Web automatiquement. Utiliser Gii pour auto-générer du code consiste simplement à saisir les -bonnes informations en suivant les instructions affichées sur les pages Web Gii. +Cette section décrit comment utiliser [Gii](https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide) pour générer du code qui met automatiquement en œuvre des fonctionnalités courantes de sites Web. Utiliser Gii pour auto-générer du code consiste simplement à saisir les bonnes informations en suivant les instructions affichées sur les pages Web de Gii. Au long de ce tutoriel, vous apprendrez comment : * Activer Gii dans votre application -* Utiliser Gii pour générer des classes Active Record -* Utiliser Gii pour générer du code implémentant les opérations CRUD pour une table de BDD +* Utiliser Gii pour générer des classes Active Record (enregistrement actif) +* Utiliser Gii pour générer du code mettant en œuvre les opérations CRUD pour une table de BDD * Personnaliser le code généré par Gii Démarrer Gii ------------ -[Gii](tool-gii.md) est fourni dans Yii en tant que [module](structure-modules.md). Vous pouvez activer Gii en le -configurant dans la propriété [[yii\base\Application::modules|modules]] de l’application. En fonction de la manière -dont vous avez créé votre application, vous trouverez peut être que le code suivant est déjà fourni dans le fichier de -configuration `config/web.php`: +[Gii](https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide) est fourni dans Yii en tant que [module](structure-modules.md). Vous pouvez activer Gii en le +configurant dans la propriété [[yii\base\Application::modules|modules]] de l’application. En fonction de la manière dont vous avez créé votre application, il se peut que le code suivant soit déjà fourni dans le fichier de configuration `config/web.php`: ```php $config = [ ... ]; @@ -32,24 +28,21 @@ if (YII_ENV_DEV) { } ``` -La configuration ci-dessus établit que dans un [environnement de développement](concept-configurations.md#environment-constants), -l’application doit inclure un module appelé `gii`, qui est de classe [[yii\gii\Module]]. +La configuration ci-dessus établit que dans un [environnement de développement](concept-configurations.md#environment-constants), l’application doit inclure un module appelé `gii`, qui est de classe [[yii\gii\Module]]. -Si vous vérifiez le [script de démarrage](structure-entry-scripts.md) `web/index.php` de votre application, vous -les lignes suivantes, qui en gros, font que `YII_ENV_DEV` est vrai. +Si vous vérifiez le [script de démarrage](structure-entry-scripts.md) `web/index.php` de votre application, vous y trouverez les lignes suivantes, qui en gros, font que `YII_ENV_DEV` est défini à `true` (vrai). ```php defined('YII_ENV') or define('YII_ENV', 'dev'); ``` -Grâce à cette ligne, votre application est en mode développement, et aura déjà active Gii, suivant la configuration -ci-dessus. Vous pouvez maintenant accéder à Gii via l’URL suivante : +Grâce à cette ligne, votre application est en mode développement, et active Gii, suivant la configuration vue ci-dessus. Vous pouvez maintenant accéder à Gii via l’URL suivante : ``` http://hostname/index.php?r=gii ``` -> Note : Si vous accède à Gii depuis une machine autre que localhost, l’accès sera refuse par défaut pour des raisons +> Note : si vous accédez à Gii depuis une machine autre que localhost, l’accès sera refusé par défaut pour des raisons > de sécurité. Vous pouvez configurer Gii pour ajouter les adresses IP autorisées comme suit, > ```php @@ -65,35 +58,29 @@ http://hostname/index.php?r=gii Générer une Classe Active Record --------------------------------- -Pour utiliser Gii pour générer une classe Active Record, sélectionnez le "Model Generator" (en cliquant sur le lien -dans la page index de Gii). Puis complétez le formulaire comme suit : +Pour générer une classe Active Record avec Gii, sélectionnez le "Model Generator" (générateur de modèle), en cliquant sur le lien dans la page d'accueil de Gii, puis complétez le formulaire comme suit : * Table Name: `country` * Model Class: `Country` ![Générateur de Modèles](images/start-gii-model.png) -Ensuite, cliquez sur le bouton "Preview". Vous verrez que `models/Country.php` est listé comme fichier de classe à être créé. Vous pouvez cliquer sur le nom du fichier de classe pour pré visualiser son contenu. +Ensuite, cliquez sur le bouton "Preview" (prévisualiser). Vous verrez que `models/Country.php` est listé comme fichier de classe à créer. Vous pouvez cliquer sur le nom du fichier de classe pour prévisualiser son contenu. -Quand vous utilisez Gii, si vous aviez déjà créé le même fichier et que vous l’écraseriez, cliquez sur le bouton `diff` -à côté du nom de fichier pour voir les différences entre le code à être généré et la version existant. +Si vous avez déjà créé le même fichier, il sera écrasé. Cliquez sur le bouton `diff` +à côté du nom de fichier pour voir les différences entre le fichier à générer et la version existante. -![Pré Visualisation du Générateur de Modèle](images/start-gii-model-preview.png) +![Prévisualisation du générateur de modèle](images/start-gii-model-preview.png) -Quand vous écrasez un fichier existant, cochez la case située à côté de "overwrite" et ensuite, cliquez sur le bouton -"Generate". Si vous créez un nouveau fichier, il suffit de cliquer sur "Generate". +Pour écraser un fichier existant, cochez la case située à côté de "overwrite" (écraser), puis cliquez sur le bouton "Generate" (générer). Pour créer un nouveau fichier, il suffit de cliquer sur "Generate". -Ensuite, vous verrez une page de confirmation indiquant que le code a été généré avec succès. Si vous aviez un fichier -existant, vous verrez également un message indiquant qu’il a été écrasé par le code nouvellement généré. +En fin d'opération, vous verrez une page de confirmation indiquant que le code a été généré avec succès. Si vous aviez un fichier existant, vous verrez également un message indiquant qu’il a été écrasé par le code nouvellement généré. Générer du Code CRUD -------------------- -CRUD signifie Create, Read, Update, and Delete (Créer, Lire, Mettre à Jour et Supprimer), représentant le quatre tâches -communes entreprises avec des données sur la plupart des sites Web. Pour créer les fonctionnalités CRUD en utilisant -Gii, sélectionnez le "CRUD Generator" (en cliquant sur le lien dans la page index de Gii). Pour l’exemple de "country", -remplissez le formulaire résultant comme suit : +CRUD signifie Create, Read, Update, and Delete (Créer, Lire, Mettre à Jour et Supprimer), soit les quatre tâches communes concernant des données sur la plupart des sites Web. Pour créer les fonctionnalités CRUD en utilisant Gii, sélectionnez le "CRUD Generator" en cliquant sur le lien dans la page d'accueil de Gii. Pour l’exemple de "country", remplissez le formulaire résultant comme suit : * Model Class: `app\models\Country` * Search Model Class: `app\models\CountrySearch` @@ -101,13 +88,13 @@ remplissez le formulaire résultant comme suit : ![CRUD Generator](images/start-gii-crud.png) -Ensuite, cliquez sur le bouton "Preview". Vous verrez une liste de fichiers à générer, comme ci-dessous. +Ensuite, cliquez sur le bouton "Preview" (prévisualiser). Vous verrez une liste de fichiers à générer, comme ci-dessous. ![CRUD Generator Preview](images/start-gii-crud-preview.png) Si vous aviez précédemment créé les fichiers `controllers/CountryController.php` et -`views/country/index.php` (dans la section bases de données du guide), cochez la case "overwrite" pour les remplacer. -(Les versions précédentes n’avaient pas de fonctionnalités CRUD). +`views/country/index.php` (dans la section bases de données du guide), cochez la case "overwrite" (écraser) pour les remplacer. +(Les versions précédentes ne prenaient pas totalement en charge les fonctionnalités CRUD). Essayer @@ -119,34 +106,27 @@ Pour voir comment ça fonctionne, utilisez votre navigateur pour accéder à l http://hostname/index.php?r=country/index ``` -Vous verrez une grille de données montrant les pays de la table de la base de données. Vous pouvez trier la table, ou -lui appliquer des filtres en entrant des conditions de filtrage dans les entêtes de colonnes. +Vous verrez une grille de données montrant les pays de la table de la base de données. Vous pouvez trier la table, ou lui appliquer des filtres en entrant des conditions de filtrage dans les entêtes de colonnes. -Pour chaque pays affiché dans la grille, vous pouvez choisir de visualiser les détails, le mettre à jour ou le -supprimer. -Vous pouvez aussi cliquer sur le bouton "Create Country" en haut de la grille pour que Yii vous fournisse un formulaire -permettant de créer un nouveau pays. +Pour chaque pays affiché dans la grille, vous pouvez choisir de visualiser les détails, le mettre à jour ou le supprimer. +Vous pouvez aussi cliquer sur le bouton "Create Country" (créer un pays) en haut de la grille pour que Yii vous présente un formulaire permettant de créer un nouveau pays. ![Grille de Données Pays](images/start-gii-country-grid.png) ![Mettre à Jour un Pays](images/start-gii-country-update.png) -Ce qui suit est la liste des fichiers générés par Gii, au cas où vous souhaiteriez investiguer la manière dont ces -fonctionnalités sont implémentées, ou les personnaliser : +Ce qui suit est la liste des fichiers générés par Gii, au cas où vous souhaiteriez investiguer la manière dont ces fonctionnalités sont mises en œuvre, ou les personnaliser : * Contrôleur: `controllers/CountryController.php` * Modèles: `models/Country.php` et `models/CountrySearch.php` * Vues: `views/country/*.php` -> Info: Gii est conçu pour être un outil de génération de code hautement personnalisable et extensible. L’utiliser avec - sagesse peut grandement accélérer le développement de vos applications. Pour plus de détails, merci de vous référer - à la section [Gii](tool-gii.md). +> Info: Gii est conçu pour être un outil de génération de code hautement personnalisable et extensible. L’utiliser avec sagesse peut grandement accélérer le développement de vos applications. Pour plus de détails, merci de vous référer à la section [Gii](tool-gii.md). Résumé ------- -Dans cette section, vous avez appris à utiliser Gii pour générer le code qui implémente une fonctionnalité CRUD -complète pour les contenus stockés dans une table de base de données. +Dans cette section, vous avez appris à utiliser Gii pour générer le code qui met en œuvre une fonctionnalité CRUD complète pour des contenus stockés dans une table de base de données. diff --git a/docs/guide-fr/start-installation.md b/docs/guide-fr/start-installation.md index fa36149be3c..6422c64ec28 100644 --- a/docs/guide-fr/start-installation.md +++ b/docs/guide-fr/start-installation.md @@ -1,34 +1,64 @@ Installer Yii ============= -Vous pouvez installer Yii de deux façons, en utilisant [Composer](https://getcomposer.org/) ou en téléchargeant une archive. -La première méthode est conseillée, étant donné qu'elle permet d'installer de nouvelles [extensions](extend-creating-extensions.md) ou de mettre à jour Yii en éxécutant simplement une commande. +Vous pouvez installer Yii de deux façons, en utilisant le gestionnaire de paquets [Composer](https://getcomposer.org/) ou en téléchargeant une archive. +La première méthode est conseillée, étant donné qu'elle permet d'installer de nouvelles [extensions](extend-creating-extensions.md) ou de mettre Yii à jour en exécutant simplement une commande. -> Note: contrairement à Yii 1, les installations standards de Yii 2 auront pour résultat le téléchargement et l'installation du framework, ainsi que d'un squelette d'application. +Les installations standard de Yii provoquent le téléchargement et l'installation d'un modèle de projet. Un modèle de projet et un projet Yii fonctionnel qui met en œuvre quelques fonctionnalités de base, telles que la connexion, le formulaire de contact, etc. +Son code est organisé de la façon recommandée. En conséquence, c'est un bon point de départ pour vos propres projets. + +Dans cette section et quelques-unes de ses suivantes, nous décrirons comment installer Yii avec le modèle baptisé *Basic Project Template* (modèle de projet de base) et comment mettre en œuvre de nouvelles fonctionnalités sur cette base. Yii vous offre également un autre modèle de projet appelé [Advanced Project Template ](https://www.yiiframework.com/extension/yiisoft/yii2-app-advanced/doc/guide) (modèle de projet avancé) qui convient mieux à un environnement de développement en équipe impliquant des tiers multiples. + +> Note: le modèle de projet de base conviendra à 90 pourcent des application Web. Il diffère du modèle de projet avancé essentiellement sur la manière dont le code est organisé. Si vous débutez avec Yii, nous vous conseillons fortement de vous en tenir au modèle de projet de base pour sa simplicité tout en disposant des fonctionnalités suffisantes. Installer via Composer ---------------------- -Si vous n'avez pas déjà installé Composer, vous pouvez le faire en suivant les instructions sur le site [getcomposer.org](https://getcomposer.org/download/). -Sous Linux et Mac OS X, vous pouvez éxécuter les commandes : +###Installer Composer +Si vous n'avez pas déjà installé Composer, vous pouvez le faire en suivant les instructions du site [getcomposer.org](https://getcomposer.org/download/). +Sous Linux et Mac OS X, vous pouvez exécuter les commandes : + +```bash curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer +``` + +Sous Windows, téléchargez et exécutez [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe). + +En cas de problèmes, consultez la [section Troubleshooting (résolution des problèmes) de la documentation de Composer](https://getcomposer.org/doc/articles/troubleshooting.md), + +Si vous débutez avec Composer, nous vous recommandons au minimum la lecture de la section [Basic usage (utilisation de base)](https://getcomposer.org/doc/01-basic-usage.md) de la documentation de Composer + +Dans ce guide, toutes les commandes de Composer suppose que vous avez installé Composer [globalement](https://getcomposer.org/doc/00-intro.md#globally) et qu'il est disponible par la commande `composer`. Si, au lieu de cela, vous utilisez `composer.phar` depuis un dossier local, vous devez adapter les exemples fournis en conséquence. -Sous Windows, téléchargez et éxécutez [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe). +Si Composer était déjà installé auparavant, assurez-vous d'utiliser une version à jour. Vous pouvez mettre Composer à jour avec la commande `composer self-update`. -Merci de consulter la [Documentation de Composer](https://getcomposer.org/doc/) en cas de problèmes, ou si vous souhaitez en savoir d'avantage sur l'utilisation de Composer. +> Note: durant l'installation de Yii, Composer aura besoin d'obtenir de nombreuses informations de l'API de Github. Le nombre de requêtes dépend du nombre de dépendances de votre application et peut excéder la **Github API rate limit**. Si vous arrivez à cette limite, Composer peut vous demander vos identifiants de connexion pour obtenir un jeton d'accès à l'API de Github. Avec une connexion rapide, vous pouvez atteindre cette limite plus vite que Composer n'est capable de gérer. C'est pourquoi, nous vous recommandons de configurer ce jeton d'accès avant d'installer Yii. +> Reportez-vous à la [documentation de Composer sur les jetons de l'API Github](https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens) +> pour savoir comment procéder. -Avec Composer installé, vous pouvez installer Yii en éxécutant la commande suivante dans un dossier accessible via le Web : +###Installer Yii + +Avec Composer installé, vous pouvez installer le modèle de projet Yii en exécutant la commande suivante dans un dossier accessible via le Web : +```bash composer create-project --prefer-dist yiisoft/yii2-app-basic basic +``` + +Cette commande installera la dernière version stable du modèle de projet Yii dans le dossier `basic`. Vous êtes libre de choisir un autre dossier si vous le désirez. + +> Note: si la commande `composer create-project` échoue, reportez-vous à la section +> [Troubleshooting (résolution des problèmes) de la documentation de Composer](https://getcomposer.org/doc/articles/troubleshooting.md) +> pour les erreurs communes. Une fois l'erreur corrigée, vous pouvez reprendre l'installation avortée en exécutant `composer update` dans le dossier `basic` (ou celui que vous aviez choisi). -Cette commande installera Yii dans le dossier `basic`. > Tip: si vous souhaitez installer la dernière version de développement de Yii, vous pouvez utiliser la commande suivante qui ajoutera l'[option stability](https://getcomposer.org/doc/04-schema.md#minimum-stability) : > -> composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic +>```bash +> composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic +>``` > > Notez que la version de développement de Yii ne doit pas être utilisée en production, vu qu'elle pourrait *casser* votre code existant. @@ -36,34 +66,73 @@ Cette commande installera Yii dans le dossier `basic`. Installer depuis une archive ---------------------------- -Installer Yii depuis une archive se fait en deux étapes : +Installer Yii depuis une archive se fait en trois étapes : -1. Téléchargez l'archive sur le site [yiiframework.com](http://www.yiiframework.com/download/yii2-basic). -2. Décompressez l'archive dans un dossier accessible via le Web. +1. Télécharger l'archive sur le site [yiiframework.com](http://www.yiiframework.com/download/). +2. Décompresser l'archive dans un dossier accessible via le Web. +3. Modifier le fichier `config/web.php` en entrant une clé secrète pour la configuration de `cookieValidationKey` (cela est fait automatiquement si vous installez Yii avec Composer) : + + ```php + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => 'enter your secret key here', + ``` Autres options d'installation ----------------------------- -Les instructions d'installation ci-dessus montrent comment installer Yii, ce qui installe également une application Web de base qui fonctionne *out of the box*. -Cette approche est un bon point de départ pour les petits projets, ou pour quand vous commencer à apprendre Yii. +Les instructions d'installation ci-dessus montrent comment installer Yii, ce qui installe également une application Web de base qui fonctionne *out of the box* (sans configuration supplémentaire). +Cette approche est un bon point de départ pour les petits projets, en particulier si vous débutez avec Yii. Mais il y a d'autres options d'installation disponibles : -* Si vous voulez installer uniquement le framework et que vous souhaitez créer une application à partir de zéro, vous pouvez suivre les instructions dans la partie [Construire une application à partir de zéro](tutorial-start-from-scratch.md). -* Si vous voulez commencer par une application plus sophistiquée, mieux adaptée aux environnements d'équipe de développement, vous pouvez envisager l'installation du [Modèle d'application avancée](tutorial-advanced-app.md). +* Si vous voulez installer uniquement le framework et que vous souhaitez créer une application à partir de zéro, vous pouvez suivre les instructions dans la partie [Créer votre propre structure d'application](tutorial-start-from-scratch.md). +* Si vous voulez commencer par une application plus sophistiquée, mieux adaptée aux environnements d'équipe de développement, vous pouvez envisager l'installation du [Modèle d'application avancée](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/README.md). + +Installer les Assets (ici bibliothèques CSS et JavaScript) +----------------- + +Yii s'appuie sur les paquets [Bower](http://bower.io/) et/ou [NPM](https://www.npmjs.org/) pour l'installation des bibliothèques CSS et JavaScript. + +Il utilise Composer pour les obtenir, permettant ainsi aux versions de paquet de PHP et à celles de CSS/JavaScript, d'être résolues en même temps. +Cela peut être obtenue soit en utilisant [asset-packagist.org](https://asset-packagist.org) ou [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/). +Reportez-vous à la documentation sur les [Assets](structure-assets.md) pour plus de détail. + +Vous pouvez souhaiter gérer vos « assets », soit via le client natif Bower/NPM, soit via CDN, soit éviter totalement leur installation. +Afin d'empêcher l'installation des « assets » via Composer, ajoutez les lignes suivantes à votre fichier 'composer.json' : + +```json +"replace": { + "bower-asset/jquery": ">=1.11.0", + "bower-asset/inputmask": ">=3.2.0", + "bower-asset/punycode": ">=1.3.0", + "bower-asset/yii2-pjax": ">=2.0.0" +}, +``` + +> Note: en cas de neutralisation de l'installation des « assets » via Composer, c'est à vous d'en assurer l'installation et de résoudre les problèmes de collision de versions. Attendez-vous à des incohérences possibles parmi les fichiers d'assets issus de vos différentes extensions. Vérifier l'installation ----------------------- -Après l'installation, vous pouvez utiliser votre navigateur pour accéder à l'application Yii avec l'URL suivante : +Après l'installation, vous pouvez, soit configurer votre serveur Web (voir section suivante), soit utiliser le [serveur PHP web incorporé](https://secure.php.net/manual/fr/features.commandline.webserver.php) en utilisant la commande en console suivante depuis le dossier `web` de votre projet : + +```bash +php yii serve +``` + +> Note: par défaut le serveur HTTP écoute le port 8080. Néanmoins, si ce port est déjà utilisé ou si vous voulez servir plusieurs applications de cette manière, vous pouvez spécifier le port à utiliser en ajoutant l'argument --port à la commande : + +```bash +php yii serve --port=8888 +``` +Pour accéder à l'application Yii pointez votre navigateur sur l'URL suivante : ``` -http://localhost/basic/web/index.php +http://localhost:8080/ ``` -Cette URL suppose que vous avez installé Yii dans un dossier nommé `basic`, directement dans le dossier racine du serveur Web, et que le serveur Web est en cours d'exécution sur votre machine locale (`localhost`). Vous devrez peut-être ajuster cette URL à votre environnement d'installation. ![Successful Installation of Yii](images/start-app-installed.png) @@ -72,12 +141,12 @@ Vous devriez voir dans votre navigateur la page ci-dessus. Sinon, merci de véri * Utilisez un navigateur pour accéder à l'URL `http://localhost/basic/requirements.php` * Exécutez les commandes suivantes: - ``` + ```bash cd basic php requirements.php ``` -Vous devez configurer votre installation de PHP afin qu'elle réponde aux exigences minimales de Yii. Le plus important étant que vous ayez PHP 5.4 ou plus. Si votre application a besoin d'une base de données, vous devez également installer l'[extension PHP PDO](http://www.php.net/manual/en/pdo.installation.php) ainsi qu'un pilote correspondant à votre système de base de données (par exemple `pdo_mysql` pour MySQL). +Vous devez configurer votre installation de PHP afin qu'elle réponde aux exigences minimales de Yii. Le plus important étant que vous ayez PHP 5.4 ou plus, idéalement PHP 7. Si votre application a besoin d'une base de données, vous devez également installer l'[extension PHP PDO](http://www.php.net/manual/fr/pdo.installation.php) ainsi qu'un pilote correspondant à votre système de base de données (par exemple `pdo_mysql` pour MySQL). Configuration du serveur Web @@ -85,25 +154,29 @@ Configuration du serveur Web > Note: si vous voulez juste tester Yii sans intention de l'utiliser sur un serveur de production, vous pouvez ignorer ce paragraphe. -L'application installée selon les instructions ci-dessus devrait fonctionner *out of the box* avec le [serveur HTTP Apache](http://httpd.apache.org/) ou le [serveur HTTP Nginx](http://nginx.org/), sous Windows, Mac OX X, ou linux. +L'application installée selon les instructions ci-dessus devrait fonctionner *out of the box* (sans configuration supplémentaire) avec le [serveur HTTP Apache](http://httpd.apache.org/) ou le [serveur HTTP Nginx](http://nginx.org/), sous Windows, Mac OX X, ou Linux avec PHP 5.4 ou plus récent. Yii 2.0 est aussi compatible avec +[HHVM](http://hhvm.com/) de Facebook. Cependant, il existe des cas marginaux pour lesquels HHVM se comporte différemment du PHP natif; c'est pourquoi vous devez faire plus attention en utilisant HHVM.. Sur un serveur de production, vous pouvez configurer votre serveur Web afin que l'application soit accessible via l'URL `http://www.example.com/index.php` au lieu de `http://www.example.com/basic/web/index.php`. Cela implique que le dossier racine de votre serveur Web pointe vers le dossier `basic/web`. Vous pouvez également cacher `index.php` dans l'URL, comme décrit dans la partie [Génération et traitement des URL](runtime-url-handling.md), vous y apprendrez comment configurer votre serveur Apache ou Nginx pour atteindre ces objectifs. > Note: en utilisant `basic/web` comme dossier racine, vous empêchez également aux utilisateurs finaux d'accéder à votre code d'application privé et fichiers de données sensibles qui sont stockés dans le dossier `basic`. Refuser l'accès à ces ressources est une amélioration de la sécurité. -> Note: si votre application s'exécute dans un environnement d'hébergement mutualisé où vous n'avez pas la permission de modifier la configuration du serveur Web, vous pouvez ajuster la structure de votre application pour une meilleure sécurité. Merci de lire la partie [Environnement d'hébergement mutualisé](tutorial-shared-hosting.md) pour en savoir plus. +> Note: si votre application s'exécute dans un environnement d'hébergement mutualisé où vous n'avez pas la permission de modifier la configuration du serveur Web, vous pouvez ajuster la structure de votre application pour une meilleure sécurité. Reportez-vous à la partie [Environnement d'hébergement mutualisé](tutorial-shared-hosting.md) pour en savoir plus. +> Note: si vous exécutez votre application Yii derrière un mandataire inverse, vous pourriez avoir besoin de configurer les +> [mandataires de confiance et entêtes](runtime-requests.md#trusted-proxies) dans le composant « request ». ### Configuration Apache recommandée -Utilisez la configuration suivante dans `httpd.conf`, ou dans la configuration de votre hôte virtuel. Notez que vous devez remplacer `path/to/basic/web` par le chemin vers le dossier `basic/web`. +Utilisez la configuration suivante dans le fichier `httpd.conf`, ou dans la configuration de votre hôte virtuel. Notez que vous devez remplacer `path/to/basic/web` par le chemin vers le dossier `basic/web`. -``` +```apache # Configuration du dossier racine DocumentRoot "path/to/basic/web" + # utiliser mod_rewrite pour la prise en charge des URL élégantes ("pretty URL") RewriteEngine on # Si le dossier ou fichier existe, répondre directement @@ -112,6 +185,9 @@ DocumentRoot "path/to/basic/web" # Sinon on redirige vers index.php RewriteRule . index.php + # si $showScriptName est à "false" dans UrlManager, ne pas autoriser l'accès aux URL incluant le nom du script + RewriteRule ^index.php/ - [L,R=404] + # ...other settings... ``` @@ -122,32 +198,37 @@ DocumentRoot "path/to/basic/web" Pour utiliser Nginx, vous devez avoir installé PHP en utilisant [FPM SAPI](http://php.net/install.fpm). Utilisez la configuration Nginx suivante, en remplaçant `path/to/basic/web` par le chemin vers le dossier `basic/web` et `mysite.test` par le nom d'hôte de votre serveur. -``` +```nginx server { charset utf-8; client_max_body_size 128M; - listen 80; ## port pour ipv4 - #listen [::]:80 default_server ipv6only=on; ## port pour ipv6 + listen 80; ## listen for ipv4 + #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 server_name mysite.test; root /path/to/basic/web; index index.php; - access_log /path/to/basic/log/access.log main; + access_log /path/to/basic/log/access.log; error_log /path/to/basic/log/error.log; location / { - # Test fichier/dossier, sinon redirection vers index.php - try_files $uri $uri/ /index.php?$args; + # Rediriger tout ce qui n'est pas un fichier réel index.php + try_files $uri $uri/ /index.php$is_args$args; } - # décommentez ces lignes pour évitez que Yii ne gère les requêtes vers des fichiers statiques inexistants + # enlevez les commentaires de ces lignes pour évitez que Yii ne gère les requêtes vers des fichiers statiques inexistants #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ { # try_files $uri =404; #} #error_page 404 /404.html; + + # refuser l'accès aux fichiers php pour le dossier /assets + location ~ ^/assets/.*\.php$ { + deny all; + location ~ \.php$ { include fastcgi.conf; fastcgi_pass 127.0.0.1:9000; diff --git a/docs/guide-fr/start-looking-ahead.md b/docs/guide-fr/start-looking-ahead.md index 5d8117f05f0..8592ce84daf 100644 --- a/docs/guide-fr/start-looking-ahead.md +++ b/docs/guide-fr/start-looking-ahead.md @@ -1,39 +1,38 @@ En savoir plus ============= -Si vous avez entièrement lu la section "Mise en Route", vous avec maintenant créé une application Yii complète. Ce -faisant, vous avez appris comment implémenter des fonctionnalités couramment utilisées, telles que recueillir des -données d'un utilisateur via un formulaire HTML, chercher des données dans une base de données, et afficher des données -de manière paginée. Vous avez également appris à utiliser [Gii](tool-gii.md) pour générer du code automatiquement. +Si vous avez entièrement lu la section "Mise en Route", vous avez maintenant créé une application Yii complète. Ce faisant, vous avez appris comment mettre en œuvre des fonctionnalités couramment utilisées, telles que recueillir des données d'un utilisateur via un formulaire HTML, chercher des données dans une base de données, et afficher des données +de manière paginée. Vous avez également appris à utiliser [Gii](https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide) pour générer du code automatiquement. Utiliser Gii pour générer du code rend le gros de votre processus de développement Web aussi simple que de remplir de simples formulaires. -Cette section va résumer les ressources Yii disponibles pour vous aider à être plus productif dans l'utilisation du -framework. +Cette section va résumer les ressources Yii disponibles pour vous aider à être plus productif dans l'utilisation du framework. * Documentation - - Le Guide définitif : + - [Le Guide complet](http://www.yiiframework.com/doc-2.0/guide-README.html) : Comme son nom l'indique, le guide définit précisément comment Yii fonctionne et fournit des instructions générales sur l'utilisation de Yii. C'est le tutoriel pour Yii le plus important, un que vous devriez lire avant d'écrire le moindre code Yii. - - La Référence de Classes : - Elle spécifie l'usage de toutes les classes fournies par Yii. Elle doit être principalement utilisée lorsque - vous utilisez du code et souhaitez comprendre l'usage d'une classe, méthode ou propriété particulière. - L'utilisation de la référence de classe est plus appropriée quand vous avez une compréhension contextuelle du - framework entier. - - Les Articles Wiki: - Les articles wiki sont écrits par des utilisateurs de Yii en fonction de leurs propres expériences. Ils sont en + - [Le référentiel des Classes](http://www.yiiframework.com/doc-2.0/index.html) : + Il spécifie le mode d'utilisation de toutes les classes fournies par Yii. Il doit être principalement utilisé lorsque + vous écrivez du code et souhaitez comprendre le mode d'utilisation d'une classe, méthode ou propriété particulière. + L'utilisation du référentiel des classes est plus appropriée quand vous avez une compréhension contextuelle du framework entier. + - [Les Articles du Wiki](http://www.yiiframework.com/wiki/?tag=yii2): + Les articles wiki sont écrits par des utilisateurs de Yii sur la base de leurs propres expériences. Ils sont en général écrits comme des recettes de cuisine, et montrent comment résoudre des problèmes pratiques en utilisant - Yii. Bien que la qualité de ces articles peut être inférieure à celle du Guide Définitif, ils sont utiles du fait + Yii. Bien que la qualité de ces articles puisse être moindre que celle du Guide complet, ils sont utiles du fait qu'ils couvrent des sujets plus vastes et peuvent fournir des solutions clef-en-main. - - Livres + - [Livres](http://www.yiiframework.com/doc/) * [Extensions](http://www.yiiframework.com/extensions/): Yii est fort d'une librairie de milliers d'extensions créées par les utilisateurs, qui peuvent être facilement ajoutées à votre application, rendant son développement encore plus facile et plus rapide. * Communauté - Forum : - Chat IRC : Les canal #yii sur le réseau freenode () - - GitHub : - - Facebook : - - Twitter : - - LinkedIn : + - Slack chanel: + - Gitter chat: + - GitHub: + - Facebook: + - Twitter: + - LinkedIn: + - Stackoverflow: diff --git a/docs/guide-fr/start-prerequisites.md b/docs/guide-fr/start-prerequisites.md new file mode 100644 index 00000000000..c0ccc8a9c7a --- /dev/null +++ b/docs/guide-fr/start-prerequisites.md @@ -0,0 +1,19 @@ +# Que devez-vous connaître + +La courbe d'apprentissage de Yii n’est pas aussi raide que celle des autres framework. Cependant, il y a un certain nombre de choses que vous devriez connaître avant de vous lancer avec Yii. + +## PHP + +Yii un framework (base structurée de développement) en PHP. C’est pourquoi vous devez vous assurer de [maîtriser ce langage en comprenant sa référence](http://php.net/manual/fr/langref.php). +Lors de votre développement avec Yii, vous écrirez du code dans le style « orienté objet ». Vous devez donc être familiarisé avec les [Classes et Objets](https://secure.php.net/manual/fr/language.oop5.basic.php), ainsi qu'avec les [espaces de noms](https://secure.php.net/manual/fr/language.namespaces.php). + +## Programmation orientée Objet + +Une compréhension de base de la programmation orientée objet est requise. Si vous n’êtes pas familiarisé avec elle, orientez-vous vers l’un des nombreux tutoriels disponibles tels que [celui de tuts+](https://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762). + +Notez que plus votre application sera complexe, plus vous devrez en savoir pour gérer cette complexité avec succès. + +## Ligne de commande et composer + +Yii utilise abondamment le gestionnaire de paquet [Composer](https://getcomposer.org/) qui est un standard de fait. Vous devez donc lire et comprendre son [guide](https://getcomposer.org/doc/01-basic-usage.md). Si vous n’êtes pas encore familiarisé avec la ligne de commande, c’est le moment de vous y essayer. Une fois les bases acquises, vous ne saurez plus vous en passer. + diff --git a/docs/guide-fr/start-workflow.md b/docs/guide-fr/start-workflow.md index 4efa37736dc..2058b6ce950 100644 --- a/docs/guide-fr/start-workflow.md +++ b/docs/guide-fr/start-workflow.md @@ -3,13 +3,14 @@ Fonctionnement des applications Après avoir installé Yii, vous obtenez une application Yii fonctionnelle accessible via l'URL `http://hostname/basic/web/index.php` ou `http://hostname/index.php`, en fonction de votre configuration. Cette section vous initiera aux fonctionnalités intégrées à l'application, -à la manière dont le code est organisé, et à la gestion des requêtes par l'application. +à la manière dont le code est organisé et à la gestion des requêtes par l'application. -> Info: Par simplicité, au long de ce tutoriel de démarrage, nous supposerons que `basic/web` est la racine de votre - serveur Web, et que vous avez configuré l'URL pour accéder à votre application comme suit ou similaire : +> Info: pour simplifier, au long de ce tutoriel de démarrage, nous supposerons que `basic/web` est la racine de votre + serveur Web, et que vous avez configuré l'URL pour accéder à votre application comme suit ou de façon similaire : `http://hostname/index.php`. Pour vos besoins, merci d'ajuster les URLs dans notre description comme il convient. +Notez que contrairement au framework lui-même, après avoir installé un modèle de projet, vous êtes entièrement libre d'en disposer. Vous êtes libre d'ajouter ou de supprimer du code selon vos besoins. Fonctionnalité -------------- @@ -17,19 +18,21 @@ Fonctionnalité L'application basique installée contient quatre pages : * La page d'accueil, affichée quand vous accédez à l'URL `http://hostname/index.php`, -* la page "About" (A Propos), -* la page "Contact", qui présente un formulaire de contact permettant aux utilisateurs finaux de vous contacter par email, +* la page "About" (À Propos), +* la page "Contact", qui présente un formulaire de contact permettant aux utilisateurs finaux de vous contacter par courriel, * et la page "Login" (Connexion), qui présente un formulaire de connexion qui peut être utilisé pour authentifier des utilisateurs finaux. Essayez de vous connecter - avec "admin/admin", et vous verrez l'élément "Login" du menu principal être remplacé par "Logout" (Déconnexion). + avec "admin/admin", et vous verrez l'élément "Login" du menu principal être remplacé par "Logout" (Déconnexion). Ces pages ont en commun une entête et un pied de page. L'entête contient une barre de menu principal qui permet la navigation entre les différentes pages. Vous devriez également voir une barre d'outils en bas de votre fenêtre de navigation. -C'est un [outil de débogage](tool-debugger.md) utile fourni par Yii pour enregistrer et afficher de nombreuses informations de débogage, telles que des messages de logs, statuts de réponses, les requêtes lancées vers la base de données, et ainsi de suite. +C'est un [outil de débogage](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide/README.md) utile fourni par Yii pour enregistrer et afficher de nombreuses informations de débogage, telles que des messages de journaux, les statuts de réponses, les requêtes lancées vers la base de données, etc. +En plus de l'application Web, il existe,dans le dossier de base de l'application, un script en console appelé `yii`. Ce script peut être utilisé pour exécuter des tâches de fond et de maintenance pour l'application; ces tâches sont décrites à la section [Applications en console](tutorial-console.md). -Structure de l'Application + +Structure de l'application --------------------- Les répertoires et fichiers les plus importants de votre application sont (en supposant que le répertoire racine de l'application est `basic`) : @@ -52,20 +55,20 @@ basic/ chemin de base de l'application yii le script d'exécution de Yii en commande console ``` -Dans l'ensemble, les fichiers de l'application peuvent être séparés en deux types : ceux situés dans `basic/web` et ceux situés dans d'autres répertoires. Les premiers peuvent être atteints directement en HTTP (c'est à dire dans un navigateur), tandis que les seconds doivent pas l'être. +Dans l'ensemble, les fichiers de l'application peuvent être séparés en deux types : ceux situés dans `basic/web` et ceux situés dans d'autres répertoires. Les premiers peuvent être atteints directement en HTTP (c'est à dire dans un navigateur), tandis que les seconds ne peuvent et ne doivent pas l'être. -Yii est implémenté selon le patron de conception [modèle-vue-contrôleur (MVC)](http://fr.wikipedia.org/wiki/Mod%C3%A8le-vue-contr%C3%B4leur), +Yii est mis en œuvre selon le modèle de conception [modèle-vue-contrôleur (MVC)](http://wikipedia.org/wiki/Model-view-controller), ce qui se reflète dans l'organisation des répertoires ci-dessus. Le répertoire `models` contient toutes les [classes modèles](structure-models.md), -le répertoire `views` contient tous les [scripts de vue](structure-views.md), et le répertoire `controllers` contient toutes les [classes contrôleurs](structure-controllers.md). +le répertoire `views` contient tous les [scripts de vue](structure-views.md), et le répertoire `controllers` contient toutes les [classes contrôleurs](structure-controllers.md). Le schéma suivant présente la structure statique d'une application. ![Structure Statique d'Application](images/application-structure.png) -Chaque application a un script de démarrage `web/index.php` qui est le seul script PHP de l'application accessible depuis le Web. -Le script de démarrage reçoit une requête et créé une instance d'[application](structure-applications.md) pour la traiter. +Chaque application dispose d'un script de démarrage `web/index.php` qui est le seul script PHP de l'application accessible depuis le Web. +Le script de démarrage reçoit une requête entrante et crée une instance d'[application](structure-applications.md) pour la traiter. L'[application](structure-applications.md) résout la requête avec l'aide de ses [composants](concept-components.md), -et distribue la requête aux éléments MVC. Les [Widgets](structure-widgets.md) sont utilisés dans les [vues](structure-views.md) +et distribue la requête aux éléments MVC. Les [composants graphiques (widgets)](structure-widgets.md) sont utilisés dans les [vues](structure-views.md) pour aider à créer des éléments d'interface complexes et dynamiques. @@ -74,16 +77,16 @@ Cycle de vie d'une requête Le diagramme suivant présente la manière dont une application traite une requête. -![Cycle de Vie d'une Requête](images/request-lifecycle.png) +![Cycle de vie d'une requête](images/request-lifecycle.png) 1. Un utilisateur fait une requête au [script de démarrage](structure-entry-scripts.md) `web/index.php`. -2. Le script de démarrage charge la [configuration](concept-configurations.md) de l'application et créé une instance d'[application](structure-applications.md) pour traiter la requête. +2. Le script de démarrage charge la [configuration](concept-configurations.md) de l'application et crée une instance d'[application](structure-applications.md) pour traiter la requête. 3. L'application résout la [route](runtime-routing.md) requise avec l'aide du composant d'application [requête](runtime-requests.md). 4. L'application créé une instance de [contrôleur](structure-controllers.md) pour traiter la requête. -5. Le contrôleur créé une instance d'[action](structure-controllers.md) et effectue les filtres pour l'action. +5. Le contrôleur crée une instance d'[action](structure-controllers.md) et applique les filtres pour l'action. 6. Si un filtre échoue, l'action est annulée. 7. Si tous les filtres sont validés, l'action est exécutée. 8. L'action charge un modèle de données, potentiellement depuis une base de données. 9. L'action génère une vue, lui fournissant le modèle de données. -10. Le résultat généré est renvoyé au composant d'application [réponse](runtime-responses.md). -11. Le composant réponse envoie le résultat généré au navigateur de l'utilisateur. +10. Le résultat généré est renvoyé au composant d'application [response](runtime-responses.md). +11. Le composant « response » (réponse) envoie le résultat généré au navigateur de l'utilisateur. diff --git a/docs/guide-fr/structure-application-components.md b/docs/guide-fr/structure-application-components.md index 0ac3e728446..518e2012bb3 100644 --- a/docs/guide-fr/structure-application-components.md +++ b/docs/guide-fr/structure-application-components.md @@ -46,16 +46,25 @@ Par exemple, Comme il a été dit plus haut, un composant d'application n'est instancié que lorsqu'on y accède pour la première fois. S'il n'est pas du tout accédé dans le traitement de la requête, il n'est pas instancié. Parfois, vous désirez peut être instancier un composant d'application pour chacune des requêtes, même s'il n'est pas explicitement accédé. Pour cela, vous pouvez lister son identifiant (ID) dans la propriété [[yii\base\Application::bootstrap|bootstrap]] de l'application. +Vous pouvez également utiliser des « Closures » (Fermetures) pour amorcer des composants personnalisés. Il n'est pas nécessaire de retourner une instance de composant. Une « Closure » peut également être utilisée pour exécuter du code après l'instanciation de [[yii\base\Application]]. + Par exemple, la configuration d'application suivante garantit que le composant `log` est toujours chargé. ```php [ 'bootstrap' => [ 'log', + function($app){ + return new ComponentX(); + }, + function($app){ + // some code + return; + } ], 'components' => [ 'log' => [ - // configuration pour le composant "log" + // configuration le composant "log" ], ], ] @@ -69,10 +78,10 @@ Vous trouverez ci-après la liste des composants d'application prédéfinis du n * [[yii\web\AssetManager|assetManager (gestionnaire de ressources]]: gère les paquets de ressources et la publication des ressources. - Reportez-vous à la section [Gestion des ressources](structure-assets.md) pour plus de détails. + Reportez-vous à la section [Ressources](structure-assets.md) pour plus de détails. * [[yii\db\Connection|db (base de données)]]: représente une connexion à une base de données à l'aide de laquelle vous pouvez effectuer des requêtes de base de données. Notez que lorsque vous configurez ce composant, vous devez spécifier la classe de composant tout comme les autres propriétés de composant, telle que [[yii\db\Connection::dsn]]. - Reportez-vous à la section [Objets d'accès aux données](db-dao.md) pour plus de détails. + Reportez-vous à la section [Objets d'accès aux bases de données](db-dao.md) pour plus de détails. * [[yii\base\Application::errorHandler|errorHandler (gestionnaire d'erreurs) ]]: gère les erreurs PHP et les exceptions. Reportez-vous à la section [Gestion des erreurs](runtime-handling-errors.md) pour plus de détails. * [[yii\i18n\Formatter|formatter ]]: formate les données lorsqu'elles sont présentées à l'utilisateur final. Par exemple, un nombre peut être affiché avec un séparateur de milliers, une date affichée dans un format long, etc. @@ -81,7 +90,7 @@ Vous trouverez ci-après la liste des composants d'application prédéfinis du n Reportez-vous à la section [Internationalisation](tutorial-i18n.md) pour plus de détails. * [[yii\log\Dispatcher|log]]: gère les journaux cibles. Reportez-vous à la section [Journaux](runtime-logging.md) pour plus de détails. -* [[yii\swiftmailer\Mailer|mail]]: prend en charge la composition et l'envoi des courriels. +* [[yii\swiftmailer\Mailer|mailer]]: prend en charge la composition et l'envoi des courriels. Reportez-vous à la section [Mailing](tutorial-mailing.md) pour plus de détails. * [[yii\base\Application::response|response]]: représente la réponse qui est adressée à l'utilisateur final. Reportez-vous à la section [Réponses](runtime-responses.md) pour plus de détails. @@ -90,7 +99,7 @@ Vous trouverez ci-après la liste des composants d'application prédéfinis du n * [[yii\web\Session|session]]: représente les informations de session. Ce composant n'est disponible que dans les [[yii\web\Application|applications Web]]. Reportez-vous à la section [Sessions et Cookies](runtime-sessions-cookies.md) pour plus de détails. * [[yii\web\UrlManager|urlManager (gestionnaire d'url)]]: prend en charge l'analyse des URL et leur création. - Reportez-vous à la section [Analyse et création d'URL](runtime-routing.md) pour plus de détails. + Reportez-vous à la section [Routage et création d'URL](runtime-routing.md) pour plus de détails. * [[yii\web\User|user]]: représente les informations d'authentification de l'utilisateur. Ce composant n'est disponible que dans les [[yii\web\Application|applications Web]]. Reportez-vous à la section [Authentification](security-authentication.md) pour plus de détails. * [[yii\web\View|view]]: prend en charge le rendu des vues. diff --git a/docs/guide-fr/structure-applications.md b/docs/guide-fr/structure-applications.md index 72e67bfac11..1813ad6d70b 100644 --- a/docs/guide-fr/structure-applications.md +++ b/docs/guide-fr/structure-applications.md @@ -13,7 +13,7 @@ Il existe deux types d'application : [[yii\web\Application|les applications We ## Configurations d'application -Losqu'un [script d'entrée](structure-entry-scripts.md) crée une application, il charge une [configuration](concept-configurations.md) et l'applique à cette application de la manière suivante : +Lorsqu'un [script d'entrée](structure-entry-scripts.md) crée une application, il charge une [configuration](concept-configurations.md) et l'applique à cette application de la manière suivante : ```php require __DIR__ . '/../vendor/autoload.php'; diff --git a/docs/guide-fr/structure-assets.md b/docs/guide-fr/structure-assets.md index 064efada149..1ea514dd90b 100644 --- a/docs/guide-fr/structure-assets.md +++ b/docs/guide-fr/structure-assets.md @@ -1,18 +1,29 @@ Ressources ========== -Une ressource dans Yii est un fichier qui peut être référencé dans une page Web. Ça peut être un fichier CSS, un fichier JavaScript, une image, un fichier vidéo, etc. Les ressources sont situées dans un dossier accessible du Web et sont servies directement par les serveurs Web. +Une ressource dans Yii est un fichier qui peut être référencé dans une page Web. Ça peut être un fichier CSS, un fichier JavaScript, une image, un fichier vidéo, etc. +Les ressources sont situées dans un dossier accessible du Web et sont servies directement par les serveurs Web. + +Il est souvent préférable de gérer les ressources par programmation. +Par exemple, lorsque vous utilisez l'objet graphique [[yii\jui\DatePicker]] dans une page, il inclut automatiquement les fichiers CSS et JavaScript dont il a besoin, au lieu de vous demander de les inclure à la main. + +De plus, lorsque vous mettez à jour l'objet graphique, il utilise une nouvelle version des fichiers de ressources. +Dans ce tutoriel, nous décrivons les puissantes possibilités de la gestion des ressources de Yii. -Il est souvent préférable de gérer les ressources par programmation. Par exemple, lorsque vous utilisez l'objet graphique [[yii\jui\DatePicker]] dans une page, il inclut automatiquement les fichiers CSS et JavaScript dont il a besoin, au lieu de vous demander de les inclure à la main. De plus, lorsque vous mettez à jour l'objet graphique, il utilise une nouvelle version des fichiers de ressources. Dans ce tutoriel, nous décrivons les puissantes possibilités de la gestion des ressources de Yii. ## Paquets de ressources -Yii gère les ressources sous forme de *paquets de ressources*. Un paquet de ressources est simplement une collection de ressources situées dans un dossier. Lorsque vous enregistrez un paquet de ressources dans une [vue](structure-views.md), cette vue inclut les fichiers CSS et JavaScript du paquet dans la page Web rendue. +Yii gère les ressources sous forme de *paquets de ressources*. +Un paquet de ressources est simplement une collection de ressources situées dans un dossier. +Lorsque vous enregistrez un paquet de ressources dans une [vue](structure-views.md), cette vue inclut les fichiers CSS et JavaScript du paquet dans la page Web rendue. ## Définition de paquets de ressources -Les paquets de ressources sont spécifiés comme des classes PHP qui étendent [[yii\web\AssetBundle]]. Le nom du paquet est simplement le nom pleinement qualifié de la classe PHP correspondante (sans la barre oblique inversée de tête). Une classe de paquet de ressources doit être [auto-chargeable](concept-autoloading.md). Généralement, elle spécifie où les ressources sont situées, quels fichiers CSS et JavaScript le paquet contient, et si le paquet dépend d'autres paquets de ressources. +Les paquets de ressources sont spécifiés comme des classes PHP qui étendent [[yii\web\AssetBundle]]. +Le nom du paquet est simplement le nom pleinement qualifié de la classe PHP correspondante (sans la barre oblique inversée de tête). +Une classe de paquet de ressources doit être [auto-chargeable](concept-autoloading.md). +Généralement, elle spécifie où les ressources sont situées, quels fichiers CSS et JavaScript le paquet contient, et si le paquet dépend d'autres paquets de ressources. Le code suivant définit le paquet de ressources principal utilisé par le [modèle de projet *basic*](start-installation.md): @@ -29,6 +40,7 @@ class AppAsset extends AssetBundle public $baseUrl = '@web'; public $css = [ 'css/site.css', + ['css/print.css', 'media' => 'print'], ]; public $js = [ ]; @@ -39,53 +51,102 @@ class AppAsset extends AssetBundle } ``` -La classe `AppAsset` ci-dessus spécifie que les fichiers de ressources sont situés dans le dossier `@webroot` qui correspond à l'URL `@web`; le paquet contient un unique fichier CSS `css/site.css` et aucun fichier JavaScript ; le paquet dépend de deux autres paquets : [[yii\web\YiiAsset]] et [[yii\bootstrap\BootstrapAsset]]. Des explications plus détaillées sur les propriétés d'[[yii\web\AssetBundle]] sont disponibles dans les ressources suivantes : - -* [[yii\web\AssetBundle::sourcePath|sourcePath(chemin des sources)]]: spécifie le dossier racine qui contient les fichiers de ressources dans ce paquet. Cette propriété doit être définie si le dossier racine n'est pas accessible du Web. Autrement, vous devez définir les propriétés [[yii\web\AssetBundle::basePath|basePath]] et [[yii\web\AssetBundle::baseUrl|baseUrl]]. Des [alias de chemin](concept-aliases.md) sont utilisables ici. -* [[yii\web\AssetBundle::basePath|basePath (chemin de base)]]: spécifie un dossier accessible du Web qui contient les fichiers de ressources dans ce paquet. Lorsque vous spécifiez la propriété[[yii\web\AssetBundle::sourcePath|sourcePath (chemin des sources)]], le [gestionnaire de ressources](#asset-manager) publie les ressources de ce paquet dans un dossier accessible du Web et redéfinit cette propriété en conséquence. Vous devez définir cette propriété si vos fichiers de ressources sont déjà dans un dossier accessible du Web et n'ont pas besoin d'être publiés. Les [alias de chemin](concept-aliases.md) sont utilisables ici. -* [[yii\web\AssetBundle::baseUrl|baseUrl (URL de base)]]: spécifie l'URL qui correspond au dossier [[yii\web\AssetBundle::basePath|basePath]]. Comme pour [[yii\web\AssetBundle::basePath|basePath (chemin de base)]], si vous spécifiez la propriété [[yii\web\AssetBundle::sourcePath|sourcePath]], le [gestionnaire de ressources](#asset-manager) publie les ressources et redéfinit cette propriété en conséquence. Les [alias de chemin](concept-aliases.md) sont utilisables ici. -* [[yii\web\AssetBundle::js|js]]: un tableau listant les fichiers JavaScript contenus dans ce paquet. Notez que seule la barre oblique de division "/" peut être utilisée en tant que séparateur de dossiers. Chaque fichier JavaScript peut être spécifié dans l'un des formats suivants : - - Un chemin relatif représentant un fichier JavaScript local (p. ex. `js/main.js`). Le chemin réel du fichier peut être déterminé en préfixant le chemin relatif avec le [[yii\web\AssetManager::basePath| chemin de base]], et l'URL réelle du fichier peut être déterminée en préfixant le chemin relatif avec l'[[yii\web\AssetManager::baseUrl|URL de base]]. - - Une URL absolue représentant un fichier JavaScript externe. Par exemple , `http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` ou +La classe `AppAsset` ci-dessus spécifie que les fichiers de ressources sont situés dans le dossier `@webroot` qui correspond à l'URL `@web`; +le paquet contient un unique fichier CSS `css/site.css` et aucun fichier JavaScript ; +le paquet dépend de deux autres paquets : [[yii\web\YiiAsset]] et [[yii\bootstrap\BootstrapAsset]]. +Des explications plus détaillées sur les propriétés d'[[yii\web\AssetBundle]] sont disponibles dans les ressources suivantes : + +* [[yii\web\AssetBundle::sourcePath|sourcePath]] (chemin des sources): spécifie le dossier racine qui contient les fichiers de ressources dans ce paquet. +Cette propriété doit être définie si le dossier +racine n'est pas accessible du Web. +Autrement, vous devez définir les propriétés [[yii\web\AssetBundle::basePath|basePath]] et [[yii\web\AssetBundle::baseUrl|baseUrl]]. Des [alias de chemin](concept-aliases.md) sont utilisables ici. +* [[yii\web\AssetBundle::basePath|basePath ]] (chemin de base): spécifie un dossier accessible du Web qui contient les fichiers de ressources dans ce paquet. +Lorsque vous spécifiez la propriété[[yii\web\AssetBundle::sourcePath|sourcePath (chemin des sources)]], le [gestionnaire de ressources](#asset-manager) publie les ressources de ce paquet dans un dossier accessible du Web et redéfinit cette propriété en conséquence. +Vous devez définir cette propriété si vos fichiers de ressources sont déjà + dans un dossier accessible du Web et n'ont pas besoin d'être publiés. +Les [alias de chemin](concept-aliases.md) sont utilisables ici. +* [[yii\web\AssetBundle::baseUrl|baseUrl ]] (URL de base): spécifie l'URL qui correspond au dossier + [[yii\web\AssetBundle::basePath|basePath]]. +Comme pour [[yii\web\AssetBundle::basePath|basePath]] (chemin de base), + si vous spécifiez la propriété [[yii\web\AssetBundle::sourcePath|sourcePath]], le [gestionnaire de ressources](#asset-manager) publie les ressources et redéfinit cette propriété en conséquence. Les [alias de chemin](concept-aliases.md) sont utilisables ici. +* [[yii\web\AssetBundle::css|css]]: un tableau listant les fichiers CSS contenu dans ce paquet de ressources. +Notez que seul la barre oblique "/" doit être utilisée en tant que séparateur de dossier. Chaque fichier peut être spécifié en lui-même comme une chaîne de caractères ou dans un tableau avec les balises attributs et leur valeur. + +* [[yii\web\AssetBundle::js|js]]: un tableau listant les fichiers JavaScript contenus dans ce paquet. +Notez que seule la barre oblique de division "/" peut être utilisée en tant que séparateur de dossiers. +Chaque fichier JavaScript peut être spécifié dans l'un des formats suivants : + - Un chemin relatif représentant un fichier JavaScript local (p. ex. `js/main.js`). +Le chemin réel du fichier peut être déterminé en préfixant le chemin relatif avec le [[yii\web\AssetManager::basePath| chemin de base]], +et l'URL réelle du fichier peut être déterminée en préfixant le chemin relatif avec l'[[yii\web\AssetManager::baseUrl|URL de base]]. + - Une URL absolue représentant un fichier JavaScript externe. +Par exemple , `http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` ou `//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js`. -* [[yii\web\AssetBundle::css|css]]: un tableau listant les fichiers CSS contenus dans ce paquet. Le format de ce tableau est le même que celui de [[yii\web\AssetBundle::js|js]]. -* [[yii\web\AssetBundle::depends|depends (dépendances)]]: un tableau listant les paquets de ressources dont ce paquet dépend (brièvement expliqué). -* [[yii\web\AssetBundle::jsOptions|jsOptions]]: spécifie les options qui sont passées à la méthode [[yii\web\View::registerJsFile()]] lorsqu'elle est appelée pour enregistrer *chacun des* fichiers JavaScript de ce paquet. -* [[yii\web\AssetBundle::cssOptions|cssOptions]]: spécifie les options qui sont passées à la méthode [[yii\web\View::registerCssFile()]] lorsqu'elle est appelée pour enregistrer *chacun des* fichiers CSS de ce paquet. -* [[yii\web\AssetBundle::publishOptions|publishOptions]]: spécifie les options qui sont passées à la méthode [[yii\web\AssetManager::publish()]] lorsqu'elle est appelée pour publier les fichiers de ressources sources dans un dossier accessible du Web. Cela n'est utilisé que si vous spécifiez la propriété [[yii\web\AssetBundle::sourcePath|sourcePath]]. +* [[yii\web\AssetBundle::depends|depends (dépendances)]]: +un tableau listant les paquets de ressources dont ce paquet dépend (brièvement expliqué). +* [[yii\web\AssetBundle::jsOptions|jsOptions]]: spécifie les options qui sont passées à la méthode [[yii\web\View::registerJsFile()]] +lorsqu'elle est appelée pour enregistrer *chacun des* fichiers JavaScript de ce paquet. +* [[yii\web\AssetBundle::cssOptions|cssOptions]]: spécifie les options qui sont passées à la méthode +[[yii\web\View::registerCssFile()]] lorsqu'elle est appelée pour enregistrer *chacun des* fichiers CSS de ce paquet. +* [[yii\web\AssetBundle::publishOptions|publishOptions]]: spécifie les options qui sont passées à la méthode +[[yii\web\AssetManager::publish()]] lorsqu'elle est appelée pour publier les fichiers de ressources sources dans un dossier accessible du Web. +Cela n'est utilisé que si vous spécifiez la propriété [[yii\web\AssetBundle::sourcePath|sourcePath]]. ### Emplacement des ressources En se basant sur leur emplacement, les ressources peuvent être classifiées comme suit : -* Les ressources sources : les fichiers de ressources qui sont situés avec du code source PHP et qui ne peuvent être accéder directement depuis le Web. Afin de pouvoir être utilisées dans une page, elles doivent être copiées dans un dossier accessible du Web et transformées en ressources publiées. Ce processus est appelé *publication des ressources* et il sera décrit en détail bientôt. +* Les ressources sources : les fichiers de ressources qui sont situés avec du code source PHP et qui ne peuvent être accéder directement depuis le Web. + Afin de pouvoir être utilisées dans une page, elles doivent être copiées dans un dossier accessible du Web et transformées en ressources publiées. +Ce processus est appelé *publication des ressources* et il sera décrit en détail bientôt. * Les ressources publiées : les fichiers de ressources sont situés dans un dossier accessible du Web et peuvent par conséquent être accédés directement depuis le Web. * Les ressources externes : les fichiers de ressources sont situés sur un serveur Web différent de celui qui héberge l'application Web. -Lors de la définition de classes de paquet de ressources, si vous spécifiez la propriété [[yii\web\AssetBundle::sourcePath|sourcePath (chemin des sources)]], cela veut dire que les ressources listées en utilisant des chemins relatifs sont considérées comme des ressources sources. Si vous ne spécifiez pas cette propriété, cela signifie que ces ressources sont des ressources publiées (vous devez en conséquence spécifier [[yii\web\AssetBundle::basePath (chemin de base)|basePath]] et [[yii\web\AssetBundle::baseUrl|baseUrl (URL de base)]] pour faire connaître à Yii l'emplacement où elles se trouvent). -Il est recommandé de placer les ressources appartenant à une application dans un dossier accessible du Web de manière à éviter une publication non nécessaire de ressources. C'est pourquoi `AppAsset` dans l'exemple précédent spécifie le [[yii\web\AssetBundle::basePath|chemin de base]] plutôt que le [[yii\web\AssetBundle::sourcePath|chemin des sources]]. +Lors de la définition de classes de paquet de ressources, si vous spécifiez la propriété +[[yii\web\AssetBundle::sourcePath|sourcePath (chemin des sources)]], cela veut dire que les ressources listées en utilisant des chemins relatifs sont considérées comme des ressources sources. +Si vous ne spécifiez pas cette propriété, cela signifie que ces ressources sont des ressources publiées (vous devez en conséquence spécifier [[yii\web\AssetBundle::basePath (chemin de base)|basePath]] et [[yii\web\AssetBundle::baseUrl|baseUrl (URL de base)]] + pour faire connaître à Yii l'emplacement où elles se trouvent). + +Il est recommandé de placer les ressources appartenant à une application dans un dossier accessible du Web de manière à éviter une publication non nécessaire de ressources. +C'est pourquoi `AppAsset` dans l'exemple précédent spécifie le [[yii\web\AssetBundle::basePath|chemin de base]] +plutôt que le [[yii\web\AssetBundle::sourcePath|chemin des sources]]. -Quant aux [extensions](structure-extensions.md), comme leurs ressources sont situées avec le code source dans des dossiers non accessibles depuis le Web, vous devez spécifier la propriété [[yii\web\AssetBundle::sourcePath|sourcePath]] lorsque vous définissez des classes de paquet de ressources pour elles. +Quant aux [extensions](structure-extensions.md), comme leurs ressources sont situées avec le code source dans des dossiers non accessibles depuis le Web, vous devez spécifier la propriété +[[yii\web\AssetBundle::sourcePath|sourcePath]] +lorsque vous définissez des classes de paquet de ressources pour elles. -> Note: n'utilisez pas `@webroot/assets` en tant que [[yii\web\AssetBundle::sourcePath|chemin des sources]]. Ce dossier est utilisé par défaut par le [[yii\web\AssetManager|gestionnaire de ressources]] pour sauvegarder les fichiers de ressources publiés depuis leur emplacement source. Tout contenu dans ce dossier est considéré temporaire et sujet à suppression. +> Note: n'utilisez pas `@webroot/assets` en tant que [[yii\web\AssetBundle::sourcePath|chemin des sources]]. +Ce dossier est utilisé par défaut par le +[[yii\web\AssetManager|gestionnaire de ressources]] pour sauvegarder les fichiers de ressources publiés depuis leur emplacement source. +Tout contenu dans ce dossier est considéré temporaire et sujet à suppression. ### Dépendances de ressources -Lorsque vous incluez plusieurs fichiers CSS ou JavaScript dans une page Web, ils doivent respecter un certain ordre pour éviter des problèmes de redéfinition. Par exemple, si vous utilisez l'objet graphique jQuery Ui dans une page Web, vous devez vous assurer que le fichier JavaScript jQuery est inclus avant le fichier JavaScript jQuery UI. Nous appelons un tel ordre : « dépendances entre ressources ». +Lorsque vous incluez plusieurs fichiers CSS ou JavaScript dans une page Web, ils doivent respecter un certain ordre pour éviter des problèmes de redéfinition. +Par exemple, si vous utilisez l'objet graphique jQuery Ui dans une page Web, vous devez vous assurer que le fichier JavaScript jQuery est inclus avant le fichier JavaScript jQuery UI. +Nous appelons un tel ordre : « dépendances entre ressources ». -Les dépendances entre ressources sont essentiellement spécifiées via la propriété [[yii\web\AssetBundle::depends]]. Dans l'exemple `AppAsset`, le paquet de ressources dépend de deux autres paquets de ressources : [[yii\web\YiiAsset]] et [[yii\bootstrap\BootstrapAsset]], ce qui veut dire que les fichiers CSS et JavaScript dans `AppAsset` sont inclus *après* les fichiers contenus dans ces deux paquets de ressources dont ils dépendent. + +Les dépendances entre ressources sont essentiellement spécifiées via la propriété +[[yii\web\AssetBundle::depends]]. +Dans l'exemple `AppAsset`, le paquet de ressources dépend de deux autres paquets de ressources : [[yii\web\YiiAsset]] et [[yii\bootstrap\BootstrapAsset]], +ce qui veut dire que les fichiers CSS et JavaScript dans `AppAsset` sont inclus *après* les fichiers contenus dans ces deux paquets de ressources dont ils dépendent. Les dépendances entre ressources sont transitives. Cela veut dire que si un paquet de ressources A dépend d'un paquet B qui lui-même dépend de C, A dépend de C également. ### Options des ressources -Vous pouvez spécifier les propriétés [[yii\web\AssetBundle::cssOptions|cssOptions]] et [[yii\web\AssetBundle::jsOptions|jsOptions]] pour personnaliser la manière dont les fichiers CSS et JavaScript sont inclus dans une page. Les valeurs de ces propriétés sont passées aux méthodes [[yii\web\View::registerCssFile()]] et [[yii\web\View::registerJsFile()]] , respectivement, lorsqu'elles sont appelées par la [vue](structure-views.md) pour inclure les fichiers CSS et JavaScript. +Vous pouvez spécifier les propriétés [[yii\web\AssetBundle::cssOptions|cssOptions]] et [[yii\web\AssetBundle::jsOptions|jsOptions]] +pour personnaliser la manière dont les fichiers CSS et JavaScript sont inclus dans une page. +Les valeurs de ces propriétés sont passées aux méthodes [[yii\web\View::registerCssFile()]] et [[yii\web\View::registerJsFile()]], respectivement, lorsqu'elles sont appelées par la + [vue](structure-views.md) pour inclure les fichiers CSS et JavaScript. -> Note: les options que vous définissez dans une classe de paquet de ressources s'appliquent à *chacun des* fichiers CSS/JavaScript du paquet. Si vous voulez utiliser des options différentes entre fichiers, vous devez créer des paquets de ressources séparés, et utiliser un jeu d'options différent par paquet. +> Note: les options que vous définissez dans une classe de paquet de ressources s'appliquent à *chacun des* fichiers CSS/JavaScript du paquet. +Si vous voulez utiliser des options différentes entre fichiers, vous devez utiliser le format indiqué [[yii\web\AssetBundle::css|ci-dessus]] + ou créer des paquets de ressources séparés et utiliser un jeu d'options dans chacun des paquets. Par exemple, pour inclure un fichier CSS sous condition que le navigateur soit IE9 ou inférieur, vous pouvez utiliser l'option suivante : @@ -113,7 +174,11 @@ Pour inclure un fichier JavaScript dans la section d'entête d'une page (par dé public $jsOptions = ['position' => \yii\web\View::POS_HEAD]; ``` -Par défaut, lorsqu'un paquet de ressources est publié, tous les contenus dans le dossier spécifié par la propriété [[yii\web\AssetBundle::sourcePath]] sont publiés. Vous pouvez personnaliser ce comportement en configurant la propriété [[yii\web\AssetBundle::publishOptions|publishOptions]]. Par exemple, pour publier seulement un ou quelques sous-dossiers du dossier spécifié par la propriété [[yii\web\AssetBundle::sourcePath]], vous pouvez procéder comme ceci dans la classe du paquet de ressources : +Par défaut, lorsqu'un paquet de ressources est publié, tous les contenus dans le dossier spécifié par la propriété [[yii\web\AssetBundle::sourcePath]] + sont publiés. +Vous pouvez personnaliser ce comportement en configurant la propriété [[yii\web\AssetBundle::publishOptions|publishOptions]]. +Par exemple, pour publier seulement un ou quelques sous-dossiers du dossier spécifié par la propriété [[yii\web\AssetBundle::sourcePath]], +vous pouvez procéder comme ceci dans la classe du paquet de ressources : ```php +### Installation des ressources Bower et NPM + +La plupart des paquets JavaScript/CSS sont gérés par le gestionnaire de paquets [Bower](http://bower.io/) et/ou le gestionnaire de paquets [NPM](https://www.npmjs.org/). Dans le monde PHP, nous disposons de Composer, qui gère les dépendances, mais il est possible de charger des paquets Bower et NPM comme des paquets PHP en utilisant `composer.json`. + +Pour cela, nous devons configurer quelque peu notre composer. Il y a deux options possibles : + +___ + +#### En utilisant le dépôt asset-packagist + +Cette façon de faire satisfera les exigences de la majorité des projets qui ont besoin de paquets Bower ou NPM. + +> Note: depuis la version 2.0.13, les modèles de projet Basic et Advanced sont tous deux configuré pour utiliser asset-packagist par défaut, c'est pourquoi, vous pouvez sauter cette section. + +Dans le fichier `composer.json` de votre projet, ajoutez les lignes suivantes : + +```json +"repositories": [ + { + "type": "composer", + "url": "https://asset-packagist.org/" + } +] +``` + +Ajustez les [aliases](concept-aliases.md) `@npm` et `@bower` dans la [configuration](concept-configurations.md) de votre application : + +```php +$config = [ + ... + 'aliases' => [ + '@bower' => '@vendor/bower-asset', + '@npm' => '@vendor/npm-asset', + ], + ... +]; +``` + +Visitez [asset-packagist.org](https://asset-packagist.org) pour savoir comment il fonctionne. -La plupart des paquets JavaScript/CSS sont gérés par [Bower](http://bower.io/) et/ou [NPM](https://www.npmjs.org/). Si votre application ou extension utilise un tel paquet, il est recommandé que vous suiviez ces étapes pour gérer vos ressources dans la bibliothèque : +#### En utilisant le fxp/composer-asset-plugin -1. Modifier le fichier `composer.json` de votre application ou extension et lister le paquet dans l'entrée `require`. Vous devez utiliser `bower-asset/PackageName` (pour les paquets Bower) ou `npm-asset/PackageName` (pour les paquets NPM ) pour faire référence à la bibliothèque. -2. Créer une classe de paquet de ressources et lister les fichiers JavaScript/CSS que vous envisagez d'utiliser dans votre application ou extension. Vous devez spécifier la propriété [[yii\web\AssetBundle::sourcePath|sourcePath]] comme étant `@bower/PackageName` ou `@npm/PackageName`. Cela est dû au fait que Composer installe le paquet Bower ou NPM dans le dossier correspondant à cet alias. +Comparé à asset-packagist, composer-asset-plugin ne nécessite aucun changement dans la configuration de l'application. Au lieu de cela, il nécessite l'installation globale d'un greffon spécifique de Composer en exécutant la commande suivante : + +```bash +composer global require "fxp/composer-asset-plugin:^1.4.1" +``` -> Note: quelques paquets peuvent placer les fichiers distribués dans un sous-dossier. Si c'est le cas, vous devez spécifier le sous-dossier comme étant la valeur du [[yii\web\AssetBundle::sourcePath|chemin des sources]]. Par exemple, [[yii\web\JqueryAsset]] - utilise `@bower/jquery/dist` au lieu de `@bower/jquery`. +Cette commande installe [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/) globalement, ce qui permet de gérer les dépendances des paquets Bower et NPM via Composer. Après l'installation du greffon, tout projet de votre ordinateur prendra en charge les paquets Bower et NPM via `composer.json`. + +Ajoutez les lignes suivantes au fichier `composer.json` de votre projet pour préciser les dossiers où seront installés les paquets, si vous voulez les publier en utilisant Yii : + +```json +"config": { + "asset-installer-paths": { + "npm-asset-library": "vendor/npm", + "bower-asset-library": "vendor/bower" + } +} +``` + +> Note: `fxp/composer-asset-plugin` ralentit significativement la commande `composer update` en comparaison avec asset-packagist. + +____ + +Après avoir configuré Composer pour qu'il prenne en charge Bower et NPM : + +1. Modifiez le fichier the `composer.json` de votre application ou extension et listez le paquet dans l'entrée `require`. + Vous devez utiliser `bower-asset/PackageName` (pour les paquets Bower) ou `npm-asset/PackageName` (pour les paquets NPM) pour faire référence à la bibliothèque. +2. Exécutez `composer update` +3. Créez une classe de paquet de ressources et listez les fichiers JavaScript/CSS que vous envisagez d'utiliser dans votre application ou extension. + Vous devez spécifier la propriété [[yii\web\AssetBundle::sourcePath|sourcePath]] comme `@bower/PackageName` ou `@npm/PackageName`. + Cela parce que Composer installera le paquet Bower ou NPM dans le dossier correspondant à cet alias. + +> Note: quelques paquets peuvent placer tous leurs fichiers distribués dans un sous-dossier. Si c'est le cas, vous devez spécifier le sous-dossier en tant que valeur de [[yii\web\AssetBundle::sourcePath|sourcePath]]. Par exemple, utilisez [[yii\web\JqueryAsset]] `@bower/jquery/dist` au lieu de `@bower/jquery`. ## Utilisation des paquets de ressources @@ -166,6 +297,46 @@ Si vous êtes en train d'enregistrer un paquet de ressources dans d'autres endro Lorsqu'un paquet de ressources est enregistré avec une vue, en arrière plan. Yii enregistre tous les paquets de ressources dont il dépend. Et si un paquet de ressources est situé dans un dossier inaccessible depuis le Web, il est publié dans un dossier accessible depuis le Web. Plus tard, lorsque la vue rend une page, elle génère les balises `` et `` と入力した場合、ユーザ名をエスケープせずに出力している全てのページでは、JavaScript `alert('Hello!');` が実行されて、ブラウザにアラート・ボックスがポップアップ表示されます。 -ウェブ・サイト次第では、そのようなスクリプトを使って、無害なアラートではなく、あなたの名前を使ってメッセージを送信したり、さらには銀行取引を実行したりすることが可能です。 +例えば、ユーザ名を入力できるフォームで `Alexander` の代りに `` と入力した場合、 +ユーザ名をエスケープせずに出力している全てのページでは、JavaScript `alert('Hello!');` が実行されて、ブラウザにアラート・ボックスがポップアップ表示されます。 +ウェブ・サイト次第では、そのようなスクリプトを使って、無害なアラートではなく、あなたの名前を使ってメッセージを送信したり、 +さらには銀行取引を実行したりすることが可能です。 XSS の回避は、Yii においてはとても簡単です。一般に、二つのケースがあります。 -1. データを平文テキストとして出力したい。 +1. データをプレーン・テキストとして出力したい。 2. データを HTML として出力したい。 -平文テキストしか必要でない場合は、エスケープは次のようにとても簡単です。 +プレーン・テキストしか必要でない場合は、エスケープは次のようにとても簡単です。 ```php @@ -157,26 +160,29 @@ CSRF を回避する CSRF は、クロス・サイト・リクエスト・フォージェリ (cross-site request forgery) の略称です。 多くのアプリケーションは、ユーザのブラウザから来るリクエストはユーザ自身によって発せられたものだと仮定しているけれども、その仮定は間違っているかもしれない ... というのが CSRF の考え方です。 -例えば、`an.example.com` というウェブ・サイトが `/logout` という URL を持っており、この URL を単純な GET でアクセスするとユーザをログアウトさせるようになっているとします。 -ユーザ自身によってこの URL がリクエストされる限りは何も問題はありませんが、ある日、悪い奴が、ユーザが頻繁に訪れるフォーラムに `` というリンクを含むコンテントを何とかして投稿することに成功します。 +例えば、`an.example.com` というウェブ・サイトが `/logout` という URL を持っており、 +この URL を単純な GET でアクセスするとユーザをログアウトさせるようになっているとします。 +ユーザ自身によってこの URL がリクエストされる限りは何も問題はありませんが、ある日、悪い奴が、ユーザが頻繁に訪れるフォーラムに `` というリンクを含むコンテントを何らかの方法で投稿します。 ブラウザは画像のリクエストとページのリクエストの間に何ら区別を付けませんので、ユーザがそのような `img` タグを含むページを開くとブラウザはその URL に対して GET リクエストを送信します。 そして、ユーザが `an.example.com` からログアウトされてしまうことになる訳です。 -これは基本的な考え方です。ユーザがログアウトされるぐらいは大したことではない、と言うことも出来るでしょう。 -しかし、悪い奴は、この考え方を使って、もっとひどいことをすることも出来ます。 -例えば、`http://an.example.com/purse/transfer?to=anotherUser&amount=2000` という URL を持つウェブ・サイトがあると考えて見てください。 -この URL に GET リクエストを使ってアクセスすると、権限を持つユーザア・カウントから `anotherUser` に $2000 が送金されるのです。 -私たちは、ブラウザは画像をロードするのに常に GET リクエストを使う、ということを知っていますから、この URL が POST リクエストだけを受け入れるようにコードを修正することは出来ます。 -しかし残念なことに、それで問題が解決する訳ではありません。 -攻撃者は `` タグの代りに何らかの JavaScript コードを書いて、その URL に対する POST リクエストの送信を可能にすることが出来ます。 +これは CSRF 攻撃がどのように動作するかという基本的な考え方です。ユーザがログアウトされるぐらいは大したことではない、と言うことも出来るでしょう。 +しかしこれは例に過ぎません。この考え方を使って、支払いを開始させたり、データを変更したりというような、もっとひどいことをすることも出来ます。 +`http://an.example.com/purse/transfer?to=anotherUser&amount=2000` という URL を持つウェブ・サイトがあると考えて見てください。この URL に GET リクエストを使ってアクセスすると、権限を持つユーザ・アカウントから `anotherUser` に $2000 が送金されるのです。 +私たちは、ブラウザは画像をロードするのに常に GET リクエストを使う、ということを知っていますから、 +この URL が POST リクエストだけを受け入れるようにコードを修正することは出来ます。 +しかし残念なことに、それで問題が解決する訳ではありません。攻撃者は `` タグの代りに何らかの JavaScript コードを書いて、 +その URL に対する POST リクエストの送信を可能にすることが出来ます。 + +これを理由として、Yii は CSRF 攻撃を防御するための追加のメカニズムを適用します。 CSRF を回避するためには、常に次のことを守らなければなりません。 1. HTTP の規格、すなわち、GET はアプリケーションの状態を変更すべきではない、という規則に従うこと。 + 詳細は [RFC2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) を参照して下さい。 2. Yii の CSRF 保護を有効にしておくこと。 -場合によっては、コントローラやアクションの単位で CSRF 検証を無効化する必要があることがあるでしょう。 -これは、そのプロパティを設定することによって達成することが出来ます。 +場合によっては、コントローラやアクションの単位で CSRF 検証を無効化する必要があることがあるでしょう。これは、そのプロパティを設定することによって達成することが出来ます。 ```php namespace app\controllers; @@ -196,6 +202,7 @@ class SiteController extends Controller ``` 特定のアクションに対して CSRF 検証を無効化したいときは、次のようにすることが出来ます。 + ```php namespace app\controllers; @@ -244,8 +251,7 @@ class ContactAction extends Action } ``` -> Warning: CSRF を無効化すると、あらゆるサイトから POST リクエストをあなたのサイトに送信することが出来るようになります。 - その場合には、IP アドレスや秘密のトークンをチェックするなど、追加の検証を実装することが重要です。 +> Warning: CSRF を無効化すると、あらゆるサイトから POST リクエストをあなたのサイトに送信することが出来るようになります。その場合には、IP アドレスや秘密のトークンをチェックするなど、追加の検証を実装することが重要です。 このトピックについて更に読むべき文書: @@ -260,6 +266,7 @@ class ContactAction extends Action そういう場合には、`web` 以外の全てに対してアクセスを拒否することを忘れないでください。 それも出来ない場合は、アプリケーションを別の場所でホストすることを検討してください。 + 本番環境ではデバッグ情報とデバッグ・ツールを無効にする ------------------------------------------------------ @@ -270,8 +277,7 @@ class ContactAction extends Action 本番環境では Gii やデバッグ・ツール・バーを決して有効にしてはいけません。 これらを有効にすると、データベース構造とコードに関する情報を得ることが出来るだけでなく、コードを Gii によって生成したもので書き換えることすら出来てしまいます。 -デバッグ・ツール・バーは本当に必要でない限り本番環境では使用を避けるべきです。 -これはアプリケーションと構成情報の全ての詳細を曝露することが出来ます。 +デバッグ・ツール・バーは本当に必要でない限り本番環境では使用を避けるべきです。これはアプリケーションと構成情報の全ての詳細を曝露することが出来ます。 どうしても必要な場合は、あなたの IP だけに適切にアクセス制限されていることを再度チェックしてください。 このトピックについて更に読むべき文書: @@ -283,10 +289,8 @@ class ContactAction extends Action TLS によるセキュアな接続を使う ------------------------------ -Yii が提供する機能には、クッキーや PHP セッションに依存するものがあります。 -これらのものは、接続が侵害された場合には、脆弱性となり得ます。 -アプリケーションが TLS (しばしば [SSL](https://ja.wikipedia.org/wiki/Transport_Layer_Security) と呼ばれます) -によるセキュアな接続を使用している場合は、この危険性を減少させることが出来ます。 +Yii が提供する機能には、クッキーや PHP セッションに依存するものがあります。これらのものは、接続が侵害された場合には、脆弱性となり得ます。 +アプリケーションが TLS (しばしば [SSL](https://ja.wikipedia.org/wiki/Transport_Layer_Security) と呼ばれます) によるセキュアな接続を使用している場合は、この危険性を減少させることが出来ます。 その設定の仕方については、あなたのウェブ・サーバのドキュメントの指示を参照してください。 H5BP プロジェクトが提供する構成例を参考にすることも出来ます。 @@ -296,6 +300,7 @@ H5BP プロジェクトが提供する構成例を参考にすることも出来 - [IIS](https://github.com/h5bp/server-configs-iis). - [Lighttpd](https://github.com/h5bp/server-configs-lighttpd). + サーバの構成をセキュアにする ---------------------------- @@ -307,19 +312,19 @@ H5BP プロジェクトが提供する構成例を参考にすることも出来 ### `Host` ヘッダ攻撃を避ける [[yii\web\UrlManager]] や [[yii\helpers\Url]] のクラスは、リンクを生成するために [[yii\web\Request::getHostInfo()|現在リクエストされているホスト名]] を使うことがあります。 -って ウェブ・サーバが `Host` ヘッダの値とは無関係に同じサイトとして応答するように構成されている場合は、 -この情報は [HTTP リクエストを送信するユーザによって偽装され](https://www.acunetix.com/vulnerabilities/web/host-header-attack) て、信頼できないものになっている可能性があります。 +この情報は信頼できないものになっており、[HTTP リクエストを送信するユーザによって偽装されている](https://www.acunetix.com/vulnerabilities/web/host-header-attack) 可能性があります。 そのような状況においては、ウェブ・サーバの構成を改修して、指定されたホスト名に対してのみ応答するようにするか、 -または、`request` アプリケーション・コンポーネントの [[yii\web\Request::setHostInfo()|hostInfo]] プロパティを設定して、ホスト名の値を設定ないしフィルタするか、 -どちらかの対策を取るべきです。 +または、`request` アプリケーション・コンポーネントの [[yii\web\Request::setHostInfo()|hostInfo]] プロパティを設定して、 +ホスト名の値を明示的に設定ないしフィルタするか、どちらかの対策を取るべきです。 サーバの構成についての詳細な情報は、ウェブ・サーバのドキュメントを参照して下さい。 - Apache 2: - Nginx: -サーバの構成にアクセスする権限がない場合は、このような攻撃に対して防御するために、[[yii\filters\HostControl]] フィルタを設定することが出来ます。 +サーバの構成にアクセスする権限がない場合は、このような攻撃に対して防御するために、[[yii\filters\HostControl]] +フィルタを設定することが出来ます。 ```php // ウェブ・アプリケーション構成ファイル diff --git a/docs/guide-ja/security-cryptography.md b/docs/guide-ja/security-cryptography.md index e782a92c991..9095fdce5aa 100644 --- a/docs/guide-ja/security-cryptography.md +++ b/docs/guide-ja/security-cryptography.md @@ -1,20 +1,18 @@ 暗号化 ====== -個のセクションでは、セキュリティの以下の側面について見ていきます。 +このセクションでは、セキュリティの以下の側面について見ていきます。 - 乱数データの生成 - 暗号化と複合化 - データの完全性の確認 - 擬似乱数データを生成する ------------------------ 擬似乱数データはさまざまな状況で役に立ちます。 例えば、メール経由でパスワードをリセットするときは、トークンを生成してデータベースに保存し、それをユーザにメールで送信します。 -そして、ユーザはこのトークンを自分がアカウントの所有者であることの証拠として使用します。 -このトークンがユニークかつ推測困難なものであることは非常に重要なことです。 +そして、ユーザはこのトークンを自分がアカウントの所有者であることの証拠として使用します。このトークンがユニークかつ推測困難なものであることは非常に重要なことです。 さもなくば、攻撃者がトークンの値を推測してユーザのパスワードをリセットする可能性があります。 Yii のセキュリティヘルパは擬似乱数データの生成を単純な作業にしてくれます。 @@ -27,10 +25,10 @@ $key = Yii::$app->getSecurity()->generateRandomString(); 暗号化と復号化 -------------- -Yii は秘密鍵を使ってデータを暗号化/復号化することを可能にする便利なヘルパ関数を提供しています。 -データを暗号化関数に渡して、秘密鍵を持つ者だけが復号化することが出来るようにすることが出来ます。 +Yii は秘密鍵を使ってデータを暗号化/復号化することを可能にする便利なヘルパ関数を提供しています。データを暗号化関数に渡して、秘密鍵を持つ者だけが復号化することが出来るようにすることが出来ます。 例えば、何らかの情報をデータベースに保存する必要があるけれども、(たとえアプリケーションのデータベースが第三者に漏洩した場合でも) 秘密鍵を持つユーザだけがそれを見ることが出来るようにする必要がある、という場合には次のようにします。 + ```php // $data と $secretKey はフォームから取得する $encryptedData = Yii::$app->getSecurity()->encryptByPassword($data, $secretKey); @@ -44,17 +42,17 @@ $encryptedData = Yii::$app->getSecurity()->encryptByPassword($data, $secretKey); $data = Yii::$app->getSecurity()->decryptByPassword($encryptedData, $secretKey); ``` -[[\yii\base\Security::encryptByKey()]] と [[\yii\base\Security::decryptByKey()]] によって、パスワードの代わりにキーを使うことも可能です。 - +[[\yii\base\Security::encryptByKey()]] と [[\yii\base\Security::decryptByKey()]] によって、 +パスワードの代わりにキーを使うことも可能です。 データの完全性を確認する ------------------------ -データが第三者によって改竄されたり、更には何らかの形で毀損されたりしていないことを確認する必要がある、という場合があります。 -Yii は二つのヘルパ関数の形で、データの完全性を確認するための簡単な方法を提供しています。 +データが第三者によって改竄されたり、更には何らかの形で毀損されたりしていないことを確認する必要がある、という場合があります。Yii は二つのヘルパ関数の形で、データの完全性を確認するための簡単な方法を提供しています。 秘密鍵とデータから生成されたハッシュをデータにプレフィクスします。 + ```php // $secretKey はアプリケーションまたはユーザの秘密、$genuineData は信頼できるソースから取得 $data = Yii::$app->getSecurity()->hashData($genuineData, $secretKey); diff --git a/docs/guide-ja/security-passwords.md b/docs/guide-ja/security-passwords.md index d9c91a40e7e..69854134f2d 100644 --- a/docs/guide-ja/security-passwords.md +++ b/docs/guide-ja/security-passwords.md @@ -1,11 +1,12 @@ パスワードを扱う ================ -ほとんどの開発者はパスワードを平文テキストで保存してはいけないということを知っていますが、パスワードを `md5` や `sha1` でハッシュしてもまだ安全だと思っている開発者がたくさんいます。 -かつては、前述のハッシュ・アルゴリズムを使えば十分であった時もありましたが、現代のハードウェアをもってすれば、そのようなハッシュはブルート・フォース・アタックを使って非常に簡単に復元することが可能です。 +ほとんどの開発者はパスワードを平文テキストで保存してはいけないということを知っていますが、パスワードを `md5` や `sha1` +でハッシュしてもまだ安全だと思っている開発者がたくさんいます。かつては、前述のハッシュ・アルゴリズムを使えば十分であった時もありましたが、 +現代のハードウェアをもってすれば、そのようなハッシュはブルート・フォース・アタックを使って非常に簡単に復元することが可能です。 -最悪のシナリオ (アプリケーションに侵入された場合) であっても、ユーザのパスワードについて強化されたセキュリティを提供することが出来るように、ブルート・フォース・アタックに対する耐性が強いハッシュ・アルゴリズムを使う必要があります。 -現在、最善の選択は `bcrypt` です。 +最悪のシナリオ (アプリケーションに侵入された場合) であっても、ユーザのパスワードについて強化されたセキュリティを提供することが出来るように、 +ブルート・フォース・アタックに対する耐性が強いハッシュ・アルゴリズムを使う必要があります。現在、最善の選択は `bcrypt` です。 PHP では、[crypt 関数](http://php.net/manual/ja/function.crypt.php) を使って `bcrypt` ハッシュを生成することが出来ます。 Yii は `crypt` を使ってハッシュを安全に生成し検証することを容易にするために、二つのヘルパ関数を提供しています。 diff --git a/docs/guide-ja/start-databases.md b/docs/guide-ja/start-databases.md index a90666decb8..d1e2d84249f 100644 --- a/docs/guide-ja/start-databases.md +++ b/docs/guide-ja/start-databases.md @@ -2,13 +2,15 @@ ================== このセクションでは、`country` という名前のデータベース・テーブルから読み出した国データを表示する新しいページの作り方を説明します。 -この目的を達するために、データベース接続を構成し、[アクティブレコード](db-active-record.md) クラスを作成し、[アクション](structure-controllers.md) を定義し、そして [ビュー](structure-views.md) を作成します。 +この目的を達するために、データベース接続を構成し、 +[アクティブ・レコード](db-active-record.md) クラスを作成し、[アクション](structure-controllers.md) を定義し、 +そして [ビュー](structure-views.md) を作成します。 このチュートリアルを通じて、次のことを学びます。 * DB 接続を構成する方法 -* アクティブレコードのクラスを定義する方法 -* アクティブレコードのクラスを使ってデータを検索する方法 +* アクティブ・レコードのクラスを定義する方法 +* アクティブ・レコードのクラスを使ってデータを検索する方法 * 改ページを伴う仕方でビューにデータを表示する方法 このセクションを完了するためには、データベースを使うことについて基本的な知識と経験が無ければならないことに注意してください。 @@ -19,11 +21,11 @@ ---------------------- まず初めに、`yii2basic` という名前のデータベースを作成してください。このデータベースからアプリケーションにデータを読み出すことになります。 -Yii は多数のデータベース製品に対するサポートを内蔵していますので、作成するデータベースは、SQLite、MySQL、PosttreSQL、MSSQL または Oracle から選ぶことが出来ます。 -以下の説明では、話を単純にするために、MySQL を前提とします。 +Yii は多数のデータベース製品に対するサポートを内蔵しており、作成するデータベースは、SQLite、MySQL、PosttreSQL、MSSQL または Oracle から選ぶことが出来ます。以下の説明では、話を単純にするために、MySQL を前提とします。 -次に、データベースに `country` という名前のテーブルを作り、いくつかのサンプル・データを挿入します。 -そうするためには、次の SQL 文を実行することが出来ます。 +> Info: MariaDB は、かつては MySQL と差し替え可能な代替物でしたが、現在では完全にそうだとは言えません。MariaDB で `JSON` サポートのような高度な機能を使いたいときは、後述する MariaDB エスステンションの使用を検討して下さい。 + +次に、データベースに `country` という名前のテーブルを作り、いくつかのサンプル・データを挿入します。そうするためには、次の SQL 文を実行することが出来ます。 ```sql CREATE TABLE `country` ( @@ -46,11 +48,11 @@ INSERT INTO `country` VALUES ('US','United States',322976000); この時点で、あなたは `yii2basic` という名前のデータベースを持ち、その中に三つのカラムを持つ `country` というテーブルがあり、`country` テーブルは 10 行のデータを持っている、ということになります。 - DB 接続を構成する ----------------- -先に進む前に、[PDO](http://www.php.net/manual/en/book.pdo.php) PHP 拡張および使用しているデータベースの PDO ドライバ (例えば、MySQL のための `pdo_mysql`) の両方をインストール済みであることを確認してください。 +先に進む前に、[PDO](http://www.php.net/manual/en/book.pdo.php) PHP 拡張および使用しているデータベースの PDO ドライバ +(例えば、MySQL のための `pdo_mysql`) の両方をインストール済みであることを確認してください。 アプリケーションがリレーショナル・データベースを使う場合、これは基本的な必要条件です。 これらがインストール済みなら、`config/db.php` というファイルを開いて、あなたのデータベースに適合するようにパラメータを変更してください。 @@ -68,25 +70,29 @@ return [ ]; ``` -この `config/db.php` というファイルは典型的なファイルベースの [構成情報](concept-configurations.md) ツールです。 -この構成情報ファイルが、背後のデータベースに対する SQL クエリの実行を可能にする [[yii\db\Connection]] インスタンスの作成と初期化に必要なパラメータを指定するものです。 +この `config/db.php` というファイルは典型的なファイル・ベースの [構成情報](concept-configurations.md) ツールです。 +この構成情報ファイルが、背後のデータベースに対する SQL クエリの実行を可能にする [[yii\db\Connection]] +インスタンスの作成と初期化に必要なパラメータを指定するものです。 上記のようにして構成された DB 接続は、アプリケーション・コードの中で `Yii::$app->db` という式でアクセスすることが出来ます。 > Info: `config/db.php` は、メインのアプリケーション構成情報ファイルである `config/web.php` によってインクルードされます。 この `config/web.php` が [アプリケーション](structure-applications.md) インスタンスが初期化される仕方を指定するものです。 詳しい情報については、[構成情報](concept-configurations.md) のセクションを参照してください。 + Yii がサポートを内蔵していないデータベースを扱う必要がある場合は、以下のエクステンションの利用を検討してください。 - [Informix](https://github.com/edgardmessias/yii2-informix) - [IBM DB2](https://github.com/edgardmessias/yii2-ibm-db2) - [Firebird](https://github.com/edgardmessias/yii2-firebird) +- [MariaDB](https://github.com/sam-it/yii2-mariadb) -アクティブレコードを作成する ----------------------------- +アクティブ・レコードを作成する +------------------------------ -`country` テーブルの中のデータを表現し取得するために、[アクティブレコード](db-active-record.md) から派生した `Country` という名前のクラスを作成し、それを `models/Country.php` というファイルに保存します。 +`country` テーブルの中のデータを表現し取得するために、[アクティブ・レコード](db-active-record.md) から派生した `Country` という名前のクラスを作成し、 +それを `models/Country.php` というファイルに保存します。 ```php Info: クラス名とテーブル名を直接に合致させることが出来ない場合は、[[yii\db\ActiveRecord::tableName()]] メソッドをオーバーライドして、関連づけられたテーブル名を明示的に指定することが出来ます。 +> Info: クラス名とテーブル名を直接に合致させることが出来ない場合は、[[yii\db\ActiveRecord::tableName()]] +メソッドをオーバーライドして、関連づけられたテーブル名を明示的に指定することが出来ます。 `Country` クラスを使うことによって、以下のコード断片で示すように、`country` テーブルの中のデータを簡単に操作することが出来ます。 @@ -124,8 +131,7 @@ $country->name = 'U.S.A.'; $country->save(); ``` -> Info: アクティブレコードは、オブジェクト指向の流儀でデータベースのデータにアクセスし、操作する強力な方法です。 -[アクティブレコード](db-active-record.md) のセクションで、詳細な情報を得ることが出来ます。 +> Info: アクティブ・レコードは、オブジェクト指向の流儀でデータベースのデータにアクセスし、操作する強力な方法です。[アクティブ・レコード](db-active-record.md) のセクションで、詳細な情報を得ることが出来ます。 もう一つの方法として、[データベース・アクセス・オブジェクト](db-dao.md) と呼ばれる、より低レベルなデータ・アクセス方法を使ってデータベースを操作することも出来ます。 @@ -172,13 +178,14 @@ class CountryController extends Controller 上記のコードを `controllers/CountryController.php` というファイルに保存します。 -`index` アクションは `Country::find()` を呼び出します。 -このアクティブレコードのメソッドは DB クエリを構築して、`country` テーブルから全てのデータを読み出します。 +`index` アクションは `Country::find()` を呼び出します。このアクティブ・レコードのメソッドは `country` テーブルから全てのデータを読み出すことが可能な DB クエリを構築します。 一回のリクエストで返される国の数を制限するために、クエリは [[yii\data\Pagination]] オブジェクトの助けを借りてページ付けされます。 `Pagination` オブジェクトは二つの目的に奉仕します。 -* クエリによって表現される SQL 文に `offset` 句と `limit` 句をセットして、一度に一ページ分のデータだけ (1ページ最大5行) を返すようにします。 -* 次の項で説明されるように、一連のページ・ボタンからなるページャをビューに表示するために使われます。 +* クエリによって表現される SQL 文に `offset` 句と `limit` 句をセットして、 + 一度に一ページ分のデータだけ (1ページ最大5行) を返すようにします。 +* 次の項で説明されるように、一連のページ・ボタンからなるページャを + ビューに表示するために使われます。 コードの最後で、`index` アクションは `index` と言う名前のビューをレンダリングしています。 このとき、国データだけでなく、そのページネーション情報がビューに渡されます。 @@ -226,8 +233,7 @@ http://hostname/index.php?r=country%2Findex ![国リスト](images/start-country-list.png) -最初、ページは5つの国を表示しています。 -そして、国リストの下には、4つのボタンを持ったページャがあります。 +最初、ページは5つの国を表示しています。そして、国リストの下には、4つのボタンを持ったページャがあります。 "2" のボタンをクリックすると、ページはデータベースにある次の5つの国、すなわち、2ページ目のレコードを表示します。 注意深く観察すると、ブラウザの URL も次のように変ったことに気付くでしょう。 @@ -235,16 +241,17 @@ http://hostname/index.php?r=country%2Findex http://hostname/index.php?r=country%2Findex&page=2 ``` -舞台裏では、[[yii\data\Pagination|Pagination]] が、データセットをページ付けするのに必要な全ての機能を提供しています。 +舞台裏では、[[yii\data\Pagination|Pagination]] が、データ・セットをページ付けするのに必要な全ての機能を提供しています。 * 初期状態では、[[yii\data\Pagination|Pagination]] は、1ページ目を表しています。 - これを反映して、国の SELECT クエリは `LIMIT 5 OFFSET 0` という句を伴うことになります。 - その結果、最初の5つの国が取得されて表示されます。 -* [[yii\widgets\LinkPager|LinkPager]] ウィジェットは、[[yii\data\Pagination::createUrl()|Pagination]] によって作成された URL を使ってページ・ボタンをレンダリングします。 + これを反映して、国の SELECT クエリは `LIMIT 5 OFFSET 0` という句を伴うことになります。その結果、最初の5つの国が取得されて表示されます。 +* [[yii\widgets\LinkPager|LinkPager]] ウィジェットは、[[yii\data\Pagination::createUrl()|Pagination]] によって作成された + URL を使ってページ・ボタンをレンダリングします。 URL は、別々のページ番号を表現する `page` というクエリ・パラメータを含んだものになります。 -* ページボタン "2" をクリックすると、`country/index` のルートに対する新しいリクエストが発行され、処理されます。 +* ページ・ボタン "2" をクリックすると、`country/index` のルートに対する新しいリクエストが発行され、処理されます。 [[yii\data\Pagination|Pagination]] が URL から `page` クエリ・パラメータを読み取って、カレント・ページ番号を 2 にセットします。 - こうして、新しい国のクエリは `LIMIT 5 OFFSET 5` という句を持ち、次の5つの国を表示のために返すことになります。 + こうして、新しい国のクエリは `LIMIT 5 OFFSET 5` という句を持ち、 + 次の5つの国を表示のために返すことになります。 まとめ @@ -253,6 +260,7 @@ http://hostname/index.php?r=country%2Findex&page=2 このセクションでは、データベースを扱う方法を学びました。 また、[[yii\data\Pagination]] と [[yii\widgets\LinkPager]] の助けを借りて、ページ付けされたデータを取得し表示する方法も学びました。 -次のセクションでは、[Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-ja/README.md) と呼ばれる強力なコード生成ツールを使う方法を学びます。 -このツールは、データベース・テーブルのデータを取り扱うための「作成・読出し・更新・削除 (CRUD)」操作のような、通常必要とされることが多いいくつかの機能の迅速な実装を手助けしてくれるものです。 +次のセクションでは、[Gii](https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide) と呼ばれる強力なコード生成ツールを使う方法を学びます。 +このツールは、データベース・テーブルのデータを取り扱うための「作成・読出し・更新・削除 (CRUD)」操作のような、 +通常必要とされることが多い諸機能の迅速な実装を手助けしてくれるものです。 実際のところ、あなたがたった今書いたばかりのコードは、Gii ツールを使えば、全部、Yii が自動的に生成してくれるものです。 diff --git a/docs/guide-ja/start-forms.md b/docs/guide-ja/start-forms.md index 635b7ecb4ac..fb22618dcff 100644 --- a/docs/guide-ja/start-forms.md +++ b/docs/guide-ja/start-forms.md @@ -3,9 +3,10 @@ このセクションでは、ユーザからデータを取得するためのフォームを持つ新しいページを作る方法を説明します。 このページは名前のインプット・フィールドとメールのインプット・フィールドを持つフォームを表示します。 -ユーザからこれら二つの情報を受け取った後、ページは入力された値を確認のためにエコー・バックします。 +ユーザからこれら二つの情報を受け取った後、ウェブ・ページは確認のために入力された値をエコー・バックします。 -この目的を達するために、一つの [アクション](structure-controllers.md) と 二つの [ビュー](structure-views.md) を作成する以外に、一つの [モデル](structure-models.md) をも作成します。 +この目的を達するために、一つの [アクション](structure-controllers.md) と 二つの [ビュー](structure-views.md) を作成する以外に、 +一つの [モデル](structure-models.md) をも作成します。 このチュートリアルを通じて、次の方法を学びます。 @@ -17,7 +18,8 @@ モデルを作成する ---------------- -ユーザに入力してもらうデータは、下に示されているように `EntryForm` モデル・クラスとして表現され、`models/EntryForm.php` というファイルに保存されます。 +ユーザに入力してもらうデータは、下に示されているように `EntryForm` モデル・クラスとして表現され、 +`models/EntryForm.php` というファイルに保存されます。 クラス・ファイルの命名規約についての詳細は [クラスのオートロード](concept-autoloading.md) のセクションを参照してください。 ```php @@ -44,7 +46,7 @@ class EntryForm extends Model ``` このクラスは、Yii によって提供される基底クラス [[yii\base\Model]] を拡張するものです。 -通常、この基底クラスがフォームデータを表現するのに使われます。 +通常、この基底クラスがフォーム・データを表現するのに使われます。 > Info: [[yii\base\Model]] はデータベース・テーブルと関連*しない*モデル・クラスの親として使われます。 データベース・テーブルと対応するモデル・クラスでは、通常は [[yii\db\ActiveRecord]] が親になります。 @@ -114,7 +116,8 @@ class SiteController extends Controller アクションは最初に `EntryForm` オブジェクトを生成します。 次に、モデルに `$_POST` のデータ、Yii においては [[yii\web\Request::post()]] によって提供されるデータを投入しようと試みます。 -モデルへのデータ投入が成功した場合(つまり、ユーザが HTML フォームを送信した場合)、アクションは[[yii\base\Model::validate()|validate()]] を呼んで、入力された値が有効なものであるかどうかを確認します。 +モデルへのデータ投入が成功した場合(つまり、ユーザが HTML フォームを送信した場合)、アクションは[[yii\base\Model::validate()|validate()]] を呼んで、 +入力された値が有効なものであるかどうかを確認します。 > Info: `Yii::$app` という式は [アプリケーション](structure-applications.md) インスタンスを表現します。 これはグローバルにアクセス可能なシングルトンです。 @@ -122,10 +125,12 @@ class SiteController extends Controller 上記のコードでは、アプリケーション・インスタンスの `request` コンポーネントが `$_POST` データにアクセスするために使われています。 すべてが適正である場合、アクションは `entry-confirm` という名前のビューを表示して、データの送信が成功したことをユーザに確認させます。 -データが送信されなかったり、データがエラーを含んでいたりする場合は、`entry` ビューが表示され、その中で HTML フォームが (もし有れば) 検証エラーのメッセージとともに表示されます。 +データが送信されなかったり、データがエラーを含んでいたりする場合は、`entry` ビューが表示され、 +その中で HTML フォームが (もし有れば) 検証エラーのメッセージとともに表示されます。 > Note: この簡単な例では、有効なデータ送信に対して単純に確認ページを表示しています。 - 実際の仕事では、[フォーム送信の諸問題](http://en.wikipedia.org/wiki/Post/Redirect/Get) を避けるために、[[yii\web\Controller::refresh()|refresh()]] または [[yii\web\Controller::redirect()|redirect()]] を使うことを考慮すべきです。 + 実際の仕事では、[フォーム送信の諸問題](http://en.wikipedia.org/wiki/Post/Redirect/Get) を避けるために、 + [[yii\web\Controller::refresh()|refresh()]] または [[yii\web\Controller::redirect()|redirect()]] を使うことを考慮すべきです。 ビューを作成する @@ -168,7 +173,8 @@ use yii\widgets\ActiveForm; ``` -このビューは HTML フォームを構築するのに、[[yii\widgets\ActiveForm|ActiveForm]] と呼ばれる強力な [ウィジェット](structure-widgets.md) を使います。 +このビューは HTML フォームを構築するのに、[[yii\widgets\ActiveForm|ActiveForm]] と呼ばれる強力な +[ウィジェット](structure-widgets.md) を使います。 ウィジェットの `begin()` メソッドと `end()` メソッドが、それぞれ、フォームの開始タグと終了タグをレンダリングします。 この二つのメソッドの呼び出しの間に、[[yii\widgets\ActiveForm::field()|field()]] メソッドによってインプット・フィールドが作成されます。 最初のインプット・フィールドは "name" のデータ、第二のインプット・フィールドは "email" のデータのためのものです。 @@ -184,34 +190,38 @@ use yii\widgets\ActiveForm; http://hostname/index.php?r=site%2Fentry ``` -二つのインプット・フィールドを持つフォームを表示するページが表示されるでしょう。 -それぞれのインプット・フィールドの前には、どんなデータを入力すべきかを示すラベルがあります。 +二つのインプット・フィールドを持つフォームを表示するページが表示されるでしょう。それぞれのインプット・フィールドの前には、どんなデータを入力すべきかを示すラベルがあります。 何も入力せずに、あるいは、無効なメール・アドレスを入力して送信ボタンをクリックすると、それぞれ問題のあるインプット・フィールドの後ろにエラー・メッセージが表示されます。 ![検証エラーのあるフォーム](images/start-form-validation.png) -有効な名前とメール・アドレスを入力してから送信ボタンをクリックすると、たった今入力したデータを表示する新しいページが表示されます。 +有効な名前とメール・アドレスを入力してから送信ボタンをクリックすると、 +たった今入力したデータを表示する新しいページが表示されます。 ![データ入力の確認](images/start-entry-confirmation.png) + ### 魔法の説明 あなたは、舞台裏で HTML フォームがどのように動いているのか、不思議に思うかも知れません。 -なぜなら、フォームが、ほとんど魔法のように、各インプット・フィールドのラベルを表示し、データを正しく入力しなかった場合には、ページをリロードすることなく、エラー・メッセージを表示するからです。 +なぜなら、フォームが、ほとんど魔法のように、各インプット・フィールドのラベルを表示し、データを正しく入力しなかった場合には、 +ページをリロードすることなく、エラー・メッセージを表示するからです。 そう、データの検証は、最初に JavaScript を使ってクライアント・サイドで実行され、次に PHP によってサーバ・サイドで実行されます。 -[[yii\widgets\ActiveForm]] は、賢いことに、`EntryForm` で宣言した検証規則を抽出し、それを実行可能な JavaScript コードに変換して、JavaScript を使ってデータ検証を実行します。 +[[yii\widgets\ActiveForm]] は、賢いことに、`EntryForm` で宣言した検証規則を抽出し、それを実行可能な JavaScript コードに変換して、 +JavaScript を使ってデータ検証を実行します。 ブラウザで JavaScript を無効にした場合でも、`actionEntry()` メソッドで示されているように、サーバ・サイドでの検証は引き続き実行されます。 これにより、どのような状況であっても、データの有効性が保証されます。 > Warning: クライアント・サイドの検証は、ユーザにとってのより良い使い心地のために利便性を提供するものです。 - クライアント・サイドの検証の有無にかかわらず、サーバ・サイドの検証は常に必要とされます。 + クライアント・サイドの検証の有無にかかわらず、サーバ・サイドの検証は常に必要です。 インプット・フィールドのラベルは、モデルのプロパティ名を使用して、`field()` メソッドによって生成されます。 例えば、`name` というプロパティから `Name` というラベルが生成されます。 -ビューの中で、下記のコードのように、ラベルをカスタマイズすることも出来ます。 +ビューの中で、下記のコードのように、 +ラベルをカスタマイズすることも出来ます。 ```php field($model, 'name')->label('お名前') ?> @@ -220,14 +230,14 @@ http://hostname/index.php?r=site%2Fentry > Info: Yii はこのようなウィジェットを数多く提供して、複雑で動的なビューを素速く作成することを手助けしてくれます。 後で学ぶように、新しいウィジェットを書くことも非常に簡単です。 - あなたは、将来のビュー開発を単純化するために、多くのビューコードを再利用可能なウィジェットに変換したいと思うことでしょう。 + あなたは、将来のビュー開発を単純化するために、多くのビュー・コードを再利用可能なウィジェットに変換したいと思うことでしょう。 まとめ ------ -ガイドのこのセクションにおいては、MVC アーキテクチャパターンの全ての部分に触れました。 -そして、ユーザデータを表現し、当該データを検証するモデル・クラスを作成する方法を学びました。 +ガイドのこのセクションにおいては、MVC アーキテクチャ・パターンの全ての部分に触れました。 +そして、ユーザ・データを表現し、当該データを検証するモデル・クラスを作成する方法を学びました。 また、ユーザからデータを取得する方法と、ブラウザにデータを表示して返す方法も学びました。 この作業は、アプリケーションを開発するときに、多大な時間を必要とするものになり得るものです。 diff --git a/docs/guide-ja/start-gii.md b/docs/guide-ja/start-gii.md index b4b4719336a..be49ca03ada 100644 --- a/docs/guide-ja/start-gii.md +++ b/docs/guide-ja/start-gii.md @@ -1,13 +1,13 @@ Gii でコードを生成する ====================== -このセクションでは、[Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-ja/README.md) を使って、ウェブ・サイトの一般的な機能のいくつかを実装するコードを自動的に生成する方法を説明します。 +このセクションでは、[Gii](https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide) を使って、ウェブ・サイトの一般的な機能のいくつかを実装するコードを自動的に生成する方法を説明します。 Gii を使ってコードを自動生成することは、Gii のウェブ・ページに表示される指示に対して正しい情報を入力するだけのことです。 このチュートリアルを通じて、次のことを学びます。 * アプリケーションで Gii を有効にする方法 -* Gii を使って、アクティブレコードのクラスを生成する方法 +* Gii を使って、アクティブ・レコードのクラスを生成する方法 * Gii を使って、DB テーブルの CRUD 操作を実装するコードを生成する方法 * Gii によって生成されるコードをカスタマイズする方法 @@ -15,9 +15,8 @@ Gii を使ってコードを自動生成することは、Gii のウェブ・ペ Gii を開始する -------------- -[Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-ja/README.md) は Yii の [モジュール](structure-modules.md) として提供されています。 -Gii は、アプリケーションの [[yii\base\Application::modules|modules]] プロパティの中で構成することで有効にすることが出来ます。 -アプリケーションを生成した仕方にもよりますが、`config/web.php` の構成情報ファイルの中に、多分、下記のコードが既に提供されているでしょう。 +[Gii](https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide) は Yii の [モジュール](structure-modules.md) として提供されています。 +Gii は、アプリケーションの [[yii\base\Application::modules|modules]] プロパティの中で構成することで有効にすることが出来ます。アプリケーションを生成した仕方にもよりますが、`config/web.php` の構成情報ファイルの中に、多分、下記のコードが既に提供されているでしょう。 ```php $config = [ ... ]; @@ -30,7 +29,8 @@ if (YII_ENV_DEV) { } ``` -上記の構成情報は、[開発環境](concept-configurations.md#environment-constants) において、アプリケーションは `gii` という名前のモジュールをインクルードすべきこと、そして `gii` は [[yii\gii\Module]] というクラスであることを記述しています。 +上記の構成情報は、[開発環境](concept-configurations.md#environment-constants) において、アプリケーションは `gii` という名前のモジュールをインクルードすべきこと、 +そして `gii` は [[yii\gii\Module]] というクラスであることを記述しています。 アプリケーションの [エントリ・スクリプト](structure-entry-scripts.md) である `web/index.php` をチェックすると、次の行があることに気付くでしょう。 これは本質的には `YII_ENV_DEV` を `true` に設定するものです。 @@ -39,8 +39,7 @@ if (YII_ENV_DEV) { defined('YII_ENV') or define('YII_ENV', 'dev'); ``` -この行のおかげで、アプリケーションは開発モードになっており、上記の構成情報によって、Gii が既に有効になっています。 -これで、下記の URL によって Gii にアクセスすることが出来ます。 +この行のおかげで、アプリケーションは開発モードになっており、上記の構成情報によって、Gii が既に有効になっています。これで、下記の URL によって Gii にアクセスすることが出来ます。 ``` http://hostname/index.php?r=gii @@ -59,28 +58,25 @@ http://hostname/index.php?r=gii ![Gii](images/start-gii.png) -アクティブレコードのクラスを生成する +アクティブ・レコードのクラスを生成する ------------------------------------ -Gii を使ってアクティブレコードのクラスを生成するためには、"Model Generator" を選びます -(Gii のインデックス・ページのリンクをクリックして下さい)。 -そして、次のようにフォームに入力します。 +Gii を使ってアクティブ・レコードのクラスを生成するためには、"Model Generator" を選びます (Gii のインデックス・ページのリンクをクリックして下さい)。そして、次のようにフォームに入力します。 * Table Name: `country` * Model Class: `Country` ![Model Generator](images/start-gii-model.png) -次に、"Preview" ボタンをクリックします。 -そうすると、結果として作成されるクラス・ファイルのリストに `models/Country.php` が挙ってきます。 -クラス・ファイルの名前をクリックすると、内容をプレビューすることが出来ます。 +次に、"Preview" ボタンをクリックします。そうすると、結果として作成されるクラス・ファイルのリストに `models/Country.php` が挙ってきます。クラス・ファイルの名前をクリックすると、内容をプレビューすることが出来ます。 -Gii を使うときに、既に同じファイルを作成していて、それを上書きしようとしている場合は、ファイル名の隣の `diff` ボタンをクリックして、生成されようとしているコードと既存のバージョンの違いを見てください。 +Gii を使うときに、既に同じファイルを作成していて、それを上書きしようとしている場合は、 +ファイル名の隣の `diff` ボタンをクリックして、 +生成されようとしているコードと既存のバージョンの違いを見てください。 ![Model Generator のプレビュー](images/start-gii-model-preview.png) -既存のファイルを上書きするときは、"overwrite" の隣のチェックボックスをチェックしてから "Generate" ボタンをクリックします。 -新しいファイルを作成するときは、単に "Generate" をクリックすれば十分です。 +既存のファイルを上書きするときは、"overwrite" の隣のチェックボックスをチェックしてから "Generate" ボタンをクリックします。新しいファイルを作成するときは、単に "Generate" をクリックすれば十分です。 次に、コードの生成が成功したことを示す確認ページが表示されます。 既存のファイルがあった場合は、それが新しく生成されたコードで上書きされたことを示すメッセージも同じく表示されます。 @@ -89,9 +85,7 @@ Gii を使うときに、既に同じファイルを作成していて、それ CRUD コードを生成する --------------------- -CRUD は Create(作成)、Read(読出し)、Update(更新)、そして Delete(削除) を意味しており、ほとんどのウェブ・サイトでデータを扱うときによく用いられる4つのタスクを表しています。 -Gii を使って CRUD 機能を作成するためには、"CRUD Generator" を選びます (Gii のインデックス・ページのリンクをクリックしてください) 。 -「国リスト」のサンプルのためには、表示されたフォームに以下のように入力します。 +CRUD は Create(作成)、Read(読出し)、Update(更新)、そして Delete(削除) を意味しており、ほとんどのウェブ・サイトでデータを扱うときによく用いられる4つのタスクを表しています。Gii を使って CRUD 機能を作成するためには、"CRUD Generator" を選びます (Gii のインデックス・ページのリンクをクリックしてください) 。「国リスト」のサンプルのためには、表示されたフォームに以下のように入力します。 * Model Class: `app\models\Country` * Search Model Class: `app\models\CountrySearch` @@ -99,8 +93,7 @@ Gii を使って CRUD 機能を作成するためには、"CRUD Generator" を ![CRUD Generator](images/start-gii-crud.png) -次に、"Preview" ボタンをクリックします。 -生成されるファイルのリストは、次のようになります。 +次に、"Preview" ボタンをクリックします。生成されるファイルのリストは、次のようになります。 ![CRUD Generator のプレビュー](images/start-gii-crud-preview.png) @@ -136,10 +129,11 @@ http://hostname/index.php?r=country%2Findex > Info: Gii は非常にカスタマイズしやすく拡張しやすいコード生成ツールとして設計されています。 これを賢く使うと、アプリケーションの開発速度を大いに高めることが出来ます。 - 詳細については、[Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-ja/README.md) のセクションを参照してください。 + 詳細については、[Gii](https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide) のセクションを参照してください。 まとめ ------ -このセクションでは、Gii を使ってコードを生成して、データベース・テーブルに保存されているコンテントのための完全な CRUD 機能を実装する方法を学びました。 +このセクションでは、Gii を使ってコードを生成して、データベース・テーブルに保存されているコンテントのための +完全な CRUD 機能を実装する方法を学びました。 diff --git a/docs/guide-ja/start-hello.md b/docs/guide-ja/start-hello.md index ed95fbec46d..23209f01be8 100644 --- a/docs/guide-ja/start-hello.md +++ b/docs/guide-ja/start-hello.md @@ -2,7 +2,8 @@ ================== このセクションでは、アプリケーションに「こんにちは」という新しいページを作成する方法を説明します。 -この目的を達するために、[アクション](structure-controllers.md#creating-actions) と [ビュー](structure-views.md) を作成します。 +この目的を達するために、[アクション](structure-controllers.md#creating-actions) と +[ビュー](structure-views.md) を作成します。 * アプリケーションは、このページへのリクエストをそのアクションに送付します。 * 次にそのアクションが「こんにちは」という言葉をエンド・ユーザに示すビューを表示します。 @@ -17,7 +18,8 @@ アクションを作成する -------------------- -「こんにちは」のタスクのために、リクエストから `message` パラメータを読んで、そのメッセージをユーザに表示して返す `say` [アクション](structure-controllers.md#creating-actions) を作ります。 +「こんにちは」のタスクのために、リクエストから `message` パラメータを読んで、そのメッセージをユーザに表示して返す +`say` [アクション](structure-controllers.md#creating-actions) を作ります。 リクエストが `message` パラメータを提供しなかった場合は、アクションはデフォルト値として "こんにちは" というメッセージを表示するものとします。 > Info: [アクション](structure-controllers.md#creating-actions) は、エンド・ユーザが直接に参照して実行できるオブジェクトです。 @@ -26,8 +28,7 @@ アクションは [コントローラ](structure-controllers.md) の中で宣言されなければなりません。 話を簡単にするために、`say` アクションを既存の `SiteController` の中で宣言しましょう。 -このコントローラは `controllers/SiteController.php` というクラス・ファイルの中で定義されています。 -次のようにして、新しいアクションが始まります。 +このコントローラは `controllers/SiteController.php` というクラス・ファイルの中で定義されています。次のようにして、新しいアクションが始まります。 ```php @@ -105,13 +107,13 @@ http://hostname/index.php?r=site%2Fsay&message=Hello+World ![Hello World](images/start-hello-world.png) -この URL は、結果として、"Hello World" を表示するページになります。 -このページはアプリケーションの他のページと同じヘッダとフッタを共有しています。 +この URL は、結果として、"Hello World" を表示するページになります。このページはアプリケーションの他のページと同じヘッダとフッタを共有しています。 URL から `message` パラメータを省略すると、"こんにちは" を表示するページを見ることになるでしょう。 これは、`message` が `actionSay()` メソッドにパラメータとして渡されるものであり、それが省略された場合には、デフォルト値である `"こんにちは"` が代りに使われるからです。 -> Info: 新しいページは他のページと同じヘッダとフッタを共有していますが、それは [[yii\web\Controller::render()|render()]] メソッドが `say` ビューの結果をいわゆる [レイアウト](structure-views.md#layouts) に自動的に埋め込むからです。 +> Info: 新しいページは他のページと同じヘッダとフッタを共有していますが、それは [[yii\web\Controller::render()|render()]] メソッドが `say` ビューの結果を +いわゆる [レイアウト](structure-views.md#layouts) に自動的に埋め込むからです。 レイアウトは、この場合、`views/layouts/main.php` にあります。 上記の URL の `r` パラメータについては、さらに説明が必要でしょう。 @@ -122,10 +124,10 @@ URL から `message` パラメータを省略すると、"こんにちは" を この例で言えば、`site/say` というルートは、`SiteController` コントローラ・クラスと `say` アクションとして解決されます。 結果として、`SiteController::actionSay()` メソッドがリクエストを処理するために呼び出されます。 - > Info: アクションと同じく、コントローラもまたアプリケーションの中で一意に定義される ID を持ちます。 コントローラ ID も、アクション ID と同じ命名規則を使います。 - コントローラ・クラスの名前は、コントローラ ID からダッシュを削除し、各単語の最初の文字を大文字にし、結果として出来る文字列に `Controller` という接尾辞を追加したものとなります。 + コントローラ・クラスの名前は、コントローラ ID からダッシュを削除し、各単語の最初の文字を大文字にし、 + 結果として出来る文字列に `Controller` という接尾辞を追加したものとなります。 例えば、`post-comment` というコントローラ ID に対応するコントローラ・クラスの名前は `PostCommentController` です。 @@ -133,8 +135,7 @@ URL から `message` パラメータを省略すると、"こんにちは" を ------ このセクションでは、MVC アーキテクチャ・パターンのうちのコントローラとビューの部分に触れました。 -特定のリクエストを処理するためのアクションをコントローラの一部として作成しました。 -また、レスポンスのコンテントを作成するためのビューも作成しました。 +特定のリクエストを処理するためのアクションをコントローラの一部として作成しました。また、レスポンスのコンテントを作成するためのビューも作成しました。 この単純な例においては、使用される唯一のデータが `message` パラメータであったため、モデルは関係していません。 また、Yii におけるルートについても学びました。ルートはユーザのリクエストとコントローラのアクションとの橋渡しとして働くものです。 diff --git a/docs/guide-ja/start-installation.md b/docs/guide-ja/start-installation.md index fb760578822..fb7eff5438a 100644 --- a/docs/guide-ja/start-installation.md +++ b/docs/guide-ja/start-installation.md @@ -6,11 +6,11 @@ Yii は二つの方法でインストールすることが出来ます。すな Yii の標準的なインストールを実行すると、フレームワークとプロジェクト・テンプレートの両方がダウンロードされてインストールされます。 プロジェクト・テンプレートは、いくつかの基本的な機能、例えば、ログインやコンタクト・フォームなどを実装した、動作する Yii アプリケーションです。 -そのコードは推奨される方法に従って編成されています。 -そのため、プロジェクト・テンプレートは、あなたのプロジェクトのための良い開始点としての役割を果たしうるものです。 +そのコードは推奨される方法に従って編成されています。そのため、プロジェクト・テンプレートは、あなたのプロジェクトのための良い開始点としての役割を果たしうるものです。 -ここから続くいくつかのセクションにおいては、いわゆる *ベーシック・プロジェクト・テンプレート* とともに Yii をインストールする方法、および、このテンプレート上に新しい機能を実装する方法を説明します。 -Yii はもう一つ、[アドバンスト・プロジェクト・テンプレート](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/README.md) と呼ばれるテンプレートも提供しています。 +ここから続くいくつかのセクションにおいては、いわゆる *ベーシック・プロジェクト・テンプレート* とともに Yii をインストールする方法、 +および、このテンプレートの上に新しい機能を実装する方法を説明します。 +Yii はもう一つ、[アドバンスト・プロジェクト・テンプレート](https://www.yiiframework.com/extension/yiisoft/yii2-app-advanced/doc/guide) と呼ばれるテンプレートも提供しています。 こちらは、チーム開発環境において多層構造のアプリケーションを開発するときに使用する方が望ましいものです。 > Info: ベーシック・プロジェクト・テンプレートは、ウェブ・アプリケーションの 90 パーセントを開発するのに適したものです。 @@ -23,20 +23,23 @@ Composer によるインストール ### Composer をインストールする -まだ Composer をインストールしていない場合は、[getcomposer.org]() の指示に従ってインストールすることが出来ます。 +まだ Composer をインストールしていない場合は、[getcomposer.org](https://getcomposer.org/download/) の指示に従ってインストールすることが出来ます。 Linux や Mac OS X では、次のコマンドを実行します。 ```bash curl -sS https://getcomposer.org/installer | php -mv composer.phar /usr/local/bin/composer +sudo mv composer.phar /usr/local/bin/composer ``` Windows では、[Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe) をダウンロードして実行します。 -何か問題が生じたときは、[Composer ドキュメントのトラブル・シューティングのセクション](https://getcomposer.org/doc/articles/troubleshooting.md) を参照してください。 -Composer は初めてだという場合は、少なくとも、Composer ドキュメントの [基本的な使い方のセクション](https://getcomposer.org/doc/01-basic-usage.md) も参照することを推奨します。 +何か問題が生じたときは、[Composer ドキュメントのトラブル・シューティングのセクション](https://getcomposer.org/doc/articles/troubleshooting.md) +を参照してください。 +Composer は初めてだという場合は、少なくとも、Composer ドキュメントの [基本的な使い方のセクション](https://getcomposer.org/doc/01-basic-usage.md) +も参照することを推奨します。 -このガイドでは、composer のコマンドの全ては、あなたが composer を [グローバル](https://getcomposer.org/doc/00-intro.md#globally) にインストールし、`composer` コマンドとして使用できるようにしているものと想定しています。 +このガイドでは、composer のコマンドの全ては、あなたが composer を [グローバル](https://getcomposer.org/doc/00-intro.md#globally) にインストールし、 +`composer` コマンドとして使用できるようにしているものと想定しています。 そうではなく、ローカル・ディレクトリにある `composer.phar` を使おうとする場合は、例に出てくるコマンドをそれに合せて修正しなければなりません。 以前に Composer をインストールしたことがある場合は、確実に最新のバージョンを使うようにしてください。 @@ -44,7 +47,7 @@ Composer は `composer self-update` コマンドを実行してアップデー > Note: Yii のインストールを実行する際に、Composer は大量の情報を Github API から要求する必要が生じます。 > リクエストの数は、あなたのアプリケーションが持つ依存の数によりますが、**Github API レート制限** より大きくなることがあり得ます。 -> この制限にかかった場合、Composer は Github API トークンを取得するために、あなたの Github ログイン認証情報を要求するでしょう。 +> この制限にかかった場合、Composer は Github API アクセス・トークンを取得するために、あなたの Github ログイン認証情報を要求するでしょう。 > 高速な接続においては、Composer が対処できるよりも早い段階でこの制限にかかることもありますので、 > Yii のインストールの前に、このアクセス・トークンを構成することを推奨します。 > アクセス・トークンの構成の仕方については、[Github API トークンに関する Composer ドキュメント](https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens) @@ -52,26 +55,23 @@ Composer は `composer self-update` コマンドを実行してアップデー ### Yii をインストールする -Composer がインストールされたら、ウェブからアクセスできるフォルダで下記のコマンドを実行することによって Yii をインストールすることが出来ます。 +Composer がインストールされたら、ウェブ・アクセス可能なフォルダで下記のコマンドを実行することによって +Yii アプリケーション・テンプレートをインストールすることが出来ます。 ```bash -composer global require "fxp/composer-asset-plugin:~1.3.1" composer create-project --prefer-dist yiisoft/yii2-app-basic basic ``` -最初のコマンドは [composer アセット・プラグイン](https://github.com/francoispluchino/composer-asset-plugin/) をインストールします。 -これにより、Composer を通じて bower と npm の依存パッケージを管理することが出来るようになります。 -このコマンドは一度だけ実行すれば十分です。 -第二のコマンドは `basic` という名前のディレクトリに Yii の最新の安定版をインストールします。 +このコマンドが `basic` という名前のディレクトリに Yii アプリケーション/テンプレートの最新の安定版をインストールします。 必要なら別のディレクトリ名を選ぶことも出来ます。 -> Info: `composer create-project` コマンドが失敗するときは、composer asset plugin が正しくインストール出来ているかどうかを確認して下さい。 -> `composer global show` を実行することで確認することが出来ます。このコマンドの出力に `fxp/composer-asset-plugin` のエントリが含まれていなければなりません。. -> よくあるエラーについては、[Composer ドキュメントのトラブル・シューティングのセクション](https://getcomposer.org/doc/articles/troubleshooting.md) -> も参照して下さい。 -> エラーを修正した後は、`basic` ディレクトリの中で `composer update` を実行して、中断されたインストールを再開することが出来ます。 +> Info: `composer create-project` コマンドが失敗するときは、 +> よくあるエラーについて [Composer ドキュメントのトラブル・シューティングのセクション](https://getcomposer.org/doc/articles/troubleshooting.md) を参照して下さい。 +> エラーを修正した後は、`basic` ディレクトリの中で `composer update` を実行して、 +> 中断されたインストールを再開することが出来ます。 -> Tip: Yii の最新の開発バージョンをインストールしたい場合は、[stability option](https://getcomposer.org/doc/04-schema.md#minimum-stability) を追加した次のコマンドを代りに使うことが出来ます。 +> Tip: Yii の最新の開発バージョンをインストールしたい場合は、[stability option](https://getcomposer.org/doc/04-schema.md#minimum-stability) +> を追加した次のコマンドを代りに使うことが出来ます。 > > ```bash > composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic @@ -85,9 +85,9 @@ composer create-project --prefer-dist yiisoft/yii2-app-basic basic アーカイブ・ファイルから Yii をインストールするには、三つの手順を踏みます。 -1. [yiiframework.com](http://www.yiiframework.com/download/) からアーカイブ・ファイルをダウンロードする。 -2. ダウンロードしたファイルをウェブからアクセスできるフォルダーに展開する。 -3. `config/web.php` ファイルを編集して、`cookieValidationKey` という構成情報の項目に秘密キーを入力する +1. [yiiframework.com](http://www.yiiframework.com/download/) からアーカイブ・ファイルをダウンロードします。 +2. ダウンロードしたファイルをウェブ・アクセス可能なフォルダに展開します。 +3. `config/web.php` ファイルを編集して、`cookieValidationKey` という構成情報の項目に秘密キーを入力します (Composer を使って Yii をインストールするときは、これは自動的に実行されます)。 ```php @@ -105,17 +105,17 @@ composer create-project --prefer-dist yiisoft/yii2-app-basic basic しかし、他のインストール・オプションも利用可能です。 -* コアフレームワークだけをインストールし、アプリケーション全体を一から構築したい場合は、[アプリケーションを一から構築する](tutorial-start-from-scratch.md) +* コア・フレームワークだけをインストールし、アプリケーション全体を一から構築したい場合は、[アプリケーションを一から構築する](tutorial-start-from-scratch.md) で説明されている指示に従うことが出来ます。 -* もっと洗練された、チーム開発環境により適したアプリケーションから開始したい場合は、 [アドバンスト・プロジェクト・テンプレート](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/README.md) をインストールすることを考慮することが出来ます。 +* もっと洗練された、チーム開発環境により適したアプリケーションから開始したい場合は、 + [アドバンスト・プロジェクト・テンプレート](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/README.md) をインストールすることを考慮することが出来ます。 アセットをインストールする -------------------------- -Yii は、アセット (CSS および JavaScript) ライブラリのインストールについて -[Bower](http://bower.io/) および/または [NPM](https://www.npmjs.org/) のパッケージに依存しています。 -Yii はこれらのライブラリを取得するのに Composer を使って、PHP と CSS/JavaScript のパッケージバージョンを同時に解決できるようにしています。 +Yii は、アセット (CSS および JavaScript) ライブラリのインストールについて [Bower](http://bower.io/) および/または [NPM](https://www.npmjs.org/) のパッケージに依存しています。 +Yii はこれらのライブラリを取得するのに Composer を使って、PHP と CSS/JavaScript のパッケージ・バージョンを同時に解決できるようにしています。 このことは、[asset-packagist.org](https://asset-packagist.org) または [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/) を使用することによって達成されます。 詳細は [アセットのドキュメント](structure-assets.md) を参照して下さい。 @@ -131,15 +131,14 @@ Composer によるアセットのインストールを抑止するためには }, ``` -> Note: Composer によるアセットのインストールをバイパスする場合は、アセットのインストールとバージョン衝突の解決について -> あなたが責任を持たなければなりません。 +> Note: Composer によるアセットのインストールをバイパスする場合は、アセットのインストールとバージョン衝突の解決についてあなたが責任を持たなければなりません。 > さまざまなエクステンションに由来するアセット・ファイル間で不整合が生じうることを覚悟して下さい。 インストールを検証する ---------------------- -インストール完了後、あなたのウェブ・サーバを構成してください (次の説を参照してください)。 +インストール完了後、あなたのウェブ・サーバを構成してください (次のセクションを参照してください)。 あるいは、プロジェクトの `web` ディレクトリで次のコマンドを実行して、 [PHP の内蔵ウェブ・サーバ](https://secure.php.net/manual/ja/features.commandline.webserver.php) を使ってください。 @@ -147,9 +146,8 @@ Composer によるアセットのインストールを抑止するためには php yii serve ``` -> Note: デフォルトでは、この HTTP サーバは 8080 ポートをリスンします。 -しかし、このポートがすでに使われていたり、複数のアプリケーションをこの方法で動かしたい場合は、どのポートを使うかを指定したいと思うでしょう。 -単に --port 引数を追加して下さい。 +> Note: デフォルトでは、この HTTP サーバは 8080 ポートをリスンします。しかし、このポートがすでに使われていたり、複数のアプリケーションをこの方法で動かしたい場合は、 + どのポートを使うかを指定したいと思うでしょう。単に --port 引数を追加して下さい。 ```bash php yii serve --port=8888 @@ -163,11 +161,10 @@ http://localhost:8080/ ![Yii のインストールが成功](images/start-app-installed.png) -ブラウザに上のような "おめでとう!" のページが表示されるはずです。 -もし表示されなかったら、PHP のインストールが Yii の必要条件を満たしているかどうか、チェックしてください。 +ブラウザに上のような "おめでとう!" のページが表示されるはずです。もし表示されなかったら、PHP のインストールが Yii の必要条件を満たしているかどうか、チェックしてください。 最低限の必要条件を満たしているかどうかは、次の方法のどちらかによってチェックすることが出来ます。 -* `requirements.php` を `/web/requirements.php` としてコピーし、ブラウザを使って URL `http://localhost/requirements.php` にアクセスする。 +* `/requirements.php` を `/web/requirements.php` としてコピーし、ブラウザを使って URL `http://localhost/requirements.php` にアクセスする。 * 次のコマンドを実行する。 ```bash @@ -177,29 +174,37 @@ http://localhost:8080/ Yii の最低必要条件を満たすように PHP のインストールを構成しなければなりません。 最も重要なことは、PHP 5.4 以上でなければならないということです。最新の PHP 7 なら理想的です。 -また、アプリケーションがデータベースを必要とする場合は、[PDO PHP 拡張](http://www.php.net/manual/ja/pdo.installation.php) および対応するデータベースドライバ (MySQL データベースのための `pdo_mysql` など) をインストールしなければなりません。 +また、アプリケーションがデータベースを必要とする場合は、[PDO PHP 拡張](http://www.php.net/manual/ja/pdo.installation.php) および対応するデータベース・ドライバ (MySQL データベースのための `pdo_mysql` など) をインストールしなければなりません。 ウェブ・サーバを構成する ------------------------ -> Info: もし Yii の試運転をしているだけで、本番サーバに配備する意図がないのであれば、当面、この項は飛ばしても構いません。 +> Info: もし Yii の試運転をしているだけで、本番サーバに配備する意図がないのであれば、 + 当面、この項は飛ばしても構いません。 -上記の説明に従ってインストールされたアプリケーションは、[Apache HTTP サーバ](http://httpd.apache.org/) と [Nginx HTTP サーバ](http://nginx.org/) のどちらでも、また、Windows、Mac OS X、Linux のどれでも、PHP 5.4 以上を走らせている環境であれば、そのままの状態で動作するはずです。 +上記の説明に従ってインストールされたアプリケーションは、[Apache HTTP サーバ](http://httpd.apache.org/) +と [Nginx HTTP サーバ](http://nginx.org/) のどちらでも、また、Windows、Mac OS X、Linux のどれでも、 +PHP 5.4 以上を走らせている環境であれば、そのままの状態で動作するはずです。 Yii 2.0 は、また、facebook の [HHVM](http://hhvm.com/) とも互換性があります。 ただし HHVM がネイティブの PHP とは異なる振舞いをする特殊なケースもいくつかありますので、HHVM を使うときはいくらか余分に注意を払う必要があります。 -本番用のサーバでは、`http://www.example.com/basic/web/index.php` の代りに `http://www.example.com/index.php` という URL でアプリケーションにアクセス出来るようにウェブ・サーバを設定したいでしょう。 -そういう設定をするためには、ウェブ・サーバのドキュメントルートを `basic/web` フォルダに向けることが必要になります。 +本番用のサーバでは、`http://www.example.com/basic/web/index.php` の代りに `http://www.example.com/index.php` という +URL でアプリケーションにアクセス出来るようにウェブ・サーバを設定したいでしょう。 +そういう設定をするためには、ウェブ・サーバのドキュメント・ルートを `basic/web` フォルダに向けることが必要になります。 また、[ルーティングと URL 生成](runtime-routing.md) のセクションで述べられているように、URL から `index.php` を隠したいとも思うでしょう。 -このセクションでは、これらの目的を達するために Apache または Nginx サーバをどのように設定すれば良いかを学びます。 +この項では、これらの目的を達するために Apache または Nginx サーバをどのように設定すれば良いかを学びます。 -> Info: `basic/web` をドキュメント・ルートに設定することは、`basic/web` の兄弟ディレクトリに保存されたプライベートなアプリケーション・コードや公開できないデータ・ファイルにエンド・ユーザがアクセスすることを防止することにもなります。 +> Info: `basic/web` をドキュメント・ルートに設定することは、`basic/web` の兄弟ディレクトリに保存されたプライベートなアプリケーション・コードや +公開できないデータ・ファイルにエンド・ユーザがアクセスすることを防止することにもなります。 `basic/web` 以外のフォルダに対するアクセスを拒否することはセキュリティ強化の一つです。 -> Info: あなたがウェブ・サーバの設定を修正する権限を持たない共用ホスティング環境でアプリケーションが走る場合であっても、セキュリティ強化のためにアプリケーションの構造を調整することがまだ出来ます。 +> Info: あなたがウェブ・サーバの設定を修正する権限を持たない共用ホスティング環境でアプリケーションが走る場合であっても、 +セキュリティ強化のためにアプリケーションの構造を調整することがまだ出来ます。 詳細については、[共有ホスティング環境](tutorial-shared-hosting.md) のセクションを参照してください。 +> Info: あなたのアプリケーションをリバース・プロキシの背後で動かそうとする場合は、 +> リクエスト・コンポーネントの [信頼できるプロキシとヘッダ](runtime-requests.md#trusted-proxies) を構成する必要があるかもしれません。 ### 推奨される Apache の構成 @@ -207,15 +212,20 @@ Yii 2.0 は、また、facebook の [HHVM](http://hhvm.com/) とも互換性が `path/to/basic/web` の部分を `basic/web` の実際のパスに置き換えなければならないことに注意してください。 ```apache -# ドキュメントルートを "basic/web" に設定 +# ドキュメント・ルートを "basic/web" に設定 DocumentRoot "path/to/basic/web" # 綺麗な URL をサポートするために mod_rewrite を使う RewriteEngine on + + # UrlManager の $showScriptName が false の場合は、スクリプト名で URL にアクセスすることを許さない + RewriteRule ^index.php/ - [L,R=404] + # ディレクトリかファイルが存在する場合は、リクエストをそのまま通す RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d + # そうでなければ、リクエストを index.php に送付する RewriteRule . index.php @@ -275,6 +285,8 @@ server { } ``` -この構成を使う場合は、多数の不要な `stat()` システム・コールを避けるために、`php.ini` ファイルで `cgi.fix_pathinfo=0` を同時に設定しておくべきです。 +この構成を使う場合は、多数の不要な `stat()` システム・コールを避けるために、 +`php.ini` ファイルで `cgi.fix_pathinfo=0` を同時に設定しておくべきです。 -また、HTTPS サーバを走らせている場合には、安全な接続であることを Yii が正しく検知できるように、`fastcgi_param HTTPS on;` を追加しなければならないことにも注意を払ってください。 +また、HTTPS サーバを走らせている場合には、安全な接続であることを Yii が正しく検知できるように、 +`fastcgi_param HTTPS on;` を追加しなければならないことにも注意を払ってください。 diff --git a/docs/guide-ja/start-looking-ahead.md b/docs/guide-ja/start-looking-ahead.md index 2a2d6191541..fb893a5d712 100644 --- a/docs/guide-ja/start-looking-ahead.md +++ b/docs/guide-ja/start-looking-ahead.md @@ -3,7 +3,7 @@ 「はじめよう」の章全体を読み通したなら、いまやあなたは、完全な Yii のアプリケーションを作成したことがある、ということになります。 その過程で、あなたは必要とされることが多いいくつかの機能、例えば、HTML フォームを通じてユーザからデータを取得することや、データベースからデータを取得すること、また、ページ付けをしてデータを表示することなどを実装する方法を学びました。 -また、[Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-ja/README.md) を使ってコードを自動的に生成する方法も学びました。 +また、[Gii](https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide) を使ってコードを自動的に生成する方法も学びました。 Gii をコード生成に使うと、ウェブ開発のプロセスの大部分が、いくつかのフォームに入力していくだけの簡単な仕事になります。 このセクションでは、Yii フレームワークを使うときの生産性を更に高めるために利用できるリソースについてまとめます。 @@ -11,7 +11,7 @@ Gii をコード生成に使うと、ウェブ開発のプロセスの大部分 * ドキュメント - [決定版ガイド](http://www.yiiframework.com/doc-2.0/guide-README.html): 名前が示すように、このガイドは Yii がどのように動作すべきものかを正確に記述し、Yii を使用するについての全般的な手引きを提供するものです。 - これは唯一の最も重要な Yii のチュートリアルであり、Yii のコードを少しでも書く前にあなたはこれを読まなければなりません。 + これは唯一の最も重要な Yii のチュートリアルであり、Yii のコードを少しでも書く前にあなたが読まなければならないものです。 - [クラス・リファレンス](http://www.yiiframework.com/doc-2.0/index.html): これは Yii によって提供される全てのクラスの使用法を記述しています。 主として、コードを書いている時に、特定のクラス、メソッド、プロパティについて理解したい場合に読まれるべきものです。 diff --git a/docs/guide-ja/start-prerequisites.md b/docs/guide-ja/start-prerequisites.md index c31cd7ce5ab..4a37d68ed65 100644 --- a/docs/guide-ja/start-prerequisites.md +++ b/docs/guide-ja/start-prerequisites.md @@ -5,19 +5,19 @@ Yii の学習曲線は他の PHP フレームワークほど急峻ではあり ## PHP Yii は PHP フレームワークですから、必ず [言語リファレンスを読んで理解する](http://php.net/manual/ja/langref.php) ようにして下さい。 -Yii を使って開発するときはオブジェクト指向でコードを書くことになりますから、必ず、 -[クラスとオブジェクト](https://secure.php.net/manual/ja/language.oop5.basic.php) および [名前空間](https://secure.php.net/manual/ja/language.namespaces.php) には慣れ親しんでおいて下さい。 +Yii を使って開発するときはオブジェクト指向の流儀でコードを書くことになりますから、必ず、[クラスとオブジェクト](https://secure.php.net/manual/ja/language.oop5.basic.php) および [名前空間](https://secure.php.net/manual/ja/language.namespaces.php) には慣れ親しんでおいて下さい。 ## オブジェクト指向プログラミング オブジェクト指向プログラミングの基礎的な理解が必要です。これに慣れていない場合は、利用できるチュートリアルが沢山ありますので、その中の一つをチェックして下さい。 例えば、[tuts+ の中の一つ](https://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762) など。 -あなたのアプリケーションが複雑であればあるほど、その複雑性を管理するために、より高度な OOP 概念を学ぶ必要があることに留意して下さい。 +あなたのアプリケーションが複雑であればあるほど、その複雑性をうまく管理するために、 +より高度な OOP 概念を学ぶ必要があることに留意して下さい。 -## コマンドラインと Composer +## コマンド・ラインと Composer + +Yii は業界標準の PHP パッケージ管理ソフトである [Composer](https://getcomposer.org/) を広範囲に使用していますので、必ずその [ガイド](https://getcomposer.org/doc/01-basic-usage.md) を読んで理解して下さい。 +あなたがコマンド・ラインの使用に慣れていないのであれば、今こそ使い始めてみるべき時です。 +いったん基礎さえ学習してしまえば、二度とコマンド・ラインなしで仕事をしようとは思わなくなりますよ。 -Yii は業界標準の PHP パッケージ管理ソフトである [Composer](https://getcomposer.org/) を広範囲に使用していますので、 -必ずその [ガイド](https://getcomposer.org/doc/01-basic-usage.md) を読んで理解して下さい。 -あなたがコマンドラインの使用に慣れていないのであれば、今こそ使い始めてみるべき時です。 -いったん基礎を学習すれば、二度とコマンドラインなしで仕事をしようとは思わなくなりますよ。 diff --git a/docs/guide-ja/start-workflow.md b/docs/guide-ja/start-workflow.md index 3d49c996831..5a0a61293e4 100644 --- a/docs/guide-ja/start-workflow.md +++ b/docs/guide-ja/start-workflow.md @@ -3,38 +3,40 @@ Yii のインストールが終ると、実際に動く Yii のアプリケーションにアクセスすることが出来ます。 その URL は、`http://hostname/basic/web/index.php` あるいは `http://hostname/index.php` など、設定によって異なります。 -このセクションでは、アプリケーションに組み込み済みの機能を紹介し、コードがどのように編成されているか、そして、一般にアプリケーションがリクエストをどのように処理するかを説明します。 +このセクションでは、アプリケーションに組み込み済みの機能を紹介し、コードがどのように編成されているか、 +そして、一般にアプリケーションがリクエストをどのように処理するかを説明します。 -> Info: 話を簡単にするために、この「始めよう」のチュートリアルを通じて、`basic/web` をウェブ・サーバのドキュメント・ルートとして設定したと仮定します。 +> Info: 話を簡単にするために、この「始めよう」のチュートリアルを通じて、`basic/web` + をウェブ・サーバのドキュメント・ルートとして設定したと仮定します。 そして、アプリケーションにアクセスするための URL は `http://hostname/index.php` またはそれに似たものになるように設定したと仮定します。 必要に応じて、説明の中の URL を読み替えてください。 - フレームワークそのものとは異なり、プロジェクト・テンプレートはインストール後は完全にあなたのものであることに注意してください。 必要に応じてコードを追加したり削除したり、完全に書き換えたりするのはあなたの自由です。 + 機能 ---- -インストールされた基本的なアプリケーションは四つのページを持っています。 +インストールされたベーシック・アプリケーションは四つのページを持っています。 * ホームページ: `http://hostname/index.php` の URL にアクセスすると表示されます。 * 「について」のページ。 * 「コンタクト」のページ: エンド・ユーザがメールであなたに連絡を取ることが出来るコンタクト・フォームが表示されます。 * 「ログイン」ページ: エンド・ユーザを認証するためのログイン・フォームが表示されます。 - "admin/admin" でログインしてみてください。 - 「ログイン」のメイン・メニュー項目が「ログアウト」に変ることに気付くでしょう。 + "admin/admin" でログインしてみてください。「ログイン」のメイン・メニュー項目が「ログアウト」に変ることに気付くでしょう。 これらのページは共通のヘッダとフッタを持っています。 ヘッダには、異なるページ間を行き来することを可能にするメイン・メニュー・バーがあります。 ブラウザのウィンドウの下部にツールバーがあることにも気がつくはずです。 -これは Yii によって提供される便利な [デバッグ・ツール・バー](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide-ja/README.md) であり、たくさんのデバッグ情報、例えば、ログ・メッセージ、レスポンスのステータス、実行されたデータベース・クエリなどを記録して表示するものです。 +これは Yii によって提供される便利な [デバッグ・ツール](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide-ja/README.md) であり、たくさんのデバッグ情報、例えば、ログ・メッセージ、レスポンスのステータス、実行されたデータベース・クエリなどを記録して表示するものです。 ウェブ・アプリケーションに加えて、`yii` というコンソール・スクリプトがアプリケーションのベース・ディレクトリにあります。 このスクリプトは、バックグラウンドのタスクまたはメンテナンスのタスクを実行するために使用することが出来ます。 これについては、[コンソール・アプリケーションのセクション](tutorial-console.md) で説明されています。 + アプリケーションの構造 ---------------------- @@ -52,7 +54,7 @@ basic/ アプリケーションのベース・パス runtime/ 実行時に Yii によって生成されるファイル (ログやキャッシュなど) を格納 vendor/ インストールされた Composer パッケージ (Yii フレームワークそのものを含む) を格納 views/ ビュー・ファイルを格納 - web/ アプリケーションのウェブ・ルート。ウェブからアクセス可能なファイルを格納 + web/ アプリケーションのウェブ・ルート。ウェブ・アクセス可能なファイルを格納 assets/ Yii によって発行されるアセット・ファイル (javascript と CSS) を格納 index.php アプリケーションのエントリ・スクリプト (ブートストラップ・スクリプト) yii Yii コンソール・コマンド実行スクリプト @@ -61,7 +63,8 @@ basic/ アプリケーションのベース・パス 一般に、アプリケーションのファイルは二種類に分けることが出来ます。すなわち、`basic/web` の下にあるファイルとその他のディレクトリの下にあるファイルです。 前者は HTTP で (すなわちブラウザで) 直接にアクセスすることが出来ますが、後者は直接のアクセスは出来ませんし、許可すべきでもありません。 -Yii は [モデル・ビュー・コントローラ (MVC)](http://wikipedia.org/wiki/Model-view-controller) アーキテクチャ・パターンを実装していますが、それが上記のディレクトリ構成にも反映されています。 +Yii は [モデル・ビュー・コントローラ (MVC)](http://wikipedia.org/wiki/Model-view-controller) アーキテクチャ・パターンを実装していますが、 +それが上記のディレクトリ構成にも反映されています。 `models` ディレクトリが全ての [モデル・クラス](structure-models.md) を格納し、`views` ディレクトリが全ての [ビュー・スクリプト](structure-views.md) を格納し、 `controllers` ディレクトリが全ての [コントローラ・クラス](structure-controllers.md) を格納しています。 @@ -70,22 +73,24 @@ Yii は [モデル・ビュー・コントローラ (MVC)](http://wikipedia.org/ ![アプリケーションの静的な構造](images/application-structure.png) 各アプリケーションは一つのエントリ・スクリプト `web/index.php` を持ちます。 -これはアプリケーション中で唯一ウェブからアクセス可能な PHP スクリプトです。 +これはアプリケーション中で唯一ウェブ・アクセス可能な PHP スクリプトです。 エントリ・スクリプトは入力されたリクエストを受け取って、[アプリケーション](structure-applications.md) のインスタンスを作成します。 [アプリケーション](structure-applications.md) は [コンポーネント](concept-components.md) の助力を得てリクエストを解決し、リクエストを MVC に送付します。 [ウィジェット](structure-widgets.md) は、複雑で動的なユーザ・インタフェイス要素を構築するために、[ビュー](structure-views.md) の中で使われます。 -リクエストのライフ・サイクル ----------------------------- +リクエストのライフサイクル +-------------------------- 次の図は、アプリケーションがどのようにリクエストを処理するかを示すものです。 -![リクエストのライフ・サイクル](images/request-lifecycle.png) +![リクエストのライフサイクル](images/request-lifecycle.png) 1. ユーザが [エントリ・スクリプト](structure-entry-scripts.md) `web/index.php` に対してリクエストを出します。 -2. エントリ・スクリプトはアプリケーションの [構成情報](concept-configurations.md) を読み出して、リクエストを処理する [アプリケーション](structure-applications.md) のインスタンスを作成します。 -3. アプリケーションは、[リクエスト](runtime-requests.md) アプリケーション・コンポーネントの助力を得て、リクエストされた [ルート](runtime-routing.md) を解決します。 +2. エントリ・スクリプトはアプリケーションの [構成情報](concept-configurations.md) を読み出して、 + リクエストを処理する [アプリケーション](structure-applications.md) のインスタンスを作成します。 +3. アプリケーションは、[リクエスト](runtime-requests.md) アプリケーション・コンポーネントの助力を得て、 + リクエストされた [ルート](runtime-routing.md) を解決します。 4. アプリケーションがリクエストを処理する [コントローラ](structure-controllers.md) のインスタンスを作成します。 5. コントローラが [アクション](structure-controllers.md) のインスタンスを作成し、アクションのためのフィルタを実行します。 6. 一つでもフィルタが失敗したときは、アクションはキャンセルされます。 diff --git a/docs/guide-ja/structure-application-components.md b/docs/guide-ja/structure-application-components.md index 02e05fc9a2c..a75554af1af 100644 --- a/docs/guide-ja/structure-application-components.md +++ b/docs/guide-ja/structure-application-components.md @@ -2,8 +2,9 @@ ================================ アプリケーションは [サービス・ロケータ](concept-service-locator.md) です。 -アプリケーションは、リクエストを処理するためのいろいろなサービスを提供する一連のオブジェクト、いわゆる *アプリケーション・コンポーネント* をホストします。 -例えば、`urlManager` がウェブ・リクエストを適切なコントローラにルーティングする役割を負い、`db` コンポーネントが DB 関連のサービスを提供する、等々です。 +アプリケーションは、リクエストを処理するためのいろいろなサービスを提供する一組の *アプリケーション・コンポーネント* と呼ばれるものをホストします。 +例えば、`urlManager` がウェブ・リクエストを適切なコントローラにルーティングする役割を負い、 +`db` コンポーネントが DB 関連のサービスを提供する、等々です。 全てのアプリケーション・コンポーネントは、それぞれ、同一のアプリケーション内で他のアプリケーション・コンポーネントから区別できるように、ユニークな ID を持ちます。 アプリケーション・コンポーネントには、次の式によってアクセス出来ます。 @@ -57,8 +58,7 @@ けれども、場合によっては、明示的にアクセスされないときでも、リクエストごとにアプリケーション・コンポーネントのインスタンスを作成したいことがあります。 そうするために、アプリケーションの [[yii\base\Application::bootstrap|bootstrap]] プロパティのリストにそのコンポーネントの ID を挙げることが出来ます。 -また、特別なコンポーネントをブートストラップするためにクロージャを用いることも出来ます。 -インスタンス化されたコンポーネントを返すことは要求されません。 +また、カスタマイズしたコンポーネントをブートストラップするためにクロージャを用いることも出来ます。インスタンス化されたコンポーネントを返すことは要求されません。 単に [[yii\base\Application]] のインスタンス化の後にコードを走らせるだけのためにクロージャを使うことも出来ます。 例えば、次のアプリケーション構成情報は、`log` コンポーネントが常にロードされることを保証するものです。 @@ -87,9 +87,10 @@ ## コア・アプリケーション・コンポーネント Yii は固定の ID とデフォルトの構成情報を持つ一連の *コア*・アプリケーション・コンポーネントを定義しています。 -例えば、[[yii\web\Application::request|request]] コンポーネントは、ユーザ・リクエストに関する情報を収集して、それを [ルート](runtime-routing.md) として解決するために使用されます。 +例えば、[[yii\web\Application::request|request]] コンポーネントは、ユーザ・リクエストに関する情報を収集して、 +それを [ルート](runtime-routing.md) として解決するために使用されます。 また、[[yii\base\Application::db|db]] コンポーネントは、それを通じてデータ・ベースクエリを実行できるデータベース接続を表現します。 -Yii のアプリケーションがユーザリクエストを処理出来るのは、まさにこれらのコア・アプリケーション・コンポーネントの助けがあってこそです。 +Yii のアプリケーションがユーザ・リクエストを処理出来るのは、まさにこれらのコア・アプリケーション・コンポーネントの助けがあってこそです。 下記が事前に定義されたコア・アプリケーション・コンポーネントです。 通常のアプリケーション・コンポーネントに対するのと同様に、これらを構成し、カスタマイズすることが出来ます。 @@ -98,8 +99,9 @@ Yii のアプリケーションがユーザリクエストを処理出来るの * [[yii\web\AssetManager|assetManager]]: アセット・バンドルとアセットの発行を管理します。 詳細は [アセット](structure-assets.md) のセクションを参照してください。 * [[yii\db\Connection|db]]: データベース接続を表します。これを通じて、DB クエリを実行することが出来ます。 - このコンポーネントを構成するときは、コンポーネントのクラスはもちろん、[[yii\db\Connection::dsn]] のような必須のコンポーネント・プロパティを指定しなければならないことに注意してください。 - 詳細は [データアクセス・オブジェクト](db-dao.md) のセクションを参照してください。 + このコンポーネントを構成するときは、コンポーネントのクラスはもちろん、[[yii\db\Connection::dsn]] + のような必須のコンポーネント・プロパティを指定しなければならないことに注意してください。 + 詳細は [データベース・アクセス・オブジェクト](db-dao.md) のセクションを参照してください。 * [[yii\base\Application::errorHandler|errorHandler]]: PHP のエラーと例外を処理します。 詳細は [エラー処理](runtime-handling-errors.md) のセクションを参照してください。 * [[yii\i18n\Formatter|formatter]]: エンド・ユーザに表示されるデータに書式を設定します。 diff --git a/docs/guide-ja/structure-applications.md b/docs/guide-ja/structure-applications.md index 03f9b558b1e..5de877a628b 100644 --- a/docs/guide-ja/structure-applications.md +++ b/docs/guide-ja/structure-applications.md @@ -1,19 +1,22 @@ アプリケーション ================ -アプリケーションは Yii アプリケーション・システム全体の構造とライフ・サイクルを統制するオブジェクトです。 +アプリケーションは Yii アプリケーション・システム全体の構造とライフサイクルを統制するオブジェクトです。 全ての Yii アプリケーション・システムは、それぞれ、単一のアプリケーション・オブジェクトを持ちます。 アプリケーション・オブジェクトは、[エントリ・スクリプト](structure-entry-scripts.md) において作成され、`\Yii::$app` という式でグローバルにアクセスすることが出来るオブジェクトです。 -> Info: ガイドの中で「アプリケーション」という言葉は、文脈に応じて、アプリケーション・オブジェクトを意味したり、アプリケーション・システムを意味したりします。 +> Info: ガイドの中で「アプリケーション」という言葉は、文脈に応じて、アプリケーション・オブジェクトを意味したり、 + アプリケーション・システムを意味したりします。 -二種類のアプリケーション、すなわち、[[yii\web\Application|ウェブ・アプリケーション]] と [[yii\console\Application|コンソール・アプリケーション]] があります。 +二種類のアプリケーション、すなわち、[[yii\web\Application|ウェブ・アプリケーション]] と +[[yii\console\Application|コンソール・アプリケーション]] があります。 名前が示すように、前者は主にウェブのリクエストを処理し、後者はコンソール・コマンドのリクエストを処理します。 ## アプリケーションの構成情報 -[エントリ・スクリプト](structure-entry-scripts.md) は、アプリケーションを作成するときに、下記のように、[構成情報](concept-configurations.md) を読み込んで、それをアプリケーションに適用します。 +[エントリ・スクリプト](structure-entry-scripts.md) は、アプリケーションを作成するときに、下記のように、 +[構成情報](concept-configurations.md) を読み込んで、それをアプリケーションに適用します。 ```php require __DIR__ . '/../vendor/autoload.php'; @@ -26,8 +29,10 @@ $config = require __DIR__ . '/../config/web.php'; (new yii\web\Application($config))->run(); ``` -通常の [構成情報](concept-configurations.md) と同じように、アプリケーションの構成情報は、アプリケーション・オブジェクトのプロパティをどのように初期化するかを指定するものです。 -アプリケーションの構成情報は、たいていは非常に複雑なものですから、通常は、上記の例の `web.php` ファイルのように、[構成情報ファイル](concept-configurations.md#configuration-files) に保管されます。 +通常の [構成情報](concept-configurations.md) と同じように、アプリケーションの構成情報は、 +アプリケーション・オブジェクトのプロパティをどのように初期化するかを指定するものです。 +アプリケーションの構成情報は、たいていは非常に複雑なものですから、通常は、上記の例の `web.php` ファイルのように、 +[構成情報ファイル](concept-configurations.md#configuration-files) に保管されます。 ## アプリケーションのプロパティ @@ -55,22 +60,22 @@ $config = require __DIR__ . '/../config/web.php'; [[yii\base\Application::basePath|basePath]] プロパティは、アプリケーションのルート・ディレクトリを指定するものです。 これは、アプリケーション・システムの全ての保護されたソース・コードを収容するディレクトリです。 -通常、このディレクトリの下に、MVC パターンに対応するソース・コードを収容した `models`、`views`、`controllers` などのサブ・ディレクトリがあります。 +通常、このディレクトリの下に、MVC パターンに対応するソース・コードを収容した `models`、`views`、`controllers` +などのサブ・ディレクトリがあります。 [[yii\base\Application::basePath|basePath]] プロパティの構成には、ディレクトリ・パスを使っても、[パス・エイリアス](concept-aliases.md) を使っても構いません。 どちらの形式においても、対応するディレクトリが存在しなければなりません。 -さもなくば、例外が投げられます。 -パスは `realpath()` 関数を呼び出して正規化されます。 +さもなくば、例外が投げられます。パスは `realpath()` 関数を呼び出して正規化されます。 [[yii\base\Application::basePath|basePath]] プロパティは、しばしば、他の重要なパス (例えば、runtime のパス) を派生させるために使われます。 このため、`basePath` を示す `@app` というパス・エイリアスが、あらかじめ定義されています。 -その結果、派生的なパスはこのエイリアスを使って形成することが出来ます -(例えば、runtime ディレクトリを示す `@app/runtime` など)。 +その結果、派生的なパスはこのエイリアスを使って形成することが出来ます(例えば、runtime ディレクトリを示す `@app/runtime` など)。 ### 重要なプロパティ -この項で説明するプロパティは、アプリケーションごとに異なってくるものであるため、たいてい、構成する必要が生じます。 +この項で説明するプロパティは、アプリケーションごとに異なるものであるため、 +構成する必要がよく生じるものです。 #### [[yii\base\Application::aliases|aliases]] @@ -88,14 +93,16 @@ $config = require __DIR__ . '/../config/web.php'; ] ``` -このプロパティが提供されているのは、[[Yii::setAlias()]] メソッドを呼び出す代りに、アプリケーションの構成情報を使ってエイリアスを定義することが出来るようにするためです。 +このプロパティが提供されているのは、[[Yii::setAlias()]] メソッドを呼び出す代りに、 +アプリケーションの構成情報を使ってエイリアスを定義することが出来るようにするためです。 #### [[yii\base\Application::bootstrap|bootstrap]] これは非常に有用なプロパティです。 これによって、アプリケーションの [[yii\base\Application::bootstrap()|ブートストラップの過程]] において走らせるべきコンポーネントを配列として指定することが出来ます。 -例えば、ある [モジュール](structure-modules.md) に [URL 規則](runtime-routing.md) をカスタマイズさせたいときに、モジュールの ID をこのプロパティの要素として挙げることが出来ます。 +例えば、ある [モジュール](structure-modules.md) に [URL 規則](runtime-routing.md) をカスタマイズさせたいときに、 +モジュールの ID をこのプロパティの要素として挙げることが出来ます。 このプロパティにリストする各コンポーネントは、以下の形式のいずれかによって指定することが出来ます。 @@ -130,8 +137,10 @@ $config = require __DIR__ . '/../config/web.php'; ] ``` -> Info: モジュール ID と同じ ID のアプリケーション・コンポーネントがある場合は、ブートストラップの過程ではアプリケーション・コンポーネントが使われます。 -> 代りにモジュールを使いたいときは、次のように、無名関数を使って指定することが出来ます。 +> Info: モジュール ID と同じ ID のアプリケーション・コンポーネントがある場合は、 +> ブートストラップの過程ではアプリケーション・コンポーネントが使われます。 +> 代りにモジュールを使いたいときは、次のように、無名関数を使って指定することが出来ます。 +> > ```php > [ > function () { @@ -140,11 +149,14 @@ $config = require __DIR__ . '/../config/web.php'; > ] > ``` + ブートストラップの過程で、各コンポーネントのインスタンスが作成されます。 -そして、コンポーネント・クラスが [[yii\base\BootstrapInterface]] を実装している場合は、その [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]] メソッドも呼び出されます。 +そして、コンポーネント・クラスが [[yii\base\BootstrapInterface]] を実装している場合は、 +その [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]] メソッドも呼び出されます。 もう一つの実用的な例が [ベーシック・プロジェクト・テンプレート](start-installation.md) のアプリケーションの構成情報の中にあります。 -そこでは、アプリケーションが開発環境で走るときには `debug` モジュールと `gii` モジュールがブートストラップ・コンポーネントとして構成されています。 +そこでは、アプリケーションが開発環境で走るときには `debug` モジュールと `gii` モジュールが +ブートストラップ・コンポーネントとして構成されています。 ```php if (YII_ENV_DEV) { @@ -158,8 +170,7 @@ if (YII_ENV_DEV) { ``` > Note: あまり多くのコンポーネントを `bootstrap` に置くと、アプリケーションのパフォーマンスを劣化させます。 - なぜなら、リクエストごとに同じ一連のコンポーネントを走らせなければならないからです。 - ですから、ブートストラップ・コンポーネントは賢く使ってください。 + なぜなら、リクエストごとに同じ一連のコンポーネントを走らせなければならないからです。ですから、ブートストラップ・コンポーネントは賢く使ってください。 #### [[yii\web\Application::catchAll|catchAll]] @@ -169,8 +180,7 @@ if (YII_ENV_DEV) { これは主としてアプリケーションがメンテナンス・モードにあって、入ってくる全てのリクエストを単一のアクションで処理する必要があるときに使われます。 構成情報は配列の形を取り、最初の要素はアクションのルートを指定します。 -そして、配列の残りの要素 (キー・値のペア) は、アクションに渡されるパラメータを指定します。 -例えば、 +そして、配列の残りの要素 (キー・値のペア) は、アクションに渡されるパラメータを指定します。例えば、 ```php [ @@ -184,12 +194,10 @@ if (YII_ENV_DEV) { > Info: このプロパティを有効にすると、開発環境でデバッグ・パネルが動作しなくなります。 - #### [[yii\base\Application::components|components]] これこそが、唯一の最も重要なプロパティです。 -これによって、[アプリケーション・コンポーネント](structure-application-components.md) と呼ばれる一連の名前付きのコンポーネントを登録して、それらを他の場所で使うことが出来るようになります。 -例えば、 +これによって、[アプリケーション・コンポーネント](structure-application-components.md) と呼ばれる一連の名前付きのコンポーネントを登録して、それらを他の場所で使うことが出来るようになります。例えば、 ```php [ @@ -234,7 +242,8 @@ if (YII_ENV_DEV) { ] ``` -このプロパティの配列のキーはコントローラ ID を表し、配列の値は対応するコントローラ・クラスの名前または [構成情報](concept-configurations.md) を表します。 +このプロパティの配列のキーはコントローラ ID を表し、配列の値は対応するコントローラ・クラスの名前または +[構成情報](concept-configurations.md) を表します。 #### [[yii\base\Application::controllerNamespace|controllerNamespace]] @@ -244,12 +253,15 @@ if (YII_ENV_DEV) { コントローラ ID が `post` である場合、規約によって対応するコントローラの (名前空間を略した) クラス名は `PostController` となり、完全修飾クラス名は `app\controllers\PostController` となります。 コントローラ・クラスは、この名前空間に対応するディレクトリのサブ・ディレクトリに配置されても構いません。 -例えば、コントローラ ID として `admin/post` を仮定すると、対応するコントローラの完全修飾クラス名は `app\controllers\admin\PostController` となります。 +例えば、コントローラ ID として `admin/post` を仮定すると、対応するコントローラの完全修飾クラス名は +`app\controllers\admin\PostController` となります。 -重要なことは、完全修飾されたコントローラ・クラスが [オートロード可能](concept-autoloading.md) でなければならず、コントローラ・クラスの実際の名前空間がこのプロパティと合致していなければならない、ということです。 +重要なことは、完全修飾されたコントローラ・クラスが [オートロード可能](concept-autoloading.md) でなければならず、 +コントローラ・クラスの実際の名前空間がこのプロパティと合致していなければならない、ということです。 そうでないと、アプリケーションにアクセスしたときに "ページがみつかりません" というエラーを受け取ることになります。 -上で説明された規約を破りたい場合は、[controllerMap](#controllerMap) プロパティを構成することが出来ます。 +上で説明された規約を破りたい場合は、 +[controllerMap](#controllerMap) プロパティを構成することが出来ます。 #### [[yii\base\Application::language|language]] @@ -259,7 +271,9 @@ if (YII_ENV_DEV) { アプリケーションが多言語をサポートする必要があるときは、このプロパティを構成しなければなりません。 このプロパティの値が、メッセージの翻訳、日付の書式、数字の書式などを含む [国際化](tutorial-i18n.md) のさまざまな側面を決定します。 -例えば、[[yii\jui\DatePicker]] ウィジェットは、どの言語でカレンダーを表示すべきか、そして日付をどのように書式設定すべきかを、デフォルトでは、このプロパティを使用して決定します。 +例えば、[[yii\jui\DatePicker]] ウィジェットは、どの言語でカレンダーを表示すべきか、 +そして日付をどのように書式設定すべきかを、デフォルトでは、 +このプロパティを使用して決定します。 言語を指定するのには、[IETF 言語タグ](http://ja.wikipedia.org/wiki/IETF%E8%A8%80%E8%AA%9E%E3%82%BF%E3%82%B0) に従うことが推奨されます。 例えば、`en` は英語を意味し、`en-US` はアメリカ合衆国の英語を意味します。 @@ -295,7 +309,8 @@ if (YII_ENV_DEV) { #### [[yii\base\Application::name|name]] このプロパティは、エンド・ユーザに対して表示されるアプリケーション名を指定するものです。 -[[yii\base\Application::id|id]] プロパティがユニークな値を取らなければならないのとは違って、このプロパティの値は主として表示目的であり、ユニークである必要はありません。 +[[yii\base\Application::id|id]] プロパティがユニークな値を取らなければならないのとは違って、 +このプロパティの値は主として表示目的であり、ユニークである必要はありません。 コードのどこにも使わないのであれば、このプロパティは必ずしも構成する必要はありません。 @@ -303,7 +318,8 @@ if (YII_ENV_DEV) { #### [[yii\base\Application::params|params]] このプロパティは、グローバルにアクセス可能なアプリケーション・パラメータの配列を指定するものです。 -コードの中のいたる処でハードコードされた数値や文字列を使う代りに、それらをアプリケーション・パラメータとして一ヶ所で定義し、必要な場所ではそのパラメータを使うというのが良いプラクティスです。 +コードの中のいたる処でハードコードされた数値や文字列を使う代りに、それらをアプリケーション・パラメータとして一ヶ所で定義し、 +必要な場所ではそのパラメータを使うというのが良いプラクティスです。 例えば、次のように、サムネール画像のサイズをパラメータとして定義することが出来ます。 ```php @@ -321,16 +337,17 @@ $size = \Yii::$app->params['thumbnail.size']; $width = \Yii::$app->params['thumbnail.size'][0]; ``` -後でサムネールのサイズを変更すると決めたときは、アプリケーションの構成情報においてのみサイズを修正すればよく、これに依存するコードには少しも触れる必要がありません。 +後でサムネールのサイズを変更すると決めたときは、アプリケーションの構成情報においてのみサイズを修正すればよく、 +これに依存するコードには少しも触れる必要がありません。 #### [[yii\base\Application::sourceLanguage|sourceLanguage]] -このプロパティはアプリケーション・コードが書かれている言語を指定するものです。 -デフォルト値は `'en-US'`、アメリカ合衆国の英語です。 +このプロパティはアプリケーション・コードが書かれている言語を指定するものです。デフォルト値は `'en-US'`、アメリカ合衆国の英語です。 あなたのコードのテキストのコンテントが英語以外で書かれているときは、このプロパティを構成しなければなりません。 -[language](#language) プロパティと同様に、このプロパティは [IETF 言語タグ](http://ja.wikipedia.org/wiki/IETF%E8%A8%80%E8%AA%9E%E3%82%BF%E3%82%B0) に従って構成しなければなりません。 +[language](#language) プロパティと同様に、このプロパティは +[IETF 言語タグ](http://ja.wikipedia.org/wiki/IETF%E8%A8%80%E8%AA%9E%E3%82%BF%E3%82%B0) に従って構成しなければなりません。 例えば、`en` は英語を意味し、`en-US` はアメリカ合衆国の英語を意味します。 このプロパティに関する詳細は [国際化](tutorial-i18n.md) のセクションで読むことが出来ます。 @@ -348,6 +365,7 @@ $width = \Yii::$app->params['thumbnail.size'][0]; ] ``` +タイム・ゾーンを設定することの意味合いについては、[日付のフォーマッティングのセクション](output-formatting.md#time-zones) で詳細を参照して下さい。 #### [[yii\base\Application::version|version]] @@ -357,14 +375,14 @@ $width = \Yii::$app->params['thumbnail.size'][0]; ### 有用なプロパティ -この項で説明されるプロパティは通常は構成されません。というのは、そのデフォルト値が通常の規約を指定しているからです。 +この項で説明されるプロパティは通常は構成されません。というのは、そのデフォルト値が通常の規約に由来するものであるからです。 しかしながら、規約を破る必要がある場合には、これらのプロパティを構成することが出来ます。 #### [[yii\base\Application::charset|charset]] このプロパティはアプリケーションが使う文字セットを指定するものです。 -デフォルト値は `'UTF-8'` であり、あなたのアプリケーションが多数の非ユニコード・データを使うレガシー・システムと連携するのでなければ、たいていのアプリケーションでは、そのままにしておくべきです。 +デフォルト値は `'UTF-8'` であり、多数の非ユニコード・データを使うレガシー・システムを扱っている場合を除けば、たいていのアプリケーションでは、そのままにしておくべきです。 #### [[yii\base\Application::defaultRoute|defaultRoute]] @@ -374,10 +392,12 @@ $width = \Yii::$app->params['thumbnail.size'][0]; 例えば、`help`、`post/create`、`admin/post/create` などです。 アクション ID が与えられていない場合は、[[yii\base\Controller::defaultAction]] で指定されるデフォルト値を取ります。 -[[yii\web\Application|ウェブ・アプリケーション]] では、このプロパティのデフォルト値は `'site'` であり、その意味するところは、`SiteController` コントローラとそのデフォルト・アクションが使用されるべきである、ということです。 +[[yii\web\Application|ウェブ・アプリケーション]] では、このプロパティのデフォルト値は `'site'` であり、 +その意味するところは、`SiteController` コントローラとそのデフォルト・アクションが使用されるべきである、ということです。 結果として、ルートを指定せずにアプリケーションにアクセスすると、`app\controllers\SiteController::actionIndex()` の結果が表示されます。 -[[yii\console\Application|コンソール・アプリケーション]] では、デフォルト値は `'help'` であり、コア・コマンドの [[yii\console\controllers\HelpController::actionIndex()]] が使用されるべきであるという意味です。 +[[yii\console\Application|コンソール・アプリケーション]] では、デフォルト値は `'help'` であり、 +コア・コマンドの [[yii\console\controllers\HelpController::actionIndex()]] が使用されるべきであるという意味です。 結果として、何も引数を与えずに `yii` というコマンドを実行すると、ヘルプ情報が表示されることになります。 @@ -419,7 +439,8 @@ $width = \Yii::$app->params['thumbnail.size'][0]; このプロパティは、[ビュー](structure-views.md) をレンダリングするときに使われるべきデフォルトのレイアウトを指定するものです。 デフォルト値は `'main'` であり、[レイアウト・パス](#layoutPath) の下にある `main.php` というファイルが使われるべきことを意味します。 -[レイアウト・パス](#layoutPath) と [ビュー・パス](#viewPath) の両方がデフォルト値を取る場合、デフォルトのレイアウト・ファイルは `@app/views/layouts/main.php` というパス・エイリアスとして表すことが出来ます。 +[レイアウト・パス](#layoutPath) と [ビュー・パス](#viewPath) の両方がデフォルト値を取る場合、デフォルトのレイアウト・ファイルは +`@app/views/layouts/main.php` というパス・エイリアスとして表すことが出来ます。 滅多には無いことですが、レイアウトをデフォルトで無効にしたい場合は、このプロパティを `false` として構成することが出来ます。 @@ -427,10 +448,10 @@ $width = \Yii::$app->params['thumbnail.size'][0]; #### [[yii\base\Application::layoutPath|layoutPath]] このプロパティは、レイアウト・ファイルが捜されるべきパスを指定するものです。 -デフォルト値は、[ビューパス](#viewPath) の下の `layouts` サブ・ディレクトリです。 +デフォルト値は、[ビュー・パス](#viewPath) の下の `layouts` サブ・ディレクトリです。 [ビュー・パス](#viewPath) がデフォルト値を取る場合、デフォルトのレイアウト・パスは `@app/views/layouts` というパス・エイリアスとして表すことが出来ます。 -このプロパティはディレクトリまたはパス [エイリアス](concept-aliases.md) として構成することが出来ます。 +このプロパティはディレクトリまたはパス・[エイリアス](concept-aliases.md) として構成することが出来ます。 #### [[yii\base\Application::runtimePath|runtimePath]] @@ -438,7 +459,7 @@ $width = \Yii::$app->params['thumbnail.size'][0]; このプロパティは、ログ・ファイルやキャッシュ・ファイルなどの一時的ファイルを生成することが出来るパスを指定するものです。 デフォルト値は、`@app/runtime` というエイリアスで表現されるディレクトリです。 -このプロパティはディレクトリまたはパス [エイリアス](concept-aliases.md) として構成することが出来ます。 +このプロパティはディレクトリまたはパス・[エイリアス](concept-aliases.md) として構成することが出来ます。 ランタイムパスは、アプリケーションを実行するプロセスによって書き込みが可能なものでなければならないことに注意してください。 そして、この下にある一時的ファイルは秘匿を要する情報を含みうるものですので、ランタイム・パスはエンド・ユーザによるアクセスから保護されなければなりません。 @@ -447,18 +468,17 @@ $width = \Yii::$app->params['thumbnail.size'][0]; #### [[yii\base\Application::viewPath|viewPath]] -このプロパティはビュー・ファイルが配置されるルート・ディレクトリを指定するものです。 -デフォルト値は、`@app/views` というエイリアスで表現されるディレクトリです。 +このプロパティはビュー・ファイルが配置されるルート・ディレクトリを指定するものです。デフォルト値は、`@app/views` というエイリアスで表現されるディレクトリです。 このプロパティはディレクトリまたはパス・[エイリアス](concept-aliases.md) として構成することが出来ます。 #### [[yii\base\Application::vendorPath|vendorPath]] このプロパティは、[Composer](https://getcomposer.org) によって管理される vendor ディレクトリを指定するものです。 -Yii フレームワークを含めて、あなたのアプリケーションによって使われる全てのサードパーティ・ライブラリを格納するディレクトリです。 +Yii フレームワークを含めて、あなたのアプリケーションによって使われる全てのサード・パーティ・ライブラリを格納するディレクトリです。 デフォルト値は、`@app/vendor` というエイリアスで表現されるディレクトリです。 -このプロパティはディレクトリまたはパス [エイリアス](concept-aliases.md) として構成することが出来ます。 +このプロパティはディレクトリまたはパス・[エイリアス](concept-aliases.md) として構成することが出来ます。 このプロパティを修正するときは、必ず、Composer の構成もそれに合せて修正してください。 このパスに簡単にアクセスできるように、Yii は `@vendor` というパス・エイリアスを事前に定義しています。 @@ -472,7 +492,7 @@ Yii リリースに含まれているコア・コマンドを有効にすべき ## アプリケーションのイベント -アプリケーションはリクエストを処理するライフ・サイクルの中でいくつかのイベントをトリガします。 +アプリケーションはリクエストを処理するライフサイクルの中でいくつかのイベントをトリガします。 これらのイベントに対して、下記のようにして、アプリケーションの構成情報の中でイベント・ハンドラをアタッチすることが出来ます。 ```php @@ -483,7 +503,8 @@ Yii リリースに含まれているコア・コマンドを有効にすべき ] ``` -`on eventName` という構文の使い方については、[構成情報](concept-configurations.md#configuration-format) のセクションで説明されています。 +`on eventName` という構文の使い方については、[構成情報](concept-configurations.md#configuration-format) +のセクションで説明されています。 別の方法として、アプリケーションのインスタンスが生成された後、[ブートストラップの過程](runtime-bootstrapping.md) の中でイベント・ハンドラをアタッチすることも出来ます。 例えば、 @@ -496,8 +517,7 @@ Yii リリースに含まれているコア・コマンドを有効にすべき ### [[yii\base\Application::EVENT_BEFORE_REQUEST|EVENT_BEFORE_REQUEST]] -このイベントは、アプリケーションがリクエストを処理する *前* にトリガされます。 -実際のイベント名は `beforeRequest` です。 +このイベントは、アプリケーションがリクエストを処理する *前* にトリガされます。実際のイベント名は `beforeRequest` です。 このイベントがトリガされるときには、アプリケーションのインスタンスは既に構成されて初期化されています。 ですから、イベント・メカニズムを使って、リクエスト処理のプロセスに干渉するカスタム・コードを挿入するのには、ちょうど良い場所です。 @@ -509,7 +529,8 @@ Yii リリースに含まれているコア・コマンドを有効にすべき このイベントは、アプリケーションがリクエストの処理を完了した *後*、レスポンスを送信する *前* にトリガされます。 実際のイベント名は `afterRequest` です。 -このイベントがトリガされるときにはリクエストの処理は完了していますので、この機をとらえて、リクエストに対する何らかの後処理をしたり、レスポンスをカスタマイズしたりすることが出来ます。 +このイベントがトリガされるときにはリクエストの処理は完了していますので、この機をとらえて、 +リクエストに対する何らかの後処理をしたり、レスポンスをカスタマイズしたりすることが出来ます。 [[yii\web\Response|response]] コンポーネントも、エンド・ユーザにレスポンスのコンテントを送出する間にいくつかのイベントをトリガすることに注意してください。 それらのイベントは、このイベントの *後* にトリガされます。 @@ -536,8 +557,9 @@ Yii リリースに含まれているコア・コマンドを有効にすべき ``` 同じ `beforeAction` イベントが、[モジュール](structure-modules.md) と [コントローラ](structure-controllers.md) からもトリガされることに注意してください。 -アプリケーション・オブジェクトが最初にこのイベントをトリガし、次に (もし有れば) モジュールが、そして最後にコントローラがこのイベントをトリガします。 -イベント・ハンドラが [[yii\base\ActionEvent::isValid]] を `false` にセットすると、後続のイベントはトリガされません。 +アプリケーション・オブジェクトが最初にこのイベントをトリガし、次に (もし有れば) モジュールが、 +そして最後にコントローラがこのイベントをトリガします。 +いずれかのイベント・ハンドラが [[yii\base\ActionEvent::isValid]] を `false` にセットすると、後続のイベントはトリガされません。 ### [[yii\base\Application::EVENT_AFTER_ACTION|EVENT_AFTER_ACTION]] @@ -562,26 +584,29 @@ Yii リリースに含まれているコア・コマンドを有効にすべき 同じ `afterAction` イベントが、[モジュール](structure-modules.md) と [コントローラ](structure-controllers.md) からもトリガされることに注意してください。 これらのオブジェクトは、`beforeAction` の場合とは逆の順でイベントをトリガします。 -すなわち、コントローラ・オブジェクトが最初にこのイベントをトリガし、次に (もし有れば) モジュールが、そして最後にアプリケーションがこのイベントをトリガします。 +すなわち、コントローラ・オブジェクトが最初にこのイベントをトリガし、次に (もし有れば) モジュールが、 +そして最後にアプリケーションがこのイベントをトリガします。 -## アプリケーションのライフ・サイクル +## アプリケーションのライフサイクル -![アプリケーションのライフ・サイクル](images/application-lifecycle.png) +![アプリケーションのライフサイクル](images/application-lifecycle.png) -[エントリ・スクリプト](structure-entry-scripts.md) が実行されて、リクエストが処理されるとき、アプリケーションは次のようなライフ・サイクルを経ます。 +[エントリ・スクリプト](structure-entry-scripts.md) が実行されて、リクエストが処理されるとき、 +アプリケーションは次のようなライフサイクルを経ます。 1. エントリ・スクリプトがアプリケーションの構成情報を配列として読み出す。 2. エントリ・スクリプトがアプリケーションの新しいインスタンスを作成する。 - * [[yii\base\Application::preInit()|preInit()]] が呼び出されて、[[yii\base\Application::basePath|basePath]] のような、優先度の高いアプリケーション・プロパティを構成する。 + * [[yii\base\Application::preInit()|preInit()]] が呼び出されて、[[yii\base\Application::basePath|basePath]] のような、 + 優先度の高いアプリケーション・プロパティを構成する。 * [[yii\base\Application::errorHandler|エラー・ハンドラ]] を登録する。 * アプリケーションのプロパティを構成する。 - * [[yii\base\Application::init()|init()]] が呼ばれ、そこから更に、ブートストラップ・コンポーネントを走らせるために、[[yii\base\Application::bootstrap()|bootstrap()]] が呼ばれる。 + * [[yii\base\Application::init()|init()]] が呼ばれ、そこから更に、ブートストラップ・コンポーネントを走らせるために、 + [[yii\base\Application::bootstrap()|bootstrap()]] が呼ばれる。 3. エントリ・スクリプトが [[yii\base\Application::run()]] を呼んで、アプリケーションを走らせる。 * [[yii\base\Application::EVENT_BEFORE_REQUEST|EVENT_BEFORE_REQUEST]] イベントをトリガする。 * リクエストを処理する: リクエストを [ルート](runtime-routing.md) とそれに結び付くパラメータとして解決する。 - ルートによって指定されたモジュール、コントローラ、および、アクションを作成する。 - そしてアクションを実行する。 + ルートによって指定されたモジュール、コントローラ、および、アクションを作成する。そしてアクションを実行する。 * [[yii\base\Application::EVENT_AFTER_REQUEST|EVENT_AFTER_REQUEST]] イベントをトリガする。 * エンド・ユーザにレスポンスを送信する。 4. エントリ・スクリプトがアプリケーションから終了ステータスを受け取り、リクエストの処理を完了する。 diff --git a/docs/guide-ja/structure-assets.md b/docs/guide-ja/structure-assets.md index 6ba031d6dcc..760ae85b776 100644 --- a/docs/guide-ja/structure-assets.md +++ b/docs/guide-ja/structure-assets.md @@ -1,8 +1,7 @@ アセット ======== -Yii では、アセットは、ウェブ・ページで参照できるファイルを意味します。 -アセットは CSS ファイルであったり、JavaScript ファイルであったり、画像やビデオのファイルであったりします。 +Yii では、アセットは、ウェブ・ページで参照できるファイルを意味します。アセットは CSS ファイルであったり、JavaScript ファイルであったり、画像やビデオのファイルであったりします。 アセットはウェブでアクセス可能なディレクトリに配置され、ウェブ・サーバによって直接に提供されます。 たいていの場合、アセットはプログラム的に管理する方が望ましいものです。 @@ -14,7 +13,8 @@ Yii では、アセットは、ウェブ・ページで参照できるファイ ## アセット・バンドル -Yii はアセットを *アセット・バンドル* を単位として管理します。アセット・バンドルは、簡単に言えば、あるディレクトリの下に集められた一群のアセットです。 +Yii はアセットを *アセット・バンドル* を単位として管理します。アセット・バンドルは、簡単に言えば、 +あるディレクトリの下に集められた一群のアセットです。 [ビュー](structure-views.md) の中でアセット・バンドルを登録すると、バンドルの中の CSS や JavaScript のファイルがレンダリングされるウェブ・ページに挿入されます。 @@ -22,8 +22,8 @@ Yii はアセットを *アセット・バンドル* を単位として管理し アセット・バンドルは [[yii\web\AssetBundle]] から拡張された PHP クラスとして定義されます。 バンドルの名前は、対応する PHP クラスの完全修飾名 (先頭のバック・スラッシュを除く) です。 -アセット・バンドルクラスは [オートロード可能](concept-autoloading.md) でなければなりません。 -アセット・バンドルクラスは、通常、アセットがどこに置かれているか、バンドルがどういう CSS や JavaScript のファイルを含んでいるか、そして、バンドルが他のバンドルにどのように依存しているかを定義します。 +アセット・バンドル・クラスは [オートロード可能](concept-autoloading.md) でなければなりません。 +アセット・バンドル・クラスは、通常、アセットがどこに置かれているか、バンドルがどういう CSS や JavaScript のファイルを含んでいるか、そして、バンドルが他のバンドルにどのように依存しているかを定義します。 以下のコードは [ベーシック・プロジェクト・テンプレート](start-installation.md) によって使用されているメインのアセット・バンドルを定義するものです。 @@ -57,15 +57,17 @@ class AppAsset extends AssetBundle 以下、[[yii\web\AssetBundle]] のプロパティに関して、更に詳細に説明します。 * [[yii\web\AssetBundle::sourcePath|sourcePath]]: このバンドルのアセット・ファイルを含むルート・ディレクトリを指定します。 - ルート・ディレクトリがウェブからアクセス可能でない場合に、このプロパティをセットしなければなりません。 + ルート・ディレクトリがウェブ・アクセス可能でない場合に、このプロパティをセットしなければなりません。 そうでない場合は、代りに、[[yii\web\AssetBundle::basePath|basePath]] と [[yii\web\AssetBundle::baseUrl|baseUrl]] のプロパティをセットしなければなりません。 [パス・エイリアス](concept-aliases.md) をここで使うことが出来ます。 -* [[yii\web\AssetBundle::basePath|basePath]]: このバンドルのアセット・ファイルを含むウェブからアクセス可能なディレクトリを指定します。 - [[yii\web\AssetBundle::sourcePath|sourcePath]] プロパティをセットした場合は、[アセットマネージャ](#asset-manager) がバンドルに含まれるファイルをウェブからアクセス可能なディレクトリに発行して、その結果、このプロパティを上書きします。 - アセット・ファイルが既にウェブからアクセス可能なディレクトリにあり、アセットの発行が必要でない場合に、このプロパティをセットしなければなりません。 +* [[yii\web\AssetBundle::basePath|basePath]]: このバンドルのアセット・ファイルを含むウェブ・アクセス可能なディレクトリを指定します。 + [[yii\web\AssetBundle::sourcePath|sourcePath]] プロパティをセットした場合は、[アセット・マネージャ](#asset-manager) がバンドルに含まれるファイルをウェブ・アクセス可能なディレクトリに発行して、 + その結果、このプロパティを上書きします。 + アセット・ファイルが既にウェブ・アクセス可能なディレクトリにあり、アセットの発行が必要でない場合に、このプロパティをセットしなければなりません。 [パス・エイリアス](concept-aliases.md) をここで使うことが出来ます。 * [[yii\web\AssetBundle::baseUrl|baseUrl]]: [[yii\web\AssetBundle::basePath|basePath]] ディレクトリに対応する URL を指定します。 - [[yii\web\AssetBundle::basePath|basePath]] と同じように、[[yii\web\AssetBundle::sourcePath|sourcePath]] プロパティをセットした場合は、[アセット・マネージャ](#asset-manager) がアセットを発行して、その結果、このプロパティを上書きします。 + [[yii\web\AssetBundle::basePath|basePath]] と同じように、[[yii\web\AssetBundle::sourcePath|sourcePath]] プロパティをセットした場合は、 + [アセット・マネージャ](#asset-manager) がアセットを発行して、その結果、このプロパティを上書きします。 [パス・エイリアス](concept-aliases.md) をここで使うことが出来ます。 * [[yii\web\AssetBundle::css|css]]: このバンドルに含まれている CSS ファイルをリストする配列です。 ディレクトリの区切りとしてフォワード・スラッシュ "/" だけを使わなければならないことに注意してください。 @@ -77,11 +79,16 @@ class AppAsset extends AssetBundle 実際のファイルのパスは、この相対パスの前に [[yii\web\AssetManager::basePath]] を付けることによって決定されます。 また、実際の URL は、この相対パスの前に [[yii\web\AssetManager::baseUrl]] を付けることによって決定されます。 - 外部の JavaScript ファイルを表す絶対 URL。 - 例えば、`http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` や `//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` など。 + 例えば、`http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` や + `//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` など。 * [[yii\web\AssetBundle::depends|depends]]: このバンドルが依存しているアセット・バンドルの名前をリストする配列です (バンドルの依存関係については、すぐ後で説明します)。 -* [[yii\web\AssetBundle::jsOptions|jsOptions]]: このバンドルにある *全て* の JavaScript ファイルについて、それを登録するときに呼ばれる [[yii\web\View::registerJsFile()]] メソッドに渡されるオプションを指定します。 -* [[yii\web\AssetBundle::publishOptions|publishOptions]]: ソースのアセット・ファイルをウェブ・ディレクトリに発行するときに呼ばれる [[yii\web\AssetManager::publish()]] メソッドに渡されるオプションを指定します。 +* [[yii\web\AssetBundle::jsOptions|jsOptions]]: このバンドルにある *全て* の JavaScript ファイルについて、 + それを登録するときに呼ばれる [[yii\web\View::registerJsFile()]] メソッドに渡されるオプションを指定します。 +* [[yii\web\AssetBundle::cssOptions|cssOptions]]: このバンドルにある *全て* の CSS ファイルについて、 + それを登録するときに呼ばれる [[yii\web\View::registerCssFile()]] メソッドに渡されるオプションを指定します。 +* [[yii\web\AssetBundle::publishOptions|publishOptions]]: ソースのアセット・ファイルをウェブ・ディレクトリに発行するときに呼ばれる + [[yii\web\AssetManager::publish()]] メソッドに渡されるオプションを指定します。 これは [[yii\web\AssetBundle::sourcePath|sourcePath]] プロパティを指定した場合にだけ使用されます。 @@ -89,43 +96,53 @@ class AppAsset extends AssetBundle アセットは、配置場所を基準にして、次のように分類することが出来ます。 -* ソースアセット: アセット・ファイルは、ウェブ経由で直接にアクセスすることが出来ない PHP ソース・コードと一緒に配置されています。 - ページの中でソースアセットを使用するためには、ウェブ・ディレクトリにコピーして、いわゆる発行されたアセットに変換しなければなりません。 +* ソース・アセット: アセット・ファイルは、ウェブ経由で直接にアクセスすることが出来ない PHP ソース・コードと一緒に配置されています。 + ページの中でソース・アセットを使用するためには、ウェブ・ディレクトリにコピーして、いわゆる発行されたアセットに変換しなければなりません。 このプロセスは、すぐ後で詳しく説明しますが、*アセット発行* と呼ばれます。 * 発行されたアセット: アセット・ファイルはウェブ・ディレクトリに配置されており、したがってウェブ経由で直接にアクセスすることが出来ます。 -* 外部アセット: アセット・ファイルは、あなたのウェブ・アプリケーションをホストしているのとは別のウェブ・サーバ上に配置されています。 +* 外部アセット: アセット・ファイルは、あなたのウェブ・アプリケーションをホストしているのとは別のウェブ・サーバ上に + 配置されています。 -アセット・バンドル・クラスを定義するときに、[[yii\web\AssetBundle::sourcePath|sourcePath]] プロパティを指定した場合は、相対パスを使ってリストに挙げられたアセットは全てソースアセットであると見なされます。 +アセット・バンドル・クラスを定義するときに、[[yii\web\AssetBundle::sourcePath|sourcePath]] プロパティを指定した場合は、 +相対パスを使ってリストに挙げられたアセットは全てソース・アセットであると見なされます。 このプロパティを指定しなかった場合は、アセットは発行されたアセットであることになります (したがって、[[yii\web\AssetBundle::basePath|basePath]] と [[yii\web\AssetBundle::baseUrl|baseUrl]] を指定して、アセットがどこに配置されているかを Yii に知らせなければなりません)。 アプリケーションに属するアセットは、不要なアセット発行プロセスを避けるために、ウェブ・ディレクトリに置くことが推奨されます。 -前述の例において `AppAsset` が [[yii\web\AssetBundle::sourcePath|sourcePath]] ではなく [[yii\web\AssetBundle::basePath|basePath]] を指定しているのは、これが理由です。 +前述の例において `AppAsset` が [[yii\web\AssetBundle::sourcePath|sourcePath]] ではなく +[[yii\web\AssetBundle::basePath|basePath]] を指定しているのは、これが理由です。 -[エクステンション](structure-extensions.md) の場合は、アセットがソース・コードと一緒にウェブからアクセス出来ないディレクトリに配置されているため、アセット・バンドル・クラスを定義するときには [[yii\web\AssetBundle::sourcePath|sourcePath]] プロパティを指定しなければなりません。 +[エクステンション](structure-extensions.md) の場合は、 +アセットがソース・コードと一緒にウェブからアクセス出来ないディレクトリに配置されているため、 +アセット・バンドル・クラスを定義するときには [[yii\web\AssetBundle::sourcePath|sourcePath]] プロパティを指定しなければなりません。 > Note: `@webroot/assets` を [[yii\web\AssetBundle::sourcePath|ソース・パス]] として使ってはいけません。 このディレクトリは、デフォルトでは、[[yii\web\AssetManager|アセット・マネージャ]] がソースの配置場所から発行されたアセット・ファイルを保存する場所として使われます。 - このディレクトリの中のファイルはすべて一時的なものと見なされており、削除されることがあります。 + このディレクトリの中のファイルはすべて一時的なものと見なされており、 + 削除されることがあります。 ### アセットの依存関係 ウェブ・ページに複数の CSS や JavaScript ファイルをインクルードするときは、オーバーライドの問題を避けるために、一定の順序に従わなければなりません。 -例えば、ウェブ・ページで jQuery UI ウィジェットを使おうとするときは、jQuery JavaScript ファイルが jQuery UI JavaScript ファイルより前にインクルードされることを保証しなければなりません。 +例えば、ウェブ・ページで jQuery UI ウィジェットを使おうとするときは、jQuery JavaScript ファイルが +jQuery UI JavaScript ファイルより前にインクルードされることを保証しなければなりません。 このような順序付けをアセット間の依存関係と呼びます。 アセットの依存関係は、主として、[[yii\web\AssetBundle::depends]] プロパティによって指定されます。 `AppAsset` の例では、このアセット・バンドルは他の二つのアセット・バンドル、すなわち、[[yii\web\YiiAsset]] と [[yii\bootstrap\BootstrapAsset]] に依存しています。 -このことは、`AppAsset` の CSS と JavaScript ファイルが、依存している二つのアセット・バンドルにあるファイルの *後に* インクルードされることを意味します。 +このことは、`AppAsset` の CSS と JavaScript ファイルが、依存している二つのアセット・バンドルにあるファイルの *後に* +インクルードされることを意味します。 アセットの依存関係は中継されます。つまり、バンドル A が B に依存し、B が C に依存していると、A は C にも依存していることになります。 ### アセットのオプション -[[yii\web\AssetBundle::cssOptions|cssOptions]] および [[yii\web\AssetBundle::jsOptions|jsOptions]] のプロパティを指定して、CSS と JavaScript ファイルがページにインクルードされる方法をカスタマイズすることが出来ます。 -これらのプロパティの値は、[ビュー](structure-views.md) が CSS と JavaScript ファイルをインクルードするために、[[yii\web\View::registerCssFile()]] および [[yii\web\View::registerJsFile()]] メソッドを呼ぶときに、それぞれ、オプションとして引き渡されます。 +[[yii\web\AssetBundle::cssOptions|cssOptions]] および [[yii\web\AssetBundle::jsOptions|jsOptions]] のプロパティを指定して、 +CSS と JavaScript ファイルがページにインクルードされる方法をカスタマイズすることが出来ます。 +これらのプロパティの値は、[ビュー](structure-views.md) が CSS と JavaScript ファイルをインクルードするために、[[yii\web\View::registerCssFile()]] および +[[yii\web\View::registerJsFile()]] メソッドを呼ぶときに、それぞれ、オプションとして引き渡されます。 > Note: バンドル・クラスでセットしたオプションは、バンドルの中の *全て* の CSS/JavaScript ファイルに適用されます。 いろいろなファイルに別々のオプションを使用したい場合は、上述した [[yii\web\AssetBundle::css|css] の形式を使うか、 @@ -158,7 +175,8 @@ JavaScript ファイルをページの head セクションにインクルード public $jsOptions = ['position' => \yii\web\View::POS_HEAD]; ``` -デフォルトでは、アセット・バンドルが発行されるときは、[[yii\web\AssetBundle::sourcePath]] で指定されたディレクトリの中にある全てのコンテントが発行されます。 +デフォルトでは、アセット・バンドルが発行されるときは、[[yii\web\AssetBundle::sourcePath]] +で指定されたディレクトリの中にある全てのコンテントが発行されます。 [[yii\web\AssetBundle::publishOptions|publishOptions]] プロパティを構成することによって、この振る舞いをカスタマイズすることが出来ます。 例えば、[[yii\web\AssetBundle::sourcePath]] の一個または数個のサブ・ディレクトリだけを発行するために、アセット・バンドル・クラスの中で下記のようにすることが出来ます。 @@ -197,13 +215,12 @@ PHP の世界には PHP の依存を管理する Composer がありますが、P ___ -##### asset-packagist レポジトリを使う +#### asset-packagist レポジトリを使う この方法は NPM または Bower のパッケージを必要とするプロジェクトの大半の要求を満たすことが出来ます。 > Note: 2.0.13 以降、ベーシック・アプリケーション・テンプレートとアドバンスト・アプリケーション・テンプレートはともに、 - デフォルトで asset-packagist を使うように前もって構成されていますので、 - このセクションは読み飛ばすことが出来ます。 + デフォルトで asset-packagist を使うように前もって構成されていますので、このセクションは読み飛ばすことが出来ます。 プロジェクトの `composer.json` に、下記を追加します。 @@ -231,7 +248,7 @@ $config = [ asset-packagist がどのようにして動作するのかは、[asset-packagist.org のサイト](https://asset-packagist.org) に説明があります。 -##### fxp/composer-asset-plugin を使う +#### fxp/composer-asset-plugin を使う asset-packagist と異なって、composer-asset-plugin はアプリケーション構成の変更を少しも要求しません。 その代りに、次のコマンドを実行して特別な Composer プラグインをグローバルにインストールすることが要求されます。 @@ -248,7 +265,7 @@ Yii を使ってこれらのアセットを発行したい場合は、プロジ インストールされるパッケージが配置されるディレクトリを調整します。 ```json -"extra": { +"config": { "asset-installer-paths": { "npm-asset-library": "vendor/npm", "bower-asset-library": "vendor/bower" @@ -256,16 +273,18 @@ Yii を使ってこれらのアセットを発行したい場合は、プロジ } ``` -> Note: `fxp/composer-asset-plugin` は、asset-packagist に比べて、`composer update` コマンドを著しく遅くします。 +> Note: `fxp/composer-asset-plugin` は、asset-packagist に比べて、`composer update` + コマンドを著しく遅くします。 ____ Composer で Bower と NPM をサポートできるように構成した後は: 1. アプリケーションまたはエクステンションの `composer.json` ファイルを修正して、パッケージを `require` のエントリに入れます。 - ライブラリを参照するのに、`bower-asset/PackageName` (Bower パッケージ) または `npm-asset/PackageName` (NPM パッケージ) を使わなければなりません。 + ライブラリを参照するのに、`bower-asset/PackageName` (Bower パッケージ) または `npm-asset/PackageName` (NPM パッケージ) + を使わなければなりません。 2. `composer update` を実行します。 -3. アセット・バンドルクラスを作成して、アプリケーションまたはエクステンションで使う予定の JavaScript/CSS ファイルをリストに挙げます。 +3. アセット・バンドル・クラスを作成して、アプリケーションまたはエクステンションで使う予定の JavaScript/CSS ファイルをリストに挙げます。 [[yii\web\AssetBundle::sourcePath|sourcePath]] プロパティは、`@bower/PackageName` または `@npm/PackageName` としなければなりません。 これは、Composer が Bower または NPM パッケージを、このエイリアスに対応するディレクトリにインストールするためです。 @@ -284,20 +303,23 @@ use app\assets\AppAsset; AppAsset::register($this); // $this はビュー・オブジェクトを表す ``` -> Info: [[yii\web\AssetBundle::register()]] メソッドは、[[yii\web\AssetBundle::basePath|basePath]] や [[yii\web\AssetBundle::baseUrl|baseUrl]] など、発行されたアセットに関する情報を含むアセット・バンドル・オブジェクトを返します。 +> Info: [[yii\web\AssetBundle::register()]] メソッドは、[[yii\web\AssetBundle::basePath|basePath]] や [[yii\web\AssetBundle::baseUrl|baseUrl]] など、 + 発行されたアセットに関する情報を含むアセット・バンドル・オブジェクトを返します。 他の場所でアセット・バンドルを登録しようとするときは、必要とされるビュー・オブジェクトを提供しなければなりません。 -例えば、[ウィジェット](structure-widgets.md) クラスの中でアセット・バンドルを登録するためには、`$this->view` によってビュー・オブジェクトを取得することが出来ます。 +例えば、[ウィジェット](structure-widgets.md)・クラスの中でアセット・バンドルを登録するためには、`$this->view` によってビュー・オブジェクトを取得することが出来ます。 アセット・バンドルがビューに登録されるとき、舞台裏では、依存している全てのアセット・バンドルが Yii によって登録されます。 -そして、アセット・バンドルがウェブからはアクセス出来ないディレクトリに配置されている場合は、アセット・バンドルがウェブ・ディレクトリに発行されます。 +そして、アセット・バンドルがウェブからはアクセス出来ないディレクトリに配置されている場合は、 +アセット・バンドルがウェブ・ディレクトリに発行されます。 その後、ビューがページをレンダリングするときに、登録されたバンドルのリストに挙げられている CSS と JavaScript ファイルのための `` タグと `