Browse Source

Merge branch 'master' into SamMousa-indexby-after-relations-9342

Conflicts:
	framework/db/Query.php
tags/2.0.14
SilverFire - Dmitry Naumenko 7 years ago
parent
commit
c3c9d1fd97
No known key found for this signature in database
GPG Key ID: 39DD917A92B270A
  1. 1
      .gitattributes
  2. 30
      .gitlab-ci.yml
  3. 36
      .travis.yml
  4. 3
      Dockerfile
  5. 5
      README.md
  6. 2
      build/controllers/ClassmapController.php
  7. 44
      build/controllers/DevController.php
  8. 92
      build/controllers/MimeTypeController.php
  9. 101
      build/controllers/PhpDocController.php
  10. 38
      build/controllers/ReleaseController.php
  11. 18
      build/controllers/Utf8Controller.php
  12. 462
      composer.lock
  13. 4
      contrib/completion/bash/yii
  14. 4
      contrib/completion/zsh/_yii
  15. 4
      docs/guide-es/caching-data.md
  16. 2
      docs/guide-es/concept-di-container.md
  17. 2
      docs/guide-es/concept-events.md
  18. 10
      docs/guide-es/runtime-logging.md
  19. 4
      docs/guide-es/start-installation.md
  20. 2
      docs/guide-es/structure-filters.md
  21. 4
      docs/guide-fr/caching-data.md
  22. 4
      docs/guide-fr/concept-di-container.md
  23. 4
      docs/guide-fr/concept-events.md
  24. 10
      docs/guide-fr/runtime-logging.md
  25. 4
      docs/guide-fr/start-installation.md
  26. 2
      docs/guide-fr/structure-filters.md
  27. 2
      docs/guide-fr/tutorial-i18n.md
  28. 4
      docs/guide-id/start-installation.md
  29. 4
      docs/guide-it/start-installation.md
  30. 4
      docs/guide-ja/caching-data.md
  31. 10
      docs/guide-ja/concept-di-container.md
  32. 4
      docs/guide-ja/concept-events.md
  33. 2
      docs/guide-ja/output-client-scripts.md
  34. 10
      docs/guide-ja/runtime-logging.md
  35. 4
      docs/guide-ja/start-installation.md
  36. 2
      docs/guide-ja/structure-filters.md
  37. 2
      docs/guide-ja/tutorial-i18n.md
  38. 2
      docs/guide-pl/README.md
  39. 192
      docs/guide-pl/input-form-javascript.md
  40. 4
      docs/guide-pl/start-installation.md
  41. 209
      docs/guide-pl/tutorial-yii-as-micro-framework.md
  42. 4
      docs/guide-pt-BR/caching-data.md
  43. 4
      docs/guide-pt-BR/concept-di-container.md
  44. 2
      docs/guide-pt-BR/concept-events.md
  45. 10
      docs/guide-pt-BR/runtime-logging.md
  46. 4
      docs/guide-pt-BR/start-installation.md
  47. 2
      docs/guide-pt-BR/structure-filters.md
  48. 3
      docs/guide-ru/README.md
  49. 12
      docs/guide-ru/caching-data.md
  50. 3
      docs/guide-ru/concept-aliases.md
  51. 12
      docs/guide-ru/concept-di-container.md
  52. 4
      docs/guide-ru/concept-events.md
  53. 8
      docs/guide-ru/db-migrations.md
  54. 12
      docs/guide-ru/input-validation.md
  55. 20
      docs/guide-ru/intro-yii.md
  56. 8
      docs/guide-ru/output-data-providers.md
  57. 20
      docs/guide-ru/output-data-widgets.md
  58. 21
      docs/guide-ru/output-formatting.md
  59. 14
      docs/guide-ru/rest-resources.md
  60. 14
      docs/guide-ru/runtime-logging.md
  61. 72
      docs/guide-ru/security-best-practices.md
  62. 4
      docs/guide-ru/start-installation.md
  63. 2
      docs/guide-ru/structure-filters.md
  64. 7
      docs/guide-ru/structure-modules.md
  65. 9
      docs/guide-ru/test-acceptance.md
  66. 1
      docs/guide-ru/translators.json
  67. 2
      docs/guide-ru/tutorial-i18n.md
  68. 206
      docs/guide-ru/tutorial-yii-as-micro-framework.md
  69. 4
      docs/guide-uk/start-installation.md
  70. 4
      docs/guide-vi/start-installation.md
  71. 4
      docs/guide-zh-CN/caching-data.md
  72. 2
      docs/guide-zh-CN/concept-di-container.md
  73. 2
      docs/guide-zh-CN/concept-events.md
  74. 4
      docs/guide-zh-CN/start-installation.md
  75. 2
      docs/guide-zh-CN/structure-filters.md
  76. 13
      docs/guide/README.md
  77. 4
      docs/guide/caching-data.md
  78. 3
      docs/guide/caching-fragment.md
  79. 3
      docs/guide/concept-aliases.md
  80. 8
      docs/guide/concept-di-container.md
  81. 77
      docs/guide/concept-events.md
  82. 63
      docs/guide/db-active-record.md
  83. 37
      docs/guide/db-migrations.md
  84. 211
      docs/guide/db-query-builder.md
  85. 13
      docs/guide/input-validation.md
  86. 2
      docs/guide/output-client-scripts.md
  87. 70
      docs/guide/output-data-providers.md
  88. 49
      docs/guide/output-data-widgets.md
  89. 7
      docs/guide/output-formatting.md
  90. 8
      docs/guide/rest-quick-start.md
  91. 10
      docs/guide/rest-resources.md
  92. 13
      docs/guide/runtime-logging.md
  93. 2
      docs/guide/runtime-requests.md
  94. 4
      docs/guide/security-authorization.md
  95. 2
      docs/guide/start-forms.md
  96. 31
      docs/guide/start-installation.md
  97. 22
      docs/guide/start-prerequisites.md
  98. 24
      docs/guide/structure-assets.md
  99. 2
      docs/guide/structure-filters.md
  100. 8
      docs/guide/structure-modules.md
  101. Some files were not shown because too many files have changed in this diff Show More

1
.gitattributes vendored

@ -13,7 +13,6 @@
*.json text
*.bat text
*.sql text
*.xml text
*.yml text
# Ensure those won't be messed up with

30
.gitlab-ci.yml

@ -1,22 +1,18 @@
before_script:
# set stack isolation
- export ISOLATION=buildpipeline${CI_PIPELINE_ID}${CI_BUILD_NAME}
- export COMPOSE_PROJECT_NAME=${ISOLATION}
- export TUPLE_C=$(expr ${CI_BUILD_ID} % 99)
- echo ${TUPLE_C}
# run docker-compose commands from tests environment
- cd tests
- cp .env-dist .env
- docker-compose config
image: docker:latest
services:
- docker:dind
after_script:
- export ISOLATION=buildpipeline${CI_PIPELINE_ID}${CI_BUILD_NAME}
- export COMPOSE_PROJECT_NAME=${ISOLATION}
# run docker-compose commands from tests environment
variables:
DOCKER_YII2_PHP_IMAGE: yiisoftware/yii2-php:7.1-apache
DOCKER_MYSQL_IMAGE: percona:5.7
DOCKER_POSTGRES_IMAGE: postgres:9.3
before_script:
- apk add --no-cache python py2-pip git
- pip install --no-cache-dir docker-compose==1.16.0
- docker info
- cd tests
- cp .env-dist .env
- docker-compose down -v --remove-orphans
- docker ps -f name=${ISOLATION}
stages:
- travis

36
.travis.yml

@ -46,18 +46,23 @@ cache:
- $HOME/.composer/cache
- $HOME/.npm
# try running against postgres 9.3
# try running against postgres 9.6
addons:
postgresql: "9.3"
postgresql: "9.6"
apt:
sources:
- mysql-5.7-trusty
packages:
- mysql-server
code_climate:
repo_token: 2935307212620b0e2228ab67eadd92c9f5501ddb60549d0d86007a354d56915b
matrix:
fast_finish: true
include:
# run tests coverage on PHP 7.1
- php: 7.2
# run tests coverage on PHP 7.1
- php: 7.1
env: TASK_TESTS_COVERAGE=1
@ -76,10 +81,10 @@ matrix:
code_climate:
repo_token: 2935307212620b0e2228ab67eadd92c9f5501ddb60549d0d86007a354d56915b
apt:
sources:
- mysql-5.7-trusty
packages:
- mysql-server-5.6
- mysql-client-core-5.6
- mysql-client-5.6
- mysql-server
services:
- mysql
@ -89,12 +94,12 @@ matrix:
addons:
code_climate:
repo_token: 2935307212620b0e2228ab67eadd92c9f5501ddb60549d0d86007a354d56915b
postgresql: "9.3"
postgresql: "9.6"
apt:
sources:
- mysql-5.7-trusty
packages:
- mysql-server-5.6
- mysql-client-core-5.6
- mysql-client-5.6
- mysql-server
services:
- mysql
- postgresql
@ -110,7 +115,6 @@ matrix:
allow_failures:
- php: nightly
- php: 7.2
install:
- |
@ -167,6 +171,7 @@ before_script:
- |
if [ $TASK_TESTS_PHP == 1 ]; then
travis_retry mysql -e 'CREATE DATABASE `yiitest`;';
mysql -e "SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';";
mysql -e "CREATE USER 'travis'@'localhost' IDENTIFIED WITH mysql_native_password;";
mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'travis'@'localhost' WITH GRANT OPTION;";
psql -U postgres -c 'CREATE DATABASE yiitest;';
@ -178,6 +183,15 @@ before_script:
PHPUNIT_FLAGS="--coverage-clover=coverage.clover"
fi
# 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 ]; 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;
fi
script:
# PHP tests

3
Dockerfile

@ -1,4 +1,5 @@
FROM dmstr/php-yii2:7.0-fpm-1.9-beta2-alpine-nginx
ARG DOCKER_YII2_PHP_IMAGE
FROM ${DOCKER_YII2_PHP_IMAGE}
# Project source-code
WORKDIR /project

5
README.md

@ -11,9 +11,7 @@ The framework is easy to adjust to meet your needs, because Yii has been designe
[![Latest Stable Version](https://poser.pugx.org/yiisoft/yii2/v/stable.png)](https://packagist.org/packages/yiisoft/yii2)
[![Total Downloads](https://poser.pugx.org/yiisoft/yii2/downloads.png)](https://packagist.org/packages/yiisoft/yii2)
[![Reference Status](https://www.versioneye.com/php/yiisoft:yii2/reference_badge.svg)](https://www.versioneye.com/php/yiisoft:yii2/references)
[![Build Status](https://img.shields.io/travis/yiisoft/yii2.svg)](http://travis-ci.org/yiisoft/yii2)
[![Dependency Status](https://www.versioneye.com/php/yiisoft:yii2/dev-master/badge.png)](https://www.versioneye.com/php/yiisoft:yii2/dev-master)
[![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)
@ -41,9 +39,10 @@ Community
---------
- Participate in [discussions at forums](http://www.yiiframework.com/forum/).
- [Chat in IRC](http://www.yiiframework.com/chat/).
- [Community Slack](https://join.slack.com/t/yii/shared_invite/MjIxMjMxMTk5MTU1LTE1MDE3MDAwMzMtM2VkMTMyMjY1Ng) and [Chat in IRC](http://www.yiiframework.com/chat/).
- Follow us on [Facebook](https://www.facebook.com/groups/yiitalk/), [Twitter](https://twitter.com/yiiframework)
and [GitHub](https://github.com/yiisoft/yii2).
- Check [other communities](https://github.com/yiisoft/yii2/wiki/communities).
Contributing
------------

2
build/controllers/ClassmapController.php

@ -60,7 +60,7 @@ class ClassmapController extends Controller
if (strpos($file, $root) !== 0) {
throw new Exception("Something wrong: $file\n");
}
$path = str_replace('\\', '/', substr($file, strlen($root)));
$path = str_replace('\\', '/', substr($file, \strlen($root)));
$map[$path] = " 'yii" . substr(str_replace('/', '\\', $path), 0, -4) . "' => YII2_PATH . '$path',";
}
ksort($map);

44
build/controllers/DevController.php

@ -24,19 +24,25 @@ use yii\helpers\FileHelper;
*/
class DevController extends Controller
{
/**
* {@inheritdoc}
*/
public $defaultAction = 'all';
/**
* @var bool whether to use HTTP when cloning github repositories
*/
public $useHttp = false;
/**
* @var array
*/
public $apps = [
'basic' => 'git@github.com:yiisoft/yii2-app-basic.git',
'advanced' => 'git@github.com:yiisoft/yii2-app-advanced.git',
'benchmark' => 'git@github.com:yiisoft/yii2-app-benchmark.git',
];
/**
* @var array
*/
public $extensions = [
'apidoc' => 'git@github.com:yiisoft/yii2-apidoc.git',
'authclient' => 'git@github.com:yiisoft/yii2-authclient.git',
@ -98,17 +104,17 @@ class DevController extends Controller
*/
public function actionRun($command)
{
$command = implode(' ', func_get_args());
$command = implode(' ', \func_get_args());
// root of the dev repo
$base = dirname(dirname(__DIR__));
$base = \dirname(\dirname(__DIR__));
$dirs = $this->listSubDirs("$base/extensions");
$dirs = array_merge($dirs, $this->listSubDirs("$base/apps"));
asort($dirs);
$oldcwd = getcwd();
foreach ($dirs as $dir) {
$displayDir = substr($dir, strlen($base));
$displayDir = substr($dir, \strlen($base));
$this->stdout("Running '$command' in $displayDir...\n", Console::BOLD);
chdir($dir);
passthru($command);
@ -137,7 +143,7 @@ class DevController extends Controller
public function actionApp($app, $repo = null)
{
// root of the dev repo
$base = dirname(dirname(__DIR__));
$base = \dirname(\dirname(__DIR__));
$appDir = "$base/apps/$app";
if (!file_exists($appDir)) {
@ -188,7 +194,7 @@ class DevController extends Controller
public function actionExt($extension, $repo = null)
{
// root of the dev repo
$base = dirname(dirname(__DIR__));
$base = \dirname(\dirname(__DIR__));
$extensionDir = "$base/extensions/$extension";
if (!file_exists($extensionDir)) {
@ -229,12 +235,12 @@ class DevController extends Controller
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function options($actionID)
{
$options = parent::options($actionID);
if (in_array($actionID, ['ext', 'app', 'all'], true)) {
if (\in_array($actionID, ['ext', 'app', 'all'], true)) {
$options[] = 'useHttp';
}
@ -250,13 +256,13 @@ class DevController extends Controller
{
if (is_link($link = "$dir/vendor/yiisoft/yii2")) {
$this->stdout("Removing symlink $link.\n");
$this->unlink($link);
FileHelper::unlink($link);
}
$extensions = $this->findDirs("$dir/vendor/yiisoft");
foreach ($extensions as $ext) {
if (is_link($link = "$dir/vendor/yiisoft/yii2-$ext")) {
$this->stdout("Removing symlink $link.\n");
$this->unlink($link);
FileHelper::unlink($link);
}
}
}
@ -294,20 +300,6 @@ class DevController extends Controller
}
/**
* Properly removes symlinked directory under Windows, MacOS and Linux.
*
* @param string $file path to symlink
*/
protected function unlink($file)
{
if (is_dir($file) && DIRECTORY_SEPARATOR === '\\') {
rmdir($file);
} else {
unlink($file);
}
}
/**
* Get a list of subdirectories for directory specified.
* @param string $dir directory to read
*

92
build/controllers/MimeTypeController.php

@ -27,34 +27,60 @@ use yii\helpers\VarDumper;
class MimeTypeController extends Controller
{
/**
* @param string $outFile the file to update. Defaults to @yii/helpers/mimeTypes.php
* @var array MIME type aliases
*/
public function actionIndex($outFile = null)
private $aliases = [
'text/xml' => 'application/xml',
];
/**
* @param string $outFile the mime file to update. Defaults to @yii/helpers/mimeTypes.php
* @param string $aliasesOutFile the aliases file to update. Defaults to @yii/helpers/mimeAliases.php
*/
public function actionIndex($outFile = null, $aliasesOutFile = null)
{
if ($outFile === null) {
$outFile = Yii::getAlias('@yii/helpers/mimeTypes.php');
}
if ($aliasesOutFile === null) {
$aliasesOutFile = Yii::getAlias('@yii/helpers/mimeAliases.php');
}
$this->stdout('downloading mime-type file from apache httpd repository...');
if ($content = file_get_contents('http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=co')) {
if ($apacheMimeTypesFileContent = file_get_contents('http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=co')) {
$this->stdout("done.\n", Console::FG_GREEN);
$this->stdout("generating file $outFile...");
$mimeMap = [];
foreach (explode("\n", $content) as $line) {
$line = trim($line);
if (empty($line) || $line[0] == '#') { // skip comments and empty lines
continue;
}
$parts = preg_split('/\s+/', $line);
$mime = array_shift($parts);
foreach ($parts as $ext) {
if (!empty($ext)) {
$mimeMap[$ext] = $mime;
}
$this->generateMimeTypesFile($outFile, $apacheMimeTypesFileContent);
$this->generateMimeAliasesFile($aliasesOutFile);
} else {
$this->stderr("Failed to download mime.types file from apache SVN.\n");
}
}
/**
* @param string $outFile
* @param string $content
*/
private function generateMimeTypesFile($outFile, $content)
{
$this->stdout("generating file $outFile...");
$mimeMap = [];
foreach (explode("\n", $content) as $line) {
$line = trim($line);
if (empty($line) || $line[0] === '#') { // skip comments and empty lines
continue;
}
$parts = preg_split('/\s+/', $line);
$mime = array_shift($parts);
foreach ($parts as $ext) {
if (!empty($ext)) {
$mimeMap[$ext] = $mime;
}
}
ksort($mimeMap);
$array = VarDumper::export($mimeMap);
$content = <<<EOD
}
ksort($mimeMap);
$array = VarDumper::export($mimeMap);
$content = <<<EOD
<?php
/**
* MIME types.
@ -68,10 +94,28 @@ class MimeTypeController extends Controller
return $array;
EOD;
file_put_contents($outFile, $content);
$this->stdout("done.\n", Console::FG_GREEN);
} else {
$this->stderr("Failed to download mime.types file from apache SVN.\n");
}
file_put_contents($outFile, $content);
$this->stdout("done.\n", Console::FG_GREEN);
}
/**
* @param string $outFile
*/
private function generateMimeAliasesFile($outFile)
{
$this->stdout("generating file $outFile...");
$array = VarDumper::export($this->aliases);
$content = <<<EOD
<?php
/**
* MIME aliases.
*
* This file contains aliases for MIME types.
*/
return $array;
EOD;
file_put_contents($outFile, $content);
$this->stdout("done.\n", Console::FG_GREEN);
}
}

101
build/controllers/PhpDocController.php

@ -11,6 +11,7 @@ use Yii;
use yii\console\Controller;
use yii\helpers\Console;
use yii\helpers\FileHelper;
use yii\helpers\Json;
/**
* PhpDocController is there to help maintaining PHPDoc annotation in class files.
@ -21,6 +22,9 @@ use yii\helpers\FileHelper;
*/
class PhpDocController extends Controller
{
/**
* {@inheritdoc}
*/
public $defaultAction = 'property';
/**
* @var bool whether to update class docs directly. Setting this to false will just output docs
@ -82,7 +86,7 @@ class PhpDocController extends Controller
$nFilesUpdated = 0;
foreach ($files as $file) {
$contents = file_get_contents($file);
$sha = sha1($contents);
$hash = $this->hash($contents);
// fix line endings
$lines = preg_split('/(\r\n|\n|\r)/', $contents);
@ -94,10 +98,10 @@ class PhpDocController extends Controller
$lines = array_values($this->fixLineSpacing($lines));
$newContent = implode("\n", $lines);
if ($sha !== sha1($newContent)) {
if ($hash !== $this->hash($newContent)) {
file_put_contents($file, $newContent);
$nFilesUpdated++;
}
file_put_contents($file, $newContent);
$nFilesTotal++;
}
@ -106,13 +110,18 @@ class PhpDocController extends Controller
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function options($actionID)
{
return array_merge(parent::options($actionID), ['updateFiles', 'skipFrameworkRequirements']);
}
/**
* @param string $root
* @param bool $needsInclude
* @return array list of files.
*/
protected function findFiles($root, $needsInclude = true)
{
$except = [];
@ -132,7 +141,7 @@ class PhpDocController extends Controller
'/generators/extension/default/AutoloadExample.php',
],
'swiftmailer' => [
'/Logger.php',
'src/Logger.php',
],
'twig' => [
'/Extension.php',
@ -147,13 +156,9 @@ class PhpDocController extends Controller
}
if ($root === null) {
$root = dirname(YII2_PATH);
$root = \dirname(YII2_PATH);
$extensionPath = "$root/extensions";
foreach (scandir($extensionPath) as $extension) {
if (ctype_alpha($extension) && is_dir($extensionPath . '/' . $extension)) {
Yii::setAlias("@yii/$extension", "$extensionPath/$extension");
}
}
$this->setUpExtensionAliases($extensionPath);
$except = [
'/apps/',
@ -172,11 +177,11 @@ class PhpDocController extends Controller
}
}
} elseif (preg_match('~extensions/([\w-]+)[\\\\/]?$~', $root, $matches)) {
$extensionPath = dirname(rtrim($root, '\\/'));
$extensionPath = \dirname(rtrim($root, '\\/'));
$this->setUpExtensionAliases($extensionPath);
list(, $extension) = $matches;
Yii::setAlias("@yii/$extension", "$root");
Yii::setAlias("@yii/$extension", (string)$root);
if (is_file($autoloadFile = Yii::getAlias("@yii/$extension/vendor/autoload.php"))) {
include $autoloadFile;
}
@ -195,11 +200,11 @@ class PhpDocController extends Controller
// return [];
// }
} elseif (preg_match('~apps/([\w-]+)[\\\\/]?$~', $root, $matches)) {
$extensionPath = dirname(dirname(rtrim($root, '\\/'))) . '/extensions';
$extensionPath = \dirname(\dirname(rtrim($root, '\\/'))) . '/extensions';
$this->setUpExtensionAliases($extensionPath);
list(, $appName) = $matches;
Yii::setAlias("@app-$appName", "$root");
Yii::setAlias("@app-$appName", (string)$root);
if (is_file($autoloadFile = Yii::getAlias("@app-$appName/vendor/autoload.php"))) {
include $autoloadFile;
}
@ -230,14 +235,30 @@ class PhpDocController extends Controller
'vendor/',
]),
];
return FileHelper::findFiles($root, $options);
}
/**
* @param string $extensionPath root path containing extension repositories.
*/
private function setUpExtensionAliases($extensionPath)
{
foreach (scandir($extensionPath) as $extension) {
if (ctype_alpha($extension) && is_dir($extensionPath . '/' . $extension)) {
Yii::setAlias("@yii/$extension", "$extensionPath/$extension");
$composerConfigFile = $extensionPath . '/' . $extension . '/composer.json';
if (file_exists($composerConfigFile)) {
$composerConfig = Json::decode(file_get_contents($composerConfigFile));
if (isset($composerConfig['autoload']['psr-4'])) {
foreach ($composerConfig['autoload']['psr-4'] as $namespace => $subPath) {
$alias = '@' . str_replace('\\', '/', $namespace);
$path = rtrim("$extensionPath/$extension/$subPath", '/');
Yii::setAlias($alias, $path);
}
}
}
}
}
}
@ -285,6 +306,7 @@ class PhpDocController extends Controller
/**
* Markdown aware fix of whitespace issues in doc comments.
* @param array $lines
*/
protected function fixDocBlockIndentation(&$lines)
{
@ -326,7 +348,7 @@ class PhpDocController extends Controller
$codeBlock = !$codeBlock;
$listIndent = '';
} elseif (preg_match('/^(\s*)([0-9]+\.|-|\*|\+) /', $docLine, $matches)) {
$listIndent = str_repeat(' ', strlen($matches[0]));
$listIndent = str_repeat(' ', \strlen($matches[0]));
$tag = false;
$lines[$i] = $indent . ' * ' . $docLine;
continue;
@ -340,6 +362,10 @@ class PhpDocController extends Controller
}
}
/**
* @param string $line
* @return string
*/
protected function fixParamTypes($line)
{
return preg_replace_callback('~@(param|return) ([\w\\|]+)~i', function ($matches) {
@ -532,10 +558,10 @@ class PhpDocController extends Controller
if (trim($oldDoc) != trim($newDoc)) {
$fileContent = explode("\n", file_get_contents($file));
$start = $ref->getStartLine() - 2;
$docStart = $start - count(explode("\n", $oldDoc)) + 1;
$docStart = $start - \count(explode("\n", $oldDoc)) + 1;
$newFileContent = [];
$n = count($fileContent);
$n = \count($fileContent);
for ($i = 0; $i < $n; $i++) {
if ($i > $start || $i < $docStart) {
$newFileContent[] = $fileContent[$i];
@ -562,7 +588,7 @@ class PhpDocController extends Controller
protected function cleanDocComment($doc)
{
$lines = explode("\n", $doc);
$n = count($lines);
$n = \count($lines);
for ($i = 0; $i < $n; $i++) {
$lines[$i] = rtrim($lines[$i]);
if (trim($lines[$i]) == '*' && trim($lines[$i + 1]) == '*') {
@ -603,7 +629,7 @@ class PhpDocController extends Controller
// if no properties or other tags where present add properties at the end
if ($propertyPosition === false) {
$propertyPosition = count($lines) - 2;
$propertyPosition = \count($lines) - 2;
}
$finalDoc = '';
@ -626,22 +652,22 @@ class PhpDocController extends Controller
$namespace = $namespace['name'];
$classes = $this->match('#\n(?:abstract )?class (?<name>\w+)( extends .+)?( implements .+)?\n\{(?<content>.*)\n\}(\n|$)#', $file);
if (count($classes) > 1) {
if (\count($classes) > 1) {
$this->stderr("[ERR] There should be only one class in a file: $fileName\n", Console::FG_RED);
return false;
}
if (count($classes) < 1) {
if (\count($classes) < 1) {
$interfaces = $this->match('#\ninterface (?<name>\w+)( extends .+)?\n\{(?<content>.*)\n\}(\n|$)#', $file);
if (count($interfaces) == 1) {
if (\count($interfaces) == 1) {
return false;
} elseif (count($interfaces) > 1) {
} elseif (\count($interfaces) > 1) {
$this->stderr("[ERR] There should be only one interface in a file: $fileName\n", Console::FG_RED);
} else {
$traits = $this->match('#\ntrait (?<name>\w+)\n\{(?<content>.*)\n\}(\n|$)#', $file);
if (count($traits) == 1) {
if (\count($traits) == 1) {
return false;
} elseif (count($traits) > 1) {
} elseif (\count($traits) > 1) {
$this->stderr("[ERR] There should be only one class/trait/interface in a file: $fileName\n", Console::FG_RED);
} else {
$this->stderr("[ERR] No class in file: $fileName\n", Console::FG_RED);
@ -682,13 +708,13 @@ class PhpDocController extends Controller
ksort($props);
if (count($props) > 0) {
if (\count($props) > 0) {
$phpdoc .= " *\n";
foreach ($props as $propName => &$prop) {
$docline = ' * @';
$docline .= 'property'; // Do not use property-read and property-write as few IDEs support complex syntax.
$note = '';
if (isset($prop['get']) && isset($prop['set'])) {
if (isset($prop['get'], $prop['set'])) {
if ($prop['get']['type'] != $prop['set']['type']) {
$note = ' Note that the type of this property differs in getter and setter.'
. ' See [[get' . ucfirst($propName) . '()]] and [[set' . ucfirst($propName) . '()]] for details.';
@ -706,7 +732,7 @@ class PhpDocController extends Controller
}
if (!$parentSetter) {
$note = ' This property is read-only.';
// $docline .= '-read';
//$docline .= '-read';
}
} elseif (isset($prop['set'])) {
// check if parent class has getter defined
@ -721,7 +747,7 @@ class PhpDocController extends Controller
}
if (!$parentGetter) {
$note = ' This property is write-only.';
// $docline .= '-write';
//$docline .= '-write';
}
} else {
continue;
@ -773,11 +799,24 @@ class PhpDocController extends Controller
return '';
}
return strtoupper(substr($str, 0, 1)) . substr($str, 1) . ($str[strlen($str) - 1] != '.' ? '.' : '');
return strtoupper(substr($str, 0, 1)) . substr($str, 1) . ($str[\strlen($str) - 1] != '.' ? '.' : '');
}
protected function getPropParam($prop, $param)
{
return isset($prop['property']) ? $prop['property'][$param] : (isset($prop['get']) ? $prop['get'][$param] : $prop['set'][$param]);
}
/**
* Generate a hash value (message digest)
* @param string $string message to be hashed.
* @return string calculated message digest.
*/
private function hash($string)
{
if (!function_exists('hash')) {
return sha1($string);
}
return hash('sha256', $string);
}
}

38
build/controllers/ReleaseController.php

@ -82,7 +82,7 @@ class ReleaseController extends Controller
throw new Exception('Sorry, but releases should be run interactively to ensure you actually verify what you are doing ;)');
}
if ($this->basePath === null) {
$this->basePath = dirname(dirname(__DIR__));
$this->basePath = \dirname(\dirname(__DIR__));
}
$this->basePath = rtrim($this->basePath, '\\/');
return parent::beforeAction($action);
@ -109,7 +109,7 @@ class ReleaseController extends Controller
foreach ($items as $item) {
$this->stdout("fetching tags for $item...");
if ($item === 'framework') {
$this->gitFetchTags("{$this->basePath}");
$this->gitFetchTags((string)$this->basePath);
} elseif (strncmp('app-', $item, 4) === 0) {
$this->gitFetchTags("{$this->basePath}/apps/" . substr($item, 4));
} else {
@ -183,7 +183,7 @@ class ReleaseController extends Controller
*/
public function actionRelease(array $what)
{
if (count($what) > 1) {
if (\count($what) > 1) {
$this->stdout("Currently only one simultaneous release is supported.\n");
return 1;
}
@ -315,7 +315,7 @@ class ReleaseController extends Controller
*/
public function actionSortChangelog(array $what)
{
if (count($what) > 1) {
if (\count($what) > 1) {
$this->stdout("Currently only one simultaneous release is supported.\n");
return 1;
}
@ -376,7 +376,7 @@ class ReleaseController extends Controller
{
foreach ($what as $w) {
if (strncmp('app-', $w, 4) === 0) {
if (!empty($limit) && !in_array('app', $limit)) {
if (!empty($limit) && !\in_array('app', $limit)) {
throw new Exception('Only the following types are allowed: ' . implode(', ', $limit) . "\n");
}
if (!is_dir($appPath = "{$this->basePath}/apps/" . substr($w, 4))) {
@ -386,7 +386,7 @@ class ReleaseController extends Controller
$this->ensureGitClean($appPath);
}
} elseif ($w === 'framework') {
if (!empty($limit) && !in_array('framework', $limit)) {
if (!empty($limit) && !\in_array('framework', $limit)) {
throw new Exception('Only the following types are allowed: ' . implode(', ', $limit) . "\n");
}
if (!is_dir($fwPath = "{$this->basePath}/framework")) {
@ -396,7 +396,7 @@ class ReleaseController extends Controller
$this->ensureGitClean($fwPath);
}
} else {
if (!empty($limit) && !in_array('ext', $limit)) {
if (!empty($limit) && !\in_array('ext', $limit)) {
throw new Exception('Only the following types are allowed: ' . implode(', ', $limit) . "\n");
}
if (!is_dir($extPath = "{$this->basePath}/extensions/$w")) {
@ -414,7 +414,7 @@ class ReleaseController extends Controller
{
$this->stdout("\n");
$this->stdout($h = "Preparing framework release version $version", Console::BOLD);
$this->stdout("\n" . str_repeat('-', strlen($h)) . "\n\n", Console::BOLD);
$this->stdout("\n" . str_repeat('-', \strlen($h)) . "\n\n", Console::BOLD);
if (!$this->confirm('Make sure you are on the right branch for this release and that it tracks the correct remote branch! Continue?')) {
exit(1);
@ -433,8 +433,8 @@ class ReleaseController extends Controller
$this->dryRun || Yii::$app->runAction('classmap', [$frameworkPath]);
$this->stdout("done.\n", Console::FG_GREEN, Console::BOLD);
$this->stdout('updating mimetype magic file...', Console::BOLD);
$this->dryRun || Yii::$app->runAction('mime-type', ["$frameworkPath/helpers/mimeTypes.php"]);
$this->stdout('updating mimetype magic file and mime aliases...', Console::BOLD);
$this->dryRun || Yii::$app->runAction('mime-type', ["$frameworkPath/helpers/mimeTypes.php"], ["$frameworkPath/helpers/mimeAliases.php"]);
$this->stdout("done.\n", Console::FG_GREEN, Console::BOLD);
$this->stdout("fixing various PHPDoc style issues...\n", Console::BOLD);
@ -552,7 +552,7 @@ class ReleaseController extends Controller
{
$this->stdout("\n");
$this->stdout($h = "Preparing release for application $name version $version", Console::BOLD);
$this->stdout("\n" . str_repeat('-', strlen($h)) . "\n\n", Console::BOLD);
$this->stdout("\n" . str_repeat('-', \strlen($h)) . "\n\n", Console::BOLD);
if (!$this->confirm('Make sure you are on the right branch for this release and that it tracks the correct remote branch! Continue?')) {
exit(1);
@ -670,7 +670,7 @@ class ReleaseController extends Controller
{
$this->stdout("\n");
$this->stdout($h = "Preparing release for extension $name version $version", Console::BOLD);
$this->stdout("\n" . str_repeat('-', strlen($h)) . "\n\n", Console::BOLD);
$this->stdout("\n" . str_repeat('-', \strlen($h)) . "\n\n", Console::BOLD);
if (!$this->confirm('Make sure you are on the right branch for this release and that it tracks the correct remote branch! Continue?')) {
exit(1);
@ -817,7 +817,7 @@ class ReleaseController extends Controller
$headline = $version . ' ' . date('F d, Y');
$this->sed(
'/' . $v . ' under development\n(-+?)\n/',
$headline . "\n" . str_repeat('-', strlen($headline)) . "\n",
$headline . "\n" . str_repeat('-', \strlen($headline)) . "\n",
$this->getChangelogs($what)
);
}
@ -825,7 +825,7 @@ class ReleaseController extends Controller
protected function openChangelogs($what, $version)
{
$headline = "\n$version under development\n";
$headline .= str_repeat('-', strlen($headline) - 2) . "\n\n- no changes in this release.\n";
$headline .= str_repeat('-', \strlen($headline) - 2) . "\n\n- no changes in this release.\n";
foreach ($this->getChangelogs($what) as $file) {
$lines = explode("\n", file_get_contents($file));
$hl = [
@ -874,7 +874,7 @@ class ReleaseController extends Controller
$state = 'end';
}
// add continued lines to the last item to keep them together
if (!empty(${$state}) && trim($line !== '') && strpos($line, '- ') !== 0) {
if (!empty(${$state}) && trim($line) !== '' && strncmp($line, '- ', 2) !== 0) {
end(${$state});
${$state}[key(${$state})] .= "\n" . $line;
} else {
@ -919,7 +919,7 @@ class ReleaseController extends Controller
protected function getChangelogs($what)
{
$changelogs = [];
if (in_array('framework', $what)) {
if (\in_array('framework', $what)) {
$changelogs[] = $this->getFrameworkChangelog();
}
@ -947,13 +947,13 @@ class ReleaseController extends Controller
protected function composerSetStability($what, $version)
{
$apps = [];
if (in_array('app-advanced', $what)) {
if (\in_array('app-advanced', $what)) {
$apps[] = $this->basePath . '/apps/advanced/composer.json';
}
if (in_array('app-basic', $what)) {
if (\in_array('app-basic', $what)) {
$apps[] = $this->basePath . '/apps/basic/composer.json';
}
if (in_array('app-benchmark', $what)) {
if (\in_array('app-benchmark', $what)) {
$apps[] = $this->basePath . '/apps/benchmark/composer.json';
}
if (empty($apps)) {

18
build/controllers/Utf8Controller.php

@ -29,7 +29,7 @@ class Utf8Controller extends Controller
public function actionCheckGuide($directory = null)
{
if ($directory === null) {
$directory = dirname(dirname(__DIR__)) . '/docs';
$directory = \dirname(\dirname(__DIR__)) . '/docs';
}
if (is_file($directory)) {
$files = [$directory];
@ -90,7 +90,7 @@ class Utf8Controller extends Controller
}
$hexcode = dechex($this->unicodeOrd($char));
$hexcode = str_repeat('0', max(4 - strlen($hexcode), 0)) . $hexcode;
$hexcode = str_repeat('0', max(4 - \strlen($hexcode), 0)) . $hexcode;
$this->stdout(" at $line:$pos FOUND $what: 0x$hexcode '$char' http://unicode-table.com/en/$hexcode/\n");
}
@ -105,20 +105,20 @@ class Utf8Controller extends Controller
*/
private function unicodeOrd($c)
{
$h = ord($c[0]);
$h = \ord($c[0]);
if ($h <= 0x7F) {
return $h;
} elseif ($h < 0xC2) {
return false;
} elseif ($h <= 0xDF) {
return ($h & 0x1F) << 6 | (ord($c[1]) & 0x3F);
return ($h & 0x1F) << 6 | (\ord($c[1]) & 0x3F);
} elseif ($h <= 0xEF) {
return ($h & 0x0F) << 12 | (ord($c[1]) & 0x3F) << 6
| (ord($c[2]) & 0x3F);
return ($h & 0x0F) << 12 | (\ord($c[1]) & 0x3F) << 6
| (\ord($c[2]) & 0x3F);
} elseif ($h <= 0xF4) {
return ($h & 0x0F) << 18 | (ord($c[1]) & 0x3F) << 12
| (ord($c[2]) & 0x3F) << 6
| (ord($c[3]) & 0x3F);
return ($h & 0x0F) << 18 | (\ord($c[1]) & 0x3F) << 12
| (\ord($c[2]) & 0x3F) << 6
| (\ord($c[3]) & 0x3F);
}
return false;

462
composer.lock generated

File diff suppressed because it is too large Load Diff

4
contrib/completion/bash/yii

@ -15,6 +15,7 @@ _yii()
local cur opts yii command
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
yii="${COMP_WORDS[0]}"
# exit if ./yii does not exist
@ -31,9 +32,10 @@ _yii()
[[ $cur == $command ]] && state="command"
[[ $cur != $command ]] && state="option"
[[ $cur = *=* ]] && state="value"
[[ $prev == "help" ]] && state="help"
case $state in
command)
command|help)
# complete command/route if not given
# fetch available commands from ./yii help/list command
opts=$($yii help/list 2> /dev/null)

4
contrib/completion/zsh/_yii

@ -3,6 +3,7 @@
_yii() {
local state command lastArgument commands options executive
lastArgument=${words[${#words[@]}]}
prevArgument=${words[${#words[@]}-1]}
executive=$words[1]
# lookup for command
@ -16,9 +17,10 @@ _yii() {
[[ $lastArgument == $command ]] && state="command"
[[ $lastArgument != $command ]] && state="option"
[[ $prevArgument == "help" ]] && state="help"
case $state in
command)
command|help)
commands=("${(@f)$(${executive} help/list 2>/dev/null)}")
_describe 'command' commands
;;

4
docs/guide-es/caching-data.md

@ -79,8 +79,8 @@ se muestra un listado con los componentes de caché disponibles:
* [[yii\caching\MemCache]]: utiliza las extensiones de PHP [memcache](http://php.net/manual/es/book.memcache.php) y [memcached](http://php.net/manual/es/book.memcached.php). Esta opción puede ser considerada como la más rápida cuando la caché es manejada en una aplicación distribuida (ej. con varios servidores, con balance de carga, etc..)
* [[yii\redis\Cache]]: implementa un componente de caché basado en [Redis](http://redis.io/) que almacenan pares clave-valor (requiere la versión 2.6.12 de redis).
* [[yii\caching\WinCache]]: utiliza la extensión de PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension) ([ver también](http://php.net/manual/es/book.wincache.php)).
* [[yii\caching\XCache]]: utiliza la extensión de PHP [XCache](http://xcache.lighttpd.net/).
* [[yii\caching\ZendDataCache]]: utiliza [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) como el medio fundamental de caché.
* [[yii\caching\XCache]] _(deprecated)_: utiliza la extensión de PHP [XCache](http://xcache.lighttpd.net/).
* [[yii\caching\ZendDataCache]] _(deprecated)_: utiliza [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) como el medio fundamental de caché.
> Tip: Puedes utilizar diferentes tipos de almacenamiento de caché en la misma aplicación. Una estrategia común es la de usar almacenamiento de caché en memoria para almacenar datos que son pequeños pero que son utilizados constantemente (ej. datos estadísticos), y utilizar el almacenamiento de caché en archivos o en base de datos para guardar datos que son grandes y utilizados con menor frecuencia (ej. contenido de página).

2
docs/guide-es/concept-di-container.md

@ -75,7 +75,7 @@ En este caso, el contenedor usará una llamada de retorno PHP registrada para co
clase. La llamada de retorno se responsabiliza de que dependencias debe inyectar al nuevo objeto creado. Por ejemplo,
```php
$container->set('Foo', function () {
$container->set('Foo', function ($container, $params, $config) {
return new Foo(new Bar);
});

2
docs/guide-es/concept-events.md

@ -218,7 +218,7 @@ use yii\base\Event;
use yii\db\ActiveRecord;
Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
Yii::trace(get_class($event->sender) . ' is inserted');
Yii::debug(get_class($event->sender) . ' is inserted');
});
```

10
docs/guide-es/runtime-logging.md

@ -20,7 +20,7 @@ En esta sección, se describirán principalmente los dos primeros pasos.
Registrar mensajes de anotación es tan simple como llamar a uno de los siguientes métodos de registro de anotaciones.
* [[Yii::trace()]]: registra un mensaje para trazar el funcionamiento de una sección de código. Se usa principalmente
* [[Yii::debug()]]: registra un mensaje para trazar el funcionamiento de una sección de código. Se usa principalmente
para tareas de desarrollo.
* [[Yii::info()]]: registra un mensaje que transmite información útil.
* [[Yii::warning()]]: registra un mensaje de advertencia que indica que ha sucedido algo inesperado.
@ -32,7 +32,7 @@ tiene que ser registrado, mientras que `$category` es la categoría del registro
ejemplo registra la huella del mensaje para la categoría `application`:
```php
Yii::trace('start calculating average revenue');
Yii::debug('start calculating average revenue');
```
> Info: Los mensajes de registro pueden ser tanto cadenas de texto como datos complejos, como arrays u objetos.
@ -47,7 +47,7 @@ efectiva de organizarlos es usar la constante predefinida (magic constant) de PH
categoría. Además este es el enfoque que se usa en el código del núcleo (core) del framework Yii. Por ejemplo,
```php
Yii::trace('start calculating average revenue', __METHOD__);
Yii::debug('start calculating average revenue', __METHOD__);
```
La constante `__METHOD__` equivale al nombre del método (con el prefijo del nombre completo del nombre de clase) donde
@ -131,7 +131,7 @@ La propiedad [[yii\log\Target::levels|levels]] es un array que consta de uno o v
* `error`: correspondiente a los mensajes registrados por [[Yii::error()]].
* `warning`: correspondiente a los mensajes registrados por [[Yii::warning()]].
* `info`: correspondiente a los mensajes registrados por [[Yii::info()]].
* `trace`: correspondiente a los mensajes registrados por [[Yii::trace()]].
* `trace`: correspondiente a los mensajes registrados por [[Yii::debug()]].
* `profile`: correspondiente a los mensajes registrados por [[Yii::beginProfile()]] y [[Yii::endProfile()]], que se
explicará más detalladamente en la subsección [Perfiles](#performance-profiling).
@ -290,7 +290,7 @@ número configurando la propiedad [[yii\log\Target::exportInterval|exportInterva
```
Debido al nivel de configuración de la liberación y exportación de mensajes, de forma predeterminada cuando se llama a
`Yii::trace()` o cualquier otro método de registro de mensajes, NO veremos el registro de mensaje inmediatamente en
`Yii::debug()` o cualquier otro método de registro de mensajes, NO veremos el registro de mensaje inmediatamente en
los destinos de registros. Esto podría ser un problema para algunas aplicaciones de consola de ejecución
prolongada (long-running). Para hacer que los mensajes de registro aparezcan inmediatamente en los destinos de
registro se deben establecer [[yii\log\Dispatcher::flushInterval|flushInterval]] y

4
docs/guide-es/start-installation.md

@ -189,7 +189,7 @@ DocumentRoot "path/to/basic/web"
Para utilizar [Nginx](http://wiki.nginx.org/), debes instalar PHP como un [FPM SAPI](http://php.net/install.fpm).
Utiliza la siguiente configuración de Nginx, reemplazando `path/to/basic/web` con la ruta real a
`basic/web` y `mysite.local` con el hostname real a servir.
`basic/web` y `mysite.test` con el hostname real a servir.
```
server {
@ -199,7 +199,7 @@ server {
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

2
docs/guide-es/structure-filters.md

@ -94,7 +94,7 @@ class ActionTimeFilter extends ActionFilter
public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::trace("Action '{$action->uniqueId}' spent $time second.");
Yii::debug("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}

4
docs/guide-fr/caching-data.md

@ -100,8 +100,8 @@ Yii prend en charge un large panel de supports de stockage pour cache. Ce qui su
(une version de redis égale ou supérieure à 2.6.12 est nécessaire).
* [[yii\caching\WinCache]]: utilise le [WinCache](http://iis.net/downloads/microsoft/wincache-extension) PHP
([voir aussi l'extension](http://php.net/manual/en/book.wincache.php)).
* [[yii\caching\XCache]]: utilise l'extension PHP [XCache](http://xcache.lighttpd.net/).
* [[yii\caching\ZendDataCache]]: utilise le
* [[yii\caching\XCache]] _(deprecated)_: utilise l'extension PHP [XCache](http://xcache.lighttpd.net/).
* [[yii\caching\ZendDataCache]] _(deprecated)_: utilise le
[cache de données Zend](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm)
en tant que médium de cache sous-jacent.

4
docs/guide-fr/concept-di-container.md

@ -99,7 +99,7 @@ $container->get('Foo', [], [
Dans ce cas, le conteneur utilise une fonction de rappel PRP enregistrée pour construire de nouvelles instances d'une classe. À chaque fois que [[yii\di\Container::get()]] est appelée, la fonction de rappel correspondante est invoquée. Cette fonction de rappel est chargée de la résolution des dépendances et de leur injection appropriée dans les objets nouvellement créés. Par exemple :
```php
$container->set('Foo', function () {
$container->set('Foo', function ($container, $params, $config) {
$foo = new Foo(new Bar);
// ... autres initialisations ...
return $foo;
@ -113,7 +113,7 @@ Pour cacher la logique complexe de construction des nouveaux objets, vous pouvez
```php
class FooBuilder
{
public static function build()
public static function build($container, $params, $config)
{
$foo = new Foo(new Bar);
// ... autres initialisations ...

4
docs/guide-fr/concept-events.md

@ -186,7 +186,7 @@ use yii\base\Event;
use yii\db\ActiveRecord;
Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
Yii::trace(get_class($event->sender) . ' is inserted');
Yii::debug(get_class($event->sender) . ' is inserted');
});
```
@ -263,7 +263,7 @@ Pour gérer l'évenement `EVENT_DANCE` déclenché par n'importe laquelle de ces
```php
Event::on('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) {
Yii::trace(get_class($event->sender) . ' just danced'); // Will log that Dog or Developer danced
Yii::debug(get_class($event->sender) . ' just danced'); // Will log that Dog or Developer danced
});
```

10
docs/guide-fr/runtime-logging.md

@ -16,7 +16,7 @@ Dans cette section, nous décrivons principalement les deux premières étapes.
Enregistrer des messages est aussi simple que d'appeler une des méthodes suivantes :
* [[Yii::trace()]]: enregistre un message pour garder une trace de comment un morceau de code fonctionne. Cela est utilisé principalement en développement.
* [[Yii::debug()]]: enregistre un message pour garder une trace de comment un morceau de code fonctionne. Cela est utilisé principalement en développement.
* [[Yii::info()]]: enregistre un message qui contient quelques informations utiles.
* [[Yii::warning()]]: enregistre un message d'avertissement qui indique que quelque chose d'inattendu s'est produit.
* [[Yii::error()]]: enregistre une erreur fatale qui doit être analysée dès que possible.
@ -24,7 +24,7 @@ Enregistrer des messages est aussi simple que d'appeler une des méthodes suivan
Ces méthodes enregistrent les messages à différents niveaux de sévérité et dans différentes catégories. Elles partagent la même signature `function ($message, $category = 'application')`, où `$message` représente le message à enregistrer, tandis que `$category` est la catégorie de ce message. Le code de l'exemple qui suit enregistre un message de trace dans la catégorie `application`:
```php
Yii::trace('start calculating average revenue');
Yii::debug('start calculating average revenue');
```
> Info: les messages enregistrés peuvent être des chaînes de caractères aussi bien que des données complexes telles que des tableaux ou des objets. Il est de la responsabilité des [cibles d'enregistrement](#log-targets) de traiter correctement ces messages. Par défaut, si un message enregistré n'est pas un chaîne de caractères, il est exporté comme une chaîne de caractères en appelant la méthode [[yii\helpers\VarDumper::export()]].
@ -32,7 +32,7 @@ Yii::trace('start calculating average revenue');
Pour mieux organiser et filtrer les messages enregistrés, il est recommandé que vous spécifiiez une catégorie appropriée pour chacun des messages. Vous pouvez choisir une schéma de nommage hiérarchisé pour les catégories, ce qui facilitera le filtrage des messages par les [cibles d'enregistrement](#log-targets) sur la base de ces catégories. Un schéma de nommage simple et efficace est d'utiliser la constante magique `__METHOD__` de PHP dans les noms de catégorie. Par exemple :
```php
Yii::trace('start calculating average revenue', __METHOD__);
Yii::debug('start calculating average revenue', __METHOD__);
```
La constante magique `__METHOD__` est évaluée comme le nom de la méthode (préfixée par le nom pleinement qualifié de la classe), là où la constante apparaît. Par exemple, elle est égale à `'app\controllers\RevenueController::calculate'` si la ligne suivante est utilisée dans cette méthode.
@ -100,7 +100,7 @@ La propriété [[yii\log\Target::levels|levels]] accepte un tableau constitué d
* `error`: correspondant aux messages enregistrés par [[Yii::error()]].
* `warning`: correspondant aux messages enregistrés par [[Yii::warning()]].
* `info`: correspondant aux messages enregistrés par [[Yii::info()]].
* `trace`: correspondant aux messages enregistrés par [[Yii::trace()]].
* `trace`: correspondant aux messages enregistrés par [[Yii::debug()]].
* `profile`: correspondant aux messages enregistrés par [[Yii::beginProfile()]] et [[Yii::endProfile()]], et qui sera expliqué en détails dans la sous-section [Profilage de la performance](#performance-profiling).
Si vous ne spécifiez pas la propriété [[yii\log\Target::levels|levels]], cela signifie que la cible traitera les messages de *n'importe quel* niveau de sévérité.
@ -222,7 +222,7 @@ Lorsque l'[[yii\log\Logger|objet *logger*]] purge les messages enregistrés vers
]
```
À cause des niveaux de purge et d'exportation, par défaut, lorsque vous appelez `Yii::trace()` ou toute autre méthode d'enregistrement, vous ne voyez PAS immédiatement le message enregistré dans la cible. Cela peut représenter un problème pour pour certaines applications de console qui durent longtemps. Pour faire en sorte que les messages apparaissent immédiatement dans les cibles d'enregistrement, vous devriez définir les propriétés [[yii\log\Dispatcher::flushInterval|flushInterval]] et [[yii\log\Target::exportInterval|exportInterval]] toutes deux à 1, comme montré ci-après :
À cause des niveaux de purge et d'exportation, par défaut, lorsque vous appelez `Yii::debug()` ou toute autre méthode d'enregistrement, vous ne voyez PAS immédiatement le message enregistré dans la cible. Cela peut représenter un problème pour pour certaines applications de console qui durent longtemps. Pour faire en sorte que les messages apparaissent immédiatement dans les cibles d'enregistrement, vous devriez définir les propriétés [[yii\log\Dispatcher::flushInterval|flushInterval]] et [[yii\log\Target::exportInterval|exportInterval]] toutes deux à 1, comme montré ci-après :
```php
return [

4
docs/guide-fr/start-installation.md

@ -120,7 +120,7 @@ DocumentRoot "path/to/basic/web"
### Configuration Nginx recommandée <span id="recommended-nginx-configuration"></span>
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.local` par le nom d'hôte de votre serveur.
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.
```
server {
@ -130,7 +130,7 @@ server {
listen 80; ## port pour ipv4
#listen [::]:80 default_server ipv6only=on; ## port pour ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

2
docs/guide-fr/structure-filters.md

@ -72,7 +72,7 @@ class ActionTimeFilter extends ActionFilter
public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::trace("Action '{$action->uniqueId}' spent $time second.");
Yii::debug("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}

2
docs/guide-fr/tutorial-i18n.md

@ -327,7 +327,7 @@ tandis que `one` correspond à `21` ou `101`:
```
Ces noms d'arguments spéciaux tels que `other`, `few`, `many` et autres varient en fonction de la langue. Pour savoir lesquels utiliser pour une locale particulière, reportez-vous aux "Plural Rules, Cardinal" à [http://intl.rmcreative.ru/](http://intl.rmcreative.ru/).
En alternative, vous pouvez vous reporter aux [rules reference at unicode.org](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html).
En alternative, vous pouvez vous reporter aux [rules reference at unicode.org](http://cldr.unicode.org/index/cldr-spec/plural-rules).
> Note: le message en russe ci-dessus est principalement utilisé comme message traduit, pas comme message source, sauf si vous définissez la [[yii\base\Application::$sourceLanguage|langue source]] de votre application comme étant `ru-RU` et traduisez à partir du russe.
>

4
docs/guide-id/start-installation.md

@ -189,7 +189,7 @@ DocumentRoot "path/to/basic/web"
Untuk menggunakan [Nginx](http://wiki.nginx.org/), Anda harus menginstal PHP sebagai [FPM SAPI](http://php.net/install.fpm).
Anda dapat menggunakan konfigurasi Nginx berikut, menggantikan `path/to/basic/web` dengan path yang sebenarnya untuk
`basic/web` dan `mysite.local` dengan hostname yang sebenarnya untuk server.
`basic/web` dan `mysite.test` dengan hostname yang sebenarnya untuk server.
```nginx
server {
@ -199,7 +199,7 @@ server {
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

4
docs/guide-it/start-installation.md

@ -161,7 +161,7 @@ DocumentRoot "path/to/basic/web"
### Configurazione consigliata di Nginx <span id="recommended-nginx-configuration"></span>
Devi aver installato PHP con il demone [FPM](http://php.net/install.fpm) per usare [Nginx](http://wiki.nginx.org/).
Usa questa configurazione per Nginx, sostituendo `path/to/basic/web` con il percorso reale di `basic/web` e `mysite.local` con
Usa questa configurazione per Nginx, sostituendo `path/to/basic/web` con il percorso reale di `basic/web` e `mysite.test` con
il nome reale del server web.
```
@ -172,7 +172,7 @@ server {
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

4
docs/guide-ja/caching-data.md

@ -111,8 +111,8 @@ Yii はさまざまなキャッシュストレージをサポートしていま
分散型のアプリケーションでキャッシュを扱うときには最速の一つとして考えることができます (例えば、複数台のサーバで、ロードバランサがある、などの場合) 。
* [[yii\redis\Cache]]: [Redis](http://redis.io/) の key-value ストアに基づいてキャッシュコンポーネントを実装しています。(Redis の バージョン 2.6.12 以降が必要です) 。
* [[yii\caching\WinCache]]: PHP の [WinCache](http://iis.net/downloads/microsoft/wincache-extension) ([関連リンク](http://php.net/manual/ja/book.wincache.php)) 拡張モジュールを使用します。
* [[yii\caching\XCache]]: PHP の [XCache](http://xcache.lighttpd.net/) 拡張モジュールを使用します。
* [[yii\caching\ZendDataCache]]: キャッシュメディアして [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) を使用します。
* [[yii\caching\XCache]] _(deprecated)_: PHP の [XCache](http://xcache.lighttpd.net/) 拡張モジュールを使用します。
* [[yii\caching\ZendDataCache]] _(deprecated)_: キャッシュメディアして [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) を使用します。
> Tip: 同じアプリケーション内で異なるキャッシュを使用することもできます。一般的なやり方として、小さくとも常に使用されるデータ (例えば、統計データ) を格納する場合はメモリベースのキャッシュストレージを使用し、大きくて使用頻度の低いデータ (例えば、ページコンテント) を格納する場合はファイルベース、またはデータベースのキャッシュストレージを使用します 。

10
docs/guide-ja/concept-di-container.md

@ -114,7 +114,7 @@ $container->get('Foo', [], [
たとえば
```php
$container->set('Foo', function () {
$container->set('Foo', function ($container, $params, $config) {
$foo = new Foo(new Bar);
// ... その他の初期化 ...
return $foo;
@ -129,7 +129,7 @@ $foo = $container->get('Foo');
```php
class FooBuilder
{
public static function build()
public static function build($container, $params, $config)
{
$foo = new Foo(new Bar);
// ... その他の初期化 ...
@ -380,14 +380,14 @@ API アプリケーションを開発していて、以下のクラスを持っ
```php
class FileStorage
{
public function __contruct($root) {
public function __construct($root) {
// あれやこれや
}
}
class DocumentsReader
{
public function __contruct(FileStorage $fs) {
public function __construct(FileStorage $fs) {
// なんやかんや
}
}
@ -413,7 +413,7 @@ $container->setDefinitions([
'class' => 'app\components\Response',
'format' => 'json'
],
'app\storage\DocumentsReader' => function () {
'app\storage\DocumentsReader' => function ($container, $params, $config) {
$fs = new app\storage\FileStorage('/var/tempfiles');
return new app\storage\DocumentsReader($fs);
}

4
docs/guide-ja/concept-events.md

@ -209,7 +209,7 @@ use yii\base\Event;
use yii\db\ActiveRecord;
Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
Yii::trace(get_class($event->sender) . ' が挿入されました');
Yii::debug(get_class($event->sender) . ' が挿入されました');
});
```
@ -292,7 +292,7 @@ class Developer extends Component implements DanceEventInterface
```php
Event::on('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) {
Yii::trace(get_class($event->sender) . ' が躍り上がって喜んだ。'); // 犬または開発者が躍り上がって喜んだことをログに記録。
Yii::debug(get_class($event->sender) . ' が躍り上がって喜んだ。'); // 犬または開発者が躍り上がって喜んだことをログに記録。
});
```

2
docs/guide-ja/output-client-scripts.md

@ -187,7 +187,7 @@ $message = \yii\helpers\Json::htmlEncode(
\Yii::t('app', 'Button clicked!')
);
$this->registerJs(<<<JS
$('#myButton').on('click', function() { alert( $message ); });",
$('#myButton').on('click', function() { alert( $message ); });
JS
);
```

10
docs/guide-ja/runtime-logging.md

@ -17,7 +17,7 @@ Yii のロギングフレームワークを使うためには、下記のステ
ログメッセージを記録することは、次のログ記録メソッドのどれかを呼び出すだけの簡単なことです。
* [[Yii::trace()]]: コードの断片がどのように走ったかをトレースするメッセージを記録します。主として開発のために使用します。
* [[Yii::debug()]]: コードの断片がどのように走ったかをトレースするメッセージを記録します。主として開発のために使用します。
* [[Yii::info()]]: 何らかの有用な情報を伝えるメッセージを記録します。
* [[Yii::warning()]]: 何か予期しないことが発生したことを示す警告メッセージを記録します。
* [[Yii::error()]]: 出来るだけ早急に調査すべき致命的なエラーを記録します。
@ -27,7 +27,7 @@ Yii のロギングフレームワークを使うためには、下記のステ
次のコードサンプルは、トレースメッセージをデフォルトのカテゴリである `application` の下に記録するものです。
```php
Yii::trace('平均収益の計算を開始');
Yii::debug('平均収益の計算を開始');
```
> Info: ログメッセージは文字列でも、配列やオブジェクトのような複雑なデータでも構いません。
@ -40,7 +40,7 @@ Yii::trace('平均収益の計算を開始');
これは、Yii フレームワークのコアコードでも使われている方法です。例えば、
```php
Yii::trace('平均収益の計算を開始', __METHOD__);
Yii::debug('平均収益の計算を開始', __METHOD__);
```
`__METHOD__` という定数は、それが出現する場所のメソッド名 (完全修飾のクラス名が前置されます) として評価されます。
@ -116,7 +116,7 @@ Yii は下記のログターゲットをあらかじめ内蔵しています。
* `error`: [[Yii::error()]] によって記録されたメッセージに対応。
* `warning`: [[Yii::warning()]] によって記録されたメッセージに対応。
* `info`: [[Yii::info()]] によって記録されたメッセージに対応。
* `trace`: [[Yii::trace()]] によって記録されたメッセージに対応。
* `trace`: [[Yii::debug()]] によって記録されたメッセージに対応。
* `profile`: [[Yii::beginProfile()]] と [[Yii::endProfile()]] によって記録されたメッセージに対応。
これについては、[プロファイリング](#performance-profiling) の項で詳細に説明します。
@ -255,7 +255,7 @@ return [
]
```
デフォルトの状態では、吐き出しとエクスポートの間隔の設定のために、`Yii::trace()` やその他のログ記録メソッドを呼んでも、ただちには、ログメッセージはログターゲットに出現しません。
デフォルトの状態では、吐き出しとエクスポートの間隔の設定のために、`Yii::debug()` やその他のログ記録メソッドを呼んでも、ただちには、ログメッセージはログターゲットに出現しません。
このことは、長時間にわたって走るコンソールアプリケーションでは、問題になる場合もあります。
各ログメッセージがただちにログターゲットに出現するようにするためには、下記のように、[[yii\log\Dispatcher::flushInterval|flushInterval]] と [[yii\log\Target::exportInterval|exportInterval]] の両方を 1 に設定しなければなりません。

4
docs/guide-ja/start-installation.md

@ -202,7 +202,7 @@ DocumentRoot "path/to/basic/web"
[Nginx](http://wiki.nginx.org/) を使うためには、PHP を [FPM SAPI](http://jp1.php.net/install.fpm) としてインストールしなければなりません。
下記の Nginx の設定を使うことができます。
`path/to/basic/web` の部分を `basic/web` の実際のパスに置き換え、`mysite.local` を実際のサーバのホスト名に置き換えてください。
`path/to/basic/web` の部分を `basic/web` の実際のパスに置き換え、`mysite.test` を実際のサーバのホスト名に置き換えてください。
```nginx
server {
@ -212,7 +212,7 @@ server {
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

2
docs/guide-ja/structure-filters.md

@ -83,7 +83,7 @@ class ActionTimeFilter extends ActionFilter
public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::trace("アクション '{$action->uniqueId}' は $time 秒を消費。");
Yii::debug("アクション '{$action->uniqueId}' は $time 秒を消費。");
return parent::afterAction($action, $result);
}
}

2
docs/guide-ja/tutorial-i18n.md

@ -459,7 +459,7 @@ echo \Yii::t('app', 'There {n,plural,=0{are no cats} =1{is one cat} other{are #
これら `other`、`few`、`many` などの特別な引数の名前は言語によって異なります。
特定のロケールに対してどんな引数を指定すべきかを学ぶためには、[http://intl.rmcreative.ru/](http://intl.rmcreative.ru/) の "Plural Rules, Cardinal" を参照してください。
あるいは、その代りに、[unicode.org の規則のリファレンス](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html) を参照することも出来ます。
あるいは、その代りに、[unicode.org の規則のリファレンス](http://cldr.unicode.org/index/cldr-spec/plural-rules) を参照することも出来ます。
> Note: 上記のロシア語のメッセージのサンプルは、主として翻訳メッセージとして使用されるものです。

2
docs/guide-pl/README.md

@ -92,6 +92,7 @@ Odbieranie danych od użytkowników
* [Wysyłanie plików](input-file-upload.md)
* [Odczytywanie tablicowych danych wejściowych](input-tabular-input.md)
* [Pobieranie danych dla wielu modeli](input-multiple-models.md)
* [Rozszerzanie ActiveForm po stronie klienta](input-form-javascript.md)
Wyświetlanie danych
@ -174,6 +175,7 @@ Tematy specjalne
* [Współdzielone środowisko hostingowe](tutorial-shared-hosting.md)
* [Silniki szablonów](tutorial-template-engines.md)
* [Praca z kodem zewnętrznym](tutorial-yii-integration.md)
* [Używanie Yii jako mikroframeworka](tutorial-yii-as-micro-framework.md)
Widżety

192
docs/guide-pl/input-form-javascript.md

@ -0,0 +1,192 @@
Rozszerzanie ActiveForm po stronie klienta
==========================================
Widżet [[yii\widgets\ActiveForm]] posiada szereg wbudowanych metod JavaScript, służących do walidacji po stronie klienta.
Ich implementacja jest bardzo elastyczna i pozwala na rozszerzanie ich na wiele sposobów.
## Zdarzenia ActiveForm
ActiveForm wyzwala serie dedykowanych zdarzeń. Używając poniższego kodu, można przechwycić te zdarzenia i je obsłużyć:
```javascript
$('#contact-form').on('beforeSubmit', function (e) {
if (!confirm("Wszystko jest w porządku. Wysłać formularz?")) {
return false;
}
return true;
});
```
Poniżej znajdziesz opis dostępnych zdarzeń.
### `beforeValidate`
`beforeValidate` jest wyzwalane przed walidacją całego formularza.
Sygnatura metody obsługującej to zdarzenie powinna wyglądać następująco:
```javascript
function (event, messages, deferreds)
```
gdzie
- `event`: obiekt Event.
- `messages`: asocjacyjna tablica, gdzie kluczami są ID atrybutów, a wartościami tablice opisów błędów dla tych atrybutów.
- `deferreds`: tablica obiektów kolejkujących. Możesz użyć `deferreds.add(callback)`, aby dodać nową walidację do kolejki.
Jeśli metoda obsługująca zwróci boolean `false`, zatrzyma dalszą walidację formularza. W takim wypadku zdarzenie
`afterValidate` nie będzie już wyzwalane.
### `afterValidate`
`afterValidate` jest wyzwalane po walidacji całego formularza.
Sygnatura metody obsługującej to zdarzenie powinna wyglądać następująco:
```javascript
function (event, messages, errorAttributes)
```
gdzie
- `event`: obiekt Event.
- `messages`: asocjacyjna tablica, gdzie kluczami są ID atrybutów, a wartościami tablice opisów błędów dla tych atrybutów.
- `errorAttributes`: tablica atrybutów z błędami walidacji. Sprawdź konstrukcję `attributeDefaults`, aby dowiedzieć się więcej o strukturze tego parametru.
### `beforeValidateAttribute`
`beforeValidateAttribute` jest wyzwalane przed walidacją atrybutu.
Sygnatura metody obsługującej to zdarzenie powinna wyglądać następująco:
```javascript
function (event, attribute, messages, deferreds)
```
gdzie
- `event`: obiekt Event.
- `attribute`: atrybut poddawany walidacji. Sprawdź konstrukcję `attributeDefaults`, aby dowiedzieć się więcej o strukturze tego parametru.
- `messages`: tablica, do której możesz dodać opisy błędów walidacji dla wybranego atrybutu.
- `deferreds`: tablica obiektów kolejki. Możesz użyć `deferreds.add(callback)`, aby dodać nową walidację do kolejki.
Jeśli metoda obsługująca zwróci boolean `false`, zatrzyma dalszą walidację wybranego atrybutu. W takim wypadku zdarzenie
`afterValidateAttribute` nie będzie już wyzwalane.
### `afterValidateAttribute`
`afterValidateAttribute` jest wyzwalane po walidacji całego formularza i każdego atrybutu.
Sygnatura metody obsługującej to zdarzenie powinna wyglądać następująco:
```javascript
function (event, attribute, messages)
```
gdzie
- `event`: obiekt Event.
- `attribute`: atrybut poddawany walidacji. Sprawdź konstrukcję `attributeDefaults`, aby dowiedzieć się więcej o strukturze tego parametru.
- `messages`: tablica, do której możesz dodać opisy błędów walidacji dla wybranego atrybutu.
### `beforeSubmit`
`beforeSubmit` jest wyzwalane przed wysłaniem formularza, po pomyślnej walidacji.
Sygnatura metody obsługującej to zdarzenie powinna wyglądać następująco:
```javascript
function (event)
```
gdzie event jest obiektem Event.
Jeśli metoda obsługująca zwróci boolean `false`, zatrzyma wysyłanie formularza.
### `ajaxBeforeSend`
`ajaxBeforeSend` jest wyzwalane przed wysłaniem żądania AJAX w przypadku walidacji AJAX-owej.
Sygnatura metody obsługującej to zdarzenie powinna wyglądać następująco:
```javascript
function (event, jqXHR, settings)
```
gdzie
- `event`: obiekt Event.
- `jqXHR`: obiekt jqXHR.
- `settings`: konfiguracja żądania AJAX.
### `ajaxComplete`
`ajaxComplete` jest wyzwalane po ukończeniu żądania AJAX w przypadku walidacji AJAX-owej.
Sygnatura metody obsługującej to zdarzenie powinna wyglądać następująco:
```javascript
function (event, jqXHR, textStatus)
```
gdzie
- `event`: obiekt Event.
- `jqXHR`: obiekt jqXHR.
- `textStatus`: status żądania ("success", "notmodified", "error", "timeout", "abort" lub "parsererror").
## Wysyłanie formularza za pomocą AJAX
Walidacja może być przeprowadzona po stronie klienta lub za pomocą AJAX-a, ale wysyłanie formularza jest domyślnie przeprowadzane
za pomocą zwyczajnego żądania. Jeśli chcesz przesłać formularz za pomocą AJAX, możesz to zrobić obsługując zdarzenie `beforeSubmit`
formularza w następujący sposób:
```javascript
var $form = $('#formId');
$form.on('beforeSubmit', function() {
var data = $form.serialize();
$.ajax({
url: $form.attr('action'),
type: 'POST',
data: data,
success: function (data) {
// Implementacja pomyślnego statusu
},
error: function(jqXHR, errMsg) {
alert(errMsg);
}
});
return false; // powstrzymuje przed domyślnym sposobem wysłania
});
```
Aby dowiedzieć się więcej o funkcji jQuery `ajax()`, zapoznaj się z [dokumentacją jQuery](https://api.jquery.com/jQuery.ajax/).
## Dynamiczne dodawanie pól
We współczesnych aplikacjach webowych często koniecznie jest modyfikowanie formularza już po tym, jak został zaprezentowany użytkownikowi.
Dla przykładu może to być dodawanie nowego pola po kliknięciu w ikonę "z plusem".
Aby uruchomić walidację takich pól, należy je zarejestrować za pomocą JavaScriptowego pluginu ActiveForm.
Po dodaniu pola do formularza, należy dołączyć je również do listy walidacji:
```javascript
$('#contact-form').yiiActiveForm('add', {
id: 'address',
name: 'address',
container: '.field-address',
input: '#address',
error: '.help-block',
validate: function (attribute, value, messages, deferred, $form) {
yii.validation.required(value, messages, {message: "Informacja dotycząca walidacji tutaj"});
}
});
```
Aby usunąć pole z listy walidacji (aby nie było już sprawdzane), możesz wykonać następujący kod:
```javascript
$('#contact-form').yiiActiveForm('remove', 'address');
```

4
docs/guide-pl/start-installation.md

@ -203,7 +203,7 @@ DocumentRoot "path/to/basic/web"
Aby użyć [Nginx](http://wiki.nginx.org/) powinienieś zainstalować PHP jako [FPM SAPI](http://php.net/install.fpm).
Możesz użyć przedstawionej poniżej konfiguracji Nginx, zastępując jedynie ścieżkę `path/to/basic/web` aktualną ścieżką do `basic/web` Twojej aplikacji oraz
`mysite.local` aktualną nazwą hosta.
`mysite.test` aktualną nazwą hosta.
```nginx
server {
@ -213,7 +213,7 @@ server {
listen 80; ## nasłuchuj ipv4
#listen [::]:80 default_server ipv6only=on; ## nasłuchuj ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

209
docs/guide-pl/tutorial-yii-as-micro-framework.md

@ -0,0 +1,209 @@
# Używanie Yii jako mikroframeworka
Yii może być z powodzeniem wykorzystywane bez dodatkowych funkcjonalności dostarczanych przez prosty i zaawansowany szablon aplikacji. Inaczej mówiąc,
Yii już jest samo w sobie mikroframeworkiem. Do pracy z Yii nie jest wymagane, aby struktura folderów była dokładnie taka, jak pokazana w szablonach.
Jest to szczególnie korzystne, kiedy nie potrzebujesz gotowego kodu szablonów, jak w przypadku assetów luc widoków. Jednym z takich przypadków jest budowa JSON API.
W tej sekcji pokażemy jak to zrobić.
## Instalacja Yii
Stwórz folder dla plików swojego projektu i ustaw go jako aktywną ścieżkę. Komendy używane w przykładach oparte są na składni UNIXowej, ale podobne dostępne są również w Windows.
```bash
mkdir micro-app
cd micro-app
```
> Note: minimalna wiedza na temat użytkowania Composera jest wymagana w celu kontynuacji. Jeśli nie wiesz, jak używać Composera, prosimy o zapoznanie się najpierw z [Przewodnikiem po Composerze](https://getcomposer.org/doc/00-intro.md).
Stwórz plik `composer.json` w folderze `micro-app`, używając swojego ulubionego edytora i dodaj co następuje:
```json
{
"require": {
"yiisoft/yii2": "~2.0.0"
},
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
]
}
```
Zapisz plik i uruchom komendę `composer install`. Dzięki temu zainstalujesz framework i wszystkie jego zależności.
## Tworzenie struktury projektu
Po zainstalowaniu frameworka, czas na utworzenie [punktu wejścia](structure-entry-scripts.md) dla aplikacji. Punkt wejścia to pierwszy plik, który będzie uruchamiany,
podczas startu aplikacji. Ze względów bezpieczeństwa, zalecane jest, aby plik punktu wejścia umieścić w osobnym folderze, który będzie ustawiony jako bazowy folder aplikacji.
Stwórz folder `web` i umieść w nim plik `index.php` z następującą zawartością:
```php
<?php
// zakomentuj poniższe dwie linie przy wydaniu aplikacji na środowisku produkcyjnym
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
$config = require __DIR__ . '/../config.php';
(new yii\web\Application($config))->run();
```
Stwórz również plik `config.php`, który będzie zawierał całą konfigurację aplikacji:
```php
<?php
return [
'id' => 'micro-app',
// ścieżką bazową aplikacji będzie folder `micro-app`
'basePath' => __DIR__,
// w tym miejscu określamy, gdzie aplikacja ma szukać wszystkich kontrolerów
'controllerNamespace' => 'micro\controllers',
// ustawiamy alias, aby umożliwić autoładowanie klas z przestrzeni nazw 'micro'
'aliases' => [
'@micro' => __DIR__,
],
];
```
> Info: Pomimo że konfiguracja mogłaby być przechowywana w pliku `index.php`, zalecane jest, aby zapisana była osobno.
> Dzięki temu może być również wykorzystywana dla aplikacji konsolowej, jak pokazano to poniżej.
Twój projekt jest już gotowy do rozpoczęcia kodowania. Od Ciebie również zależy struktura jego folderów, dopóki jak będziesz pamiętać o poprawnych przestrzeniach nazw.
## Tworzenie pierwszego kontrolera
Stwórz folder `controllers` i dodaj w nim plik `SiteController.php`, który będzie domyślnym kontrolerem obsługującym żądania bez wskazanej wyraźnie ścieżki.
```php
<?php
namespace micro\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public function actionIndex()
{
return 'Hello World!';
}
}
```
Jeśli chcesz użyć innej nazwy dla tego kontrolera, nie krępuj się - musisz jedynie skonfigurować odpowiednio [[yii\base\Application::$defaultRoute]].
Dla przykładu, jeśli chcesz go zmienić na `DefaultController`, ustaw `'defaultRoute' => 'default/index'` w konfiguracji.
W tym momencie struktura projektu powinna wyglądać jak poniżej:
```
micro-app/
├── composer.json
├── web/
└── index.php
└── controllers/
└── SiteController.php
```
Jeśli nie ustawiłeś jeszcze serwera web, być może zechcesz zerknąć na [pliki przykładów konfiguracji serwera web](start-installation.md#configuring-web-servers).
Inną opcją jest skorzystanie z komendy `yii serve`, która użyje wbudowanego w PHP serwera web. Możesz uruchomić ją z poziomu folderu `micro-app/` za pomocą:
vendor/bin/yii serve --docroot=./web
Uruchomienie adresu URL aplikacji w przeglądarce powinno zaowocować teraz komunikatem "Hello World!", który jest zwracany w `SiteController::actionIndex()`.
> Info: W naszym przykładzie zmieniliśmy domyślną przestrzeń nazw aplikacji `app` na `micro`, aby zademonstrować,
> że nie ma potrzeby być ograniczonym przez tę nazwę (w przypadku, gdyby ktoś myślał, że jednak jest). Po zmianie jej na inną,
> należy jedynie zmodyfikować odpowiednio [[yii\base\Application::$controllerNamespace|przestrzeń nazw kontrolerów]] i ustawić właściwy alias.
## Tworzenie API REST
Aby zademonstrować, jak korzystać z naszego "mikroframeworka", stworzymy proste API REST dla postów.
Aby API mogło zwrócić jakieś dane, najpierw potrzebujemy ich bazy. Dodaj konfigurację połączenia z bazą danych do konfiguracji aplikacji:
```php
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'sqlite:@micro/database.sqlite',
],
],
```
> Info: Używamy w tym przykładzie bazy danych sqlite dla uproszczenia. Aby zapoznać się z innymi opcjami, przejdź do [przewodnika po bazach danych](db-dao.md).
Następnie tworzymy [migrację bazodanową](db-migrations.md), aby skonstruować tabelę postów.
Upewnij się, że posiadasz oddzielny plik konfiguracji, jak zostało to opisane powyżej, ponieważ musimy teraz uruchomić komendę konsolową, jak poniżej.
Uruchomienie tych komend utworzy plik migracji i wprowadzi migrację do bazy danych:
vendor/bin/yii migrate/create --appconfig=config.php create_post_table --fields="title:string,body:text"
vendor/bin/yii migrate/up --appconfig=config.php
Stwórz folder `models` i plik `Post.php` w tym folderze. Poniżej znajdziesz kod dla modelu:
```php
<?php
namespace micro\models;
use yii\db\ActiveRecord;
class Post extends ActiveRecord
{
public static function tableName()
{
return '{{posts}}';
}
}
```
> Info: Tak utworzony model jest klasą ActiveRecord, która reprezentuje dane z tabeli `posts`.
> Zapoznaj się z [przewodnikiem po active record](db-active-record.md), aby uzyskać więcej informacji.
Aby obsłużyć posty w naszym API, dodaj `PostController` w `controllers`:
```php
<?php
namespace micro\controllers;
use yii\rest\ActiveController;
class PostController extends ActiveController
{
public $modelClass = 'micro\models\Post';
public function behaviors()
{
// wyłącz rateLimiter, który do pracy wymaga, aby użytkownik był zalogowany
$behaviors = parent::behaviors();
unset($behaviors['rateLimiter']);
return $behaviors;
}
}
```
W tym momencie nasze API obsługuje już następujące adresy URL:
- `/index.php?r=post` - wyświetla listę wszystkich postów
- `/index.php?r=post/view&id=1` - wyświetla post o ID 1
- `/index.php?r=post/create` - tworzy post
- `/index.php?r=post/update&id=1` - aktualizuje post o ID 1
- `/index.php?r=post/delete&id=1` - usuwa post o ID 1
Zapoznaj się z poniższymi wskazówkami, które pomogą Ci w dalszym rozwijaniu Twojej aplikacji:
- Aktualnie API rozpoznaje jedynie urlenkodowane dane formularza na wejściu - aby zmienić je w prawdziwe JSON API,
musisz skonfigurować [[yii\web\JsonParser]].
- Aby uczynić adresy URL, bardziej przyjaznymi dla użytkownika, musisz skonfigurować ruting.
Zobacz [przewodnik po rutingu REST](rest-routing.md), który wyjaśnia, jak to zrobić.
- Dodatkowo przeczytaj też sekcję [Dalsze kroki](start-looking-ahead.md), która podpowie jak zaplanować rozwój projektu.

4
docs/guide-pt-BR/caching-data.md

@ -96,8 +96,8 @@ Yii suporta uma ampla gama de sistemas de cache. A seguir um resumo:
[Redis](http://redis.io/) (requer redis versão 2.6.12 ou mais recente).
* [[yii\caching\WinCache]]: usa a extensão PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)
([veja também](http://php.net/manual/en/book.wincache.php)).
* [[yii\caching\XCache]]: usa a extensão PHP [XCache](http://xcache.lighttpd.net/).
* [[yii\caching\ZendDataCache]]: usa
* [[yii\caching\XCache]] _(deprecated)_: usa a extensão PHP [XCache](http://xcache.lighttpd.net/).
* [[yii\caching\ZendDataCache]] _(deprecated)_: usa
[Cache de Dados Zend](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm)
como o meio de cache subjacente.

4
docs/guide-pt-BR/concept-di-container.md

@ -75,7 +75,7 @@ Cada vez que [[yii\di\Container::get()]] for chamado, o callable correspondente
O callable é responsável por resolver as dependências e injetá-las de forma adequada para os objetos recém-criados. Por exemplo:
```php
$container->set('Foo', function () {
$container->set('Foo', function ($container, $params, $config) {
$foo = new Foo(new Bar);
// ... Outras inicializações...
return $foo;
@ -89,7 +89,7 @@ Para ocultar a lógica complexa da construção de um novo objeto você pode usa
```php
class FooBuilder
{
public static function build()
public static function build($container, $params, $config)
{
return function () {
$foo = new Foo(new Bar);

2
docs/guide-pt-BR/concept-events.md

@ -192,7 +192,7 @@ use yii\base\Event;
use yii\db\ActiveRecord;
Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
Yii::trace(get_class($event->sender) . ' is inserted');
Yii::debug(get_class($event->sender) . ' is inserted');
});
```

10
docs/guide-pt-BR/runtime-logging.md

@ -16,7 +16,7 @@ Nesta seção, vamos descrever principalmente os dois primeiros passos.
Gravar mensagens de log é tão simples como chamar um dos seguintes métodos de registro:
* [[Yii::trace()]]: gravar uma mensagem para rastrear como um determinado trecho de código é executado. Isso é principalmente para o uso de desenvolvimento.
* [[Yii::debug()]]: gravar uma mensagem para rastrear como um determinado trecho de código é executado. Isso é principalmente para o uso de desenvolvimento.
* [[Yii::info()]]: gravar uma mensagem que transmite algumas informações úteis.
* [[Yii::warning()]]: gravar uma mensagem de aviso que indica que algo inesperado aconteceu.
* [[Yii::error()]]: gravar um erro fatal que deve ser investigado o mais rápido possível.
@ -24,7 +24,7 @@ Gravar mensagens de log é tão simples como chamar um dos seguintes métodos de
Estes métodos gravam mensagens de log em vários *níveis* e *categorias*. Eles compartilham a mesma assinatura de função `function ($message, $category = 'application')`, onde `$message` significa a mensagem de log a ser gravada, enquanto `$category` é a categoria da mensagem de log. O código no exemplo a seguir registra uma mensagem de rastreamento sob a categoria padrão `application`:
```php
Yii::trace('start calculating average revenue');
Yii::debug('start calculating average revenue');
```
> Observação: Mensagens de log podem ser strings, bem como dados complexos, tais como arrays ou objetos. É da responsabilidade dos [destinos de log](#log-targets) lidar adequadamente com as mensagens de log. Por padrão, se uma mensagem de log não for uma string, ela será exportada como uma string chamando [[yii\helpers\VarDumper::export()]].
@ -32,7 +32,7 @@ Yii::trace('start calculating average revenue');
Para melhor organizar e filtrar as mensagens de log, é recomendável que você especifique uma categoria apropriada para cada mensagem de log. Você pode escolher um esquema de nomenclatura hierárquica para as categorias, o que tornará mais fácil para os [destinos de log](#log-targets) filtrar mensagens com base em suas categorias. Um esquema de nomes simples, mas eficaz é usar a constante mágica PHP `__METHOD__` para os nomes das categorias. Esta é também a abordagem utilizada no código central do framework Yii. Por exemplo,
```php
Yii::trace('start calculating average revenue', __METHOD__);
Yii::debug('start calculating average revenue', __METHOD__);
```
A constante `__METHOD__` corresponde ao nome do método (prefixado com o caminho completo do nome da classe) onde a constante aparece. Por exemplo, é igual a string `'app\controllers\RevenueController::calculate'` se o código acima for chamado dentro deste método.
@ -100,7 +100,7 @@ A propriedade [[yii\log\Target::levels|levels]] é um array que consiste em um o
* `error`: corresponde a mensagens logadas por [[Yii::error()]].
* `warning`: corresponde a mensagens logadas por [[Yii::warning()]].
* `info`: corresponde a mensagens logadas por [[Yii::info()]].
* `trace`: corresponde a mensagens logadas por [[Yii::trace()]].
* `trace`: corresponde a mensagens logadas por [[Yii::debug()]].
* `profile`: corresponde a mensagens logadas por [[Yii::beginProfile()]] e [[Yii::endProfile()]], que será explicado em mais detalhes na subseção [Perfil de Desempenho](#performance-profiling).
Se você não especificar a propriedade [[yii\log\Target::levels|levels]], significa que o alvo de log processará mensagens de *qualquer* nível.
@ -218,7 +218,7 @@ Quando o [[yii\log\Logger|logger object]] libera mensagens de log para os [alvos
]
```
Devido a configuração de nível, liberação e exportação, por padrão quando você chama `Yii::trace()` ou qualquer outro método de log, você NÃO verá a mensagem de log imediatamente no destino. Isto poderia ser um problema para algumas aplicações console de longa execução. Para fazer cada mensagem de log aparecer imediatamente no destino, você deve configurar ambos [[yii\log\Dispatcher::flushInterval|flushInterval]] e [[yii\log\Target::exportInterval|exportInterval]] para 1, como mostrado a seguir:
Devido a configuração de nível, liberação e exportação, por padrão quando você chama `Yii::debug()` ou qualquer outro método de log, você NÃO verá a mensagem de log imediatamente no destino. Isto poderia ser um problema para algumas aplicações console de longa execução. Para fazer cada mensagem de log aparecer imediatamente no destino, você deve configurar ambos [[yii\log\Dispatcher::flushInterval|flushInterval]] e [[yii\log\Target::exportInterval|exportInterval]] para 1, como mostrado a seguir:
```php
return [

4
docs/guide-pt-BR/start-installation.md

@ -202,7 +202,7 @@ DocumentRoot "path/to/basic/web"
Você deve ter instalado o PHP como um [FPM SAPI](http://php.net/install.fpm) para
usar o [Nginx](http://wiki.nginx.org/). Use a seguinte configuração do Nginx,
substituindo `path/to/basic/web` com o caminho real para `basic/web` e `mysite.local`
substituindo `path/to/basic/web` com o caminho real para `basic/web` e `mysite.test`
com o nome de host real a servidor.
```
@ -213,7 +213,7 @@ server {
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

2
docs/guide-pt-BR/structure-filters.md

@ -105,7 +105,7 @@ class ActionTimeFilter extends ActionFilter
public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::trace("Action '{$action->uniqueId}' spent $time second.");
Yii::debug("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}

3
docs/guide-ru/README.md

@ -79,7 +79,7 @@ All Rights Reserved.
* [Active Record](db-active-record.md) - Получение объектов AR, работа с ними и определение связей.
* [Миграции](db-migrations.md) - Контроль версий схемы данных при работе в команде.
* [Sphinx](https://github.com/yiisoft/yii2-sphinx/blob/master/docs/guide-ru/README.md)
* [Redis](https://github.com/yiisoft/yii2-redis/blob/master/docs/guide/README.md)
* [Redis](https://github.com/yiisoft/yii2-redis/blob/master/docs/guide-ru/README.md)
* [MongoDB](https://github.com/yiisoft/yii2-mongodb/blob/master/docs/guide-ru/README.md)
* [ElasticSearch](https://github.com/yiisoft/yii2-elasticsearch/blob/master/docs/guide/README.md)
@ -175,6 +175,7 @@ All Rights Reserved.
* [Окружение виртуального хостинга](tutorial-shared-hosting.md)
* [Шаблонизаторы](tutorial-template-engines.md)
* [Работа со сторонним кодом](tutorial-yii-integration.md)
* [Использование Yii в качестве микро-framework'а](tutorial-yii-as-micro-framework.md)
Виджеты

12
docs/guide-ru/caching-data.md

@ -102,14 +102,14 @@ Yii поддерживает множество хранилищ кэша:
* [[yii\caching\MemCache]]: использует расширения PHP [memcache](http://php.net/manual/en/book.memcache.php) и [memcached](http://php.net/manual/en/book.memcached.php). Этот вариант может рассматриваться как самый быстрый при работе в распределенных приложениях (например, с несколькими серверами, балансировкой нагрузки и так далее);
* [[yii\redis\Cache]]: реализует компонент кэша на основе [Redis](http://redis.io/), хранилища ключ-значение (требуется Redis версии 2.6.12 или выше);
* [[yii\caching\WinCache]]: использует расширение PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension) ([смотрите также](http://php.net/manual/en/book.wincache.php));
* [[yii\caching\XCache]]: использует расширение PHP [XCache](http://xcache.lighttpd.net/);
* [[yii\caching\ZendDataCache]]: использует [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm).
* [[yii\caching\XCache]] _(deprecated)_: использует расширение PHP [XCache](http://xcache.lighttpd.net/);
* [[yii\caching\ZendDataCache]] _(deprecated)_: использует [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm).
> Tip: Вы можете использовать разные способы хранения кэша в одном приложении. Общая стратегия заключается в использовании памяти под хранение небольших часто используемых данных (например, статистические данные). Для больших и реже используемых данных (например, содержимое страницы) лучше использовать файлы или базу данных.
## Кэш API, <a name="cache-apis"> </a>
У всех компонентов кэша один базовый класс [[yii\caching\Cache]] со следующими методами:
У всех компонентов кэша имеется один базовый класс [[yii\caching\Cache]] со следующими методами:
* [[yii\caching\Cache::get()|get()]]: возвращает данные по указанному ключу. Если данные не найдены или устарели, то
значение `false` будет возвращено;
@ -291,9 +291,9 @@ $result = $db->cache(function ($db) {
}, $duration, $dependency);
```
Любые SQL запросы в анонимной функции будут кэшироваться в течении указанного промежутка времени с заданной зависимостью. Если результат в кэше актуален - запрос будет пропущен и, вместо этого, из кэша будет возвращен результат. Если вы не укажете `'$duration'`, то значение [[yii\db\Connection::queryCacheDuration|queryCacheDuration]] будет использоваться вместо него.
Любые SQL запросы в анонимной функции будут кэшироваться в течение указанного промежутка времени и с помощью заданной зависимости. Если результат запроса в кэше актуален, запрос будет пропущен, и вместо этого из кэша будет возвращен результат. Если вы не укажете параметр `'$duration'`, то значение [[yii\db\Connection::queryCacheDuration|queryCacheDuration]] будет использоваться вместо него.
Иногда в пределах `"cache()"` вы можете отключить кэширование запроса. В этом случае вы можете использовать [[yii\db\Connection::noCache()]].
Иногда в пределах `"cache()"` вы можете захотеть отключить кэширование запроса. В этом случае вы можете использовать [[yii\db\Connection::noCache()]].
```php
$result = $db->cache(function ($db) {
@ -338,6 +338,6 @@ $result = $db->cache(function ($db) {
### Ограничения <span id="query-caching-limitations"></span>
Кэширование запросов не работает с результатами запросов, которые содержат обработчики ресурсов. Например, при использовании типа столбца `BLOB` в некоторых СУБД, в качестве результата запроса будет выведен ресурс обработчик данных столбца.
Кэширование запросов не работает с результатами запросов, которые содержат обработчики ресурсов. Например, при использовании столбца типа `BLOB` в некоторых СУБД, в качестве результата запроса будет возвращен указатель на ресурс для этого столбца данных.
Некоторые кэш хранилища имеют ограничение в размере данных. Например, Memcache ограничивает максимальный размер каждой записи до 1 Мб. Таким образом, если результат запроса превышает этот предел, данные не будут закэшированы.

3
docs/guide-ru/concept-aliases.md

@ -18,6 +18,9 @@ Yii::setAlias('@foo', '/path/to/foo');
// псевдоним URL
Yii::setAlias('@bar', 'http://www.example.com');
// псевдоним конкретного файла, содержащего класс \foo\Bar
Yii::setAlias('@foo/Bar.php', '/definitely/not/foo/Bar.php');
```
> Note: псевдоним пути к файлу или URL *не* обязательно указывает на существующий файл или ресурс.

12
docs/guide-ru/concept-di-container.md

@ -117,14 +117,14 @@ $container->get('Foo', [], [
```php
class FileStorage
{
public function __contruct($root) {
public function __construct($root) {
// делаем что-то
}
}
class DocumentsReader
{
public function __contruct(FileStorage $fs) {
public function __construct(FileStorage $fs) {
// делаем что-то
}
}
@ -151,7 +151,7 @@ $container->setDefinitions([
'class' => 'app\components\Response',
'format' => 'json'
],
'app\storage\DocumentsReader' => function () {
'app\storage\DocumentsReader' => function ($container, $params, $config) {
$fs = new app\storage\FileStorage('/var/tempfiles');
return new app\storage\DocumentsReader($fs);
}
@ -194,7 +194,7 @@ $container->setDefinitions([
]
]);
$reader = $container->get('app\storage\DocumentsReader);
$reader = $container->get('app\storage\DocumentsReader');
// Код будет работать ровно так же, как и в предыдущем примере.
```
@ -243,7 +243,7 @@ $reader = $container->get('app\storage\DocumentsReader');
Callback отвечает за разрешения зависимостей и внедряет их в соответствии с вновь создаваемыми объектами. Например,
```php
$container->set('Foo', function () {
$container->set('Foo', function ($container, $params, $config) {
$foo = new Foo(new Bar);
// ... дополнительная инициализация
return $foo;
@ -258,7 +258,7 @@ callable:
```php
class FooBuilder
{
public static function build()
public static function build($container, $params, $config)
{
$foo = new Foo(new Bar);
// ... дополнительная инициализация ...

4
docs/guide-ru/concept-events.md

@ -188,7 +188,7 @@ use yii\base\Event;
use yii\db\ActiveRecord;
Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
Yii::trace(get_class($event->sender) . ' добавлен');
Yii::debug(get_class($event->sender) . ' добавлен');
});
```
@ -266,7 +266,7 @@ class Developer extends Component implements DanceEventInterface
```php
Event::on('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) {
Yii::trace(get_class($event->sender) . ' just danced'); // Оставит запись в журнале о том, что кто-то танцевал
Yii::debug(get_class($event->sender) . ' just danced'); // Оставит запись в журнале о том, что кто-то танцевал
});
```

8
docs/guide-ru/db-migrations.md

@ -266,7 +266,7 @@ yii migrate/create create_post_table --fields="author_id:integer:notNull:foreign
class m160328_040430_create_post_table extends Migration
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function up()
{
@ -314,7 +314,7 @@ class m160328_040430_create_post_table extends Migration
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function down()
{
@ -465,7 +465,7 @@ yii migrate/create create_junction_table_for_post_and_tag_tables
class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migration
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function up()
{
@ -512,7 +512,7 @@ class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migra
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function down()
{

12
docs/guide-ru/input-validation.md

@ -358,8 +358,8 @@ class MyForm extends Model
public function validateCountry($attribute, $params)
{
if (!in_array($this->$attribute, ['USA', 'Web'])) {
$this->addError($attribute, 'Страна должна быть либо "USA" или "Web".');
if (!in_array($this->$attribute, ['USA', 'Indonesia'])) {
$this->addError($attribute, 'Страна должна быть либо "USA" или "Indonesia".');
}
}
}
@ -384,7 +384,9 @@ class MyForm extends Model
Вы можете реализовать свою логику проверки путем переопределения метода
[[yii\validators\Validator::validateAttribute()]]. Если атрибут не прошел проверку, вызвать
[[yii\base\Model::addError()]],
чтобы сохранить сообщение об ошибке в модели, как это делают [встроенные валидаторы](#inline-validators). Например:
чтобы сохранить сообщение об ошибке в модели, как это делают [встроенные валидаторы](#inline-validators).
Валидация может быть помещена в отдельный класс [[components/validators/CountryValidator]]. В этом случае можно использовать метод [[yii\validators\Validator::addError()]] для того, чтобы добавить своё сообщение об ошибке в модель:
```php
namespace app\components;
@ -395,8 +397,8 @@ class CountryValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
if (!in_array($model->$attribute, ['USA', 'Web'])) {
$this->addError($model, $attribute, 'Страна должна быть либо "USA" или "Web".');
if (!in_array($model->$attribute, ['USA', 'Indonesia'])) {
$this->addError($model, $attribute, 'Страна должна быть либо "{country1}" либо "{country2}".', ['country1' => 'USA', 'country2' => 'Indonesia']);
}
}
}

20
docs/guide-ru/intro-yii.md

@ -1,16 +1,15 @@
Что такое Yii?
==============
Yii – это высокопроизводительный компонентный PHP фреймворк, предназначенный для быстрой разработки современных веб
приложений. Слово Yii (произносится как `Йи` `[ji:]`) в китайском языке означает «простой и эволюционирующий». Также Yii
Yii – это высокопроизводительный компонентный PHP фреймворк, предназначенный для быстрой разработки современных веб-приложений. Слово Yii (произносится как `Йи` `[ji:]`) в китайском языке означает «простой и эволюционирующий». Также Yii
может расшифровываться как акроним **Yes It Is**!
Для каких задач больше всего подходит Yii?
------------------------------------------
Yii – это универсальный фреймворк и может быть задействован во всех типах веб приложений. Благодаря его компонентной
структуре и отличной поддержке кэширования, фреймворк особенно подходит для разработки таких крупных проектов как
Yii – это универсальный фреймворк и может быть задействован во всех типах веб-приложений. Благодаря его компонентной
структуре и отличной поддержке кэширования, фреймворк особенно подходит для разработки таких крупных проектов, как
порталы, форумы, CMS, магазины или RESTful-приложения.
@ -20,15 +19,15 @@ Yii – это универсальный фреймворк и может бы
Если вы уже знакомы с другими фреймворками, вам наверняка будет интересно сравнить их с Yii.
- Как и многие другие PHP фреймворки, для организации кода Yii использует архитектурный паттерн MVC (Model-View-Controller).
- Yii придерживается философии простого и элегантного кода не пытаясь усложнять дизайн только ради следования каким-либо
- Yii придерживается философии простого и элегантного кода, не пытаясь усложнять дизайн только ради следования каким-либо
шаблонам проектирования.
- Yii является full-stack фреймворком и включает в себя проверенные и хорошо зарекомендовавшие себя возможности, такие как
ActiveRecord для реляционных и NoSQL баз данных, поддержку REST API, многоуровневое кэширование и другие.
- Yii отлично расширяем. Вы можете настроить или заменить практически любую часть основного кода. Используя архитектуру расширений легко делиться кодом или использовать код сообщества.
- Yii отлично расширяем. Вы можете настроить или заменить практически любую часть основного кода. Используя архитектуру расширений, легко делиться кодом или использовать код сообщества.
- Одна из главных целей Yii – производительность.
Yii — не проект одного человека. Он поддерживается и развивается [сильной командой](http://www.yiiframework.com/team/) и большим сообществом разработчиков,
которые ей помогают. Авторы фреймворка следят за тенденциями веб разработки и развитием других проектов. Наиболее
которые ей помогают. Авторы фреймворка следят за тенденциями веб-разработки и развитием других проектов. Наиболее
подходящие возможности и лучшие практики регулярно внедряются в фреймворк в виде простых и элегантных интерфейсов.
Версии Yii
@ -43,9 +42,10 @@ Yii — не проект одного человека. Он поддержив
Требования к ПО и знаниям
-------------------------
Yii 2.0 требует PHP 5.4.0 и выше. Чтобы узнать требования для отдельных возможностей вы можете запустить скрипт проверки
Yii 2.0 требует PHP 5.4.0 и выше и наилучшим образом работает на последней версии PHP 7. Чтобы узнать требования для отдельных возможностей вы можете запустить скрипт проверки
требований, который поставляется с каждым релизом фреймворка.
Для разработки на Yii потребуется общее понимание ООП так как фреймворк полностью следует этой парадигме. Также стоит
Для разработки на Yii потребуется общее понимание ООП, так как фреймворк полностью следует этой парадигме. Также стоит
изучить такие современные возможности PHP как [пространства имён](http://www.php.net/manual/ru/language.namespaces.php)
и [трейты](http://www.php.net/manual/ru/language.oop5.traits.php).
и [трейты](http://www.php.net/manual/ru/language.oop5.traits.php). Понимание этих концепций позволит вам более легко освоиться c Yii 2.0.

8
docs/guide-ru/output-data-providers.md

@ -258,7 +258,7 @@ class CsvDataProvider extends BaseDataProvider
/**
* @inheritdoc
* {@inheritdoc}
*/
public function init()
{
@ -269,7 +269,7 @@ class CsvDataProvider extends BaseDataProvider
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function prepareModels()
{
@ -298,7 +298,7 @@ class CsvDataProvider extends BaseDataProvider
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function prepareKeys($models)
{
@ -320,7 +320,7 @@ class CsvDataProvider extends BaseDataProvider
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function prepareTotalCount()
{

20
docs/guide-ru/output-data-widgets.md

@ -222,6 +222,13 @@ echo GridView::widget([
'attribute' => 'birthday',
'format' => ['date', 'php:Y-m-d']
],
'created_at:datetime', // короткий вид записи формата
[
'label' => 'Education',
'attribute' => 'education',
'filter' => ['0' => 'Elementary', '1' => 'Secondary', '2' => 'Higher'],
'filterInputOptions' => ['prompt' => 'All educations', 'class' => 'form-control', 'id' => null]
],
],
]);
```
@ -235,6 +242,13 @@ echo GridView::widget([
Для конфигурации колонок данных также доступен короткий вид записи, который описан в API документации для [[yii\grid\GridView::columns|колонок]].
Используйте [[yii\grid\DataColumn::filter|filter]] и [[yii\grid\DataColumn::filterInputOptions|filterInputOptions]] для
настройки HTML кода фильтра.
По умолчанию заголовки колонок генерируются используя [[yii\data\Sort::link]]. Это можно изменить через свойство
[[yii\grid\Column::header]]. Для изменения заголовка нужно задать [[yii\grid\DataColumn::$label]], как в
примере выше. По умолчанию текст будет взят из модели данных. Подробное описание ищите в [[yii\grid\DataColumn::getHeaderCellLabel]].
#### ActionColumn
[[yii\grid\ActionColumn|ActionColumn]] отображает кнопки действия, такие как изменение или удаление для каждой строки.
@ -619,7 +633,7 @@ class UserView extends ActiveRecord
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public static function tableName()
{
@ -632,7 +646,7 @@ class UserView extends ActiveRecord
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function rules()
{
@ -642,7 +656,7 @@ class UserView extends ActiveRecord
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function attributeLabels()
{

21
docs/guide-ru/output-formatting.md

@ -36,9 +36,8 @@ Formatter может быть использован двумя различны
[[yii\i18n\Formatter::locale|locale]]. Если оно не было настроено, то в качестве локали будет использован
[[yii\base\Application::language|язык приложения]]. Подробнее смотрите в разделе «[интернационализация](tutorial-i18n.md)».
Компонент форматирования будет выбирать корректный формат для даты и чисел в соответствии с локалью, включая имена
месяцев и дней недели, переведённые на текущий язык. Форматирование дат также зависит от
[[yii\i18n\Formatter::timeZone|часового пояса]], которая
также будет из свойства [[yii\base\Application::timeZone|timeZone]] приложения, если она не была задана явно.
месяцев и дней недели, переведённые на текущий язык.
Форматирование дат также зависит от [[yii\i18n\Formatter::timeZone|часового пояса]], который будет взят из одноимённого свойства [[yii\base\Application::timeZone|timeZone]] приложения, если не был задан явно. В свою очередь [[yii\base\Application::timeZone|timeZone]] устанавливает / читает временную зону PHP.
Например, форматирование даты, вызванное с разной локалью, отобразит разные результаты::
@ -140,16 +139,14 @@ echo Yii::$app->formatter->asTime('2014-10-06 12:41:00'); // 14:41:00
echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00
```
Начиная с версии 2.0.1 стало возможно настраивать часовой пояс для предполагаемых timestamp, которые не включают в себя
часовой пояс, как во втором примере в коде выше. Вы можете задать [[yii\i18n\Formatter::defaultTimeZone]] часовым поясом,
который вы используете для хранения данных.
> Note: Поскольку часовые пояса являются субъектом ответственности правительств по всему миру и могут часто меняться,
> это значит, что вы, вероятно, не имеете самую свежую информацию в базе данных часовых поясов, установленной на вашем сервере.
> Вы можете обратиться к [ICU руководству](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data)
> для получения подробностей об обновлении базы данных часовых поясов.
> См. также: [Настройка вашего PHP окружения для интернационализации](tutorial-i18n.md#setup-environment).
Если [[yii\i18n\Formatter::timeZone|часовой пояс форматтера]] не задан явно, используется
[[yii\base\Application::timeZone|часовой пояс приложения]], то есть тот же, что задан в
конфигурации PHP.
> Note: Поскольку правила для часовых поясов принимаются различными правительствами и могут часто меняться,
> вероятно, информация в базе данных часовых поясов на вашем сервере не самая свежая.
> Как обновить базу вы можете узнать из [руководства ICU](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data).
> Смотрите также: [Настройка вашего PHP окружения для интернационализации](tutorial-i18n.md#setup-environment).
Форматирование чисел <span id="numbers"></span>
------------------

14
docs/guide-ru/rest-resources.md

@ -50,9 +50,9 @@ http://localhost/users?fields=id,email&expand=profile
[[yii\db\ActiveRecord::fields()]] возвращает только те атрибуты, которые были объявлены в схеме БД.
Вы можете переопределить `fields()` для того, чтобы добавить, удалить, переименовать или переобъявить поля. Значение,
возвращаемое `fields()`, должно быть массивом. Его ключи это имена полей, и значения могут быть либо именами
свойств/атрибутов, либо анонимными функциями, которые возвращают значение соответствующих полей. Если имя атрибута такое же,
как ключ массива вы можете опустить значение:
возвращаемое `fields()`, должно быть массивом. Его ключи — это названия полей. Значения могут быть либо именами
свойств/атрибутов, либо анонимными функциями, которые возвращают значение соответствующих свойств. Когда
название поля совпадает с именем аттрибута вы можете опустить ключ массива:
```php
// явное перечисление всех атрибутов лучше всего использовать когда вы хотите быть уверенным что изменение
@ -61,11 +61,11 @@ http://localhost/users?fields=id,email&expand=profile
public function fields()
{
return [
// название поля совпадает с названием атрибута
// название поля совпадает с именем атрибута
'id',
// имя поля "email", атрибут "email_address"
// название поля "email", атрибут "email_address"
'email' => 'email_address',
// имя поля "name", значение определяется callback-ом PHP
// название поля "name", значение определяется callback-ом PHP
'name' => function () {
return $this->first_name . ' ' . $this->last_name;
},
@ -77,7 +77,7 @@ public function fields()
{
$fields = parent::fields();
// удаляем не безопасные поля
// удаляем небезопасные поля
unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);
return $fields;

14
docs/guide-ru/runtime-logging.md

@ -14,7 +14,7 @@ Yii предоставляет мощную, гибко настраиваему
Запись сообщений лога осуществляется вызовом одного из следующих методов:
* [[Yii::trace()]]: записывает сообщения для отслеживания выполнения кода приложения. Используется, в основном, при разработке.
* [[Yii::debug()]]: записывает сообщения для отслеживания выполнения кода приложения. Используется, в основном, при разработке.
* [[Yii::info()]]: записывает сообщение, содержащее какую-либо полезную информацию.
* [[Yii::warning()]]: записывает *тревожное* сообщение при возникновении неожиданного события.
* [[Yii::error()]]: записывает критическую ошибку, на которую нужно, как можно скорее, обратить внимаение.
@ -22,7 +22,7 @@ Yii предоставляет мощную, гибко настраиваему
Эти методы позволяют записывать сообщения разных *уровней важности* и *категорий*. Они имеют одинаковое описание функции `function ($message, $category = 'application')`, где `$message` передает сообщение для записи, а `$category` - категорию сообщения. В следующем примере будет записано *trace* сообщение с категорией по умолчанию `application`:
```php
Yii::trace('start calculating average revenue');
Yii::debug('start calculating average revenue');
```
> Note: Сообщение может быть как строкой так и объектом или массивом. За корректную работу с содержимым сообщения отвечают [цели лога](#log-targets). По умолчанию, если сообщение не является строкой, оно будет приведено к строковому типу при помощи [[yii\helpers\VarDumper::export()]].
@ -30,7 +30,7 @@ Yii::trace('start calculating average revenue');
Для упрощения работы с сообщениями лога и их фильтрации, рекомендуется явно указывать подходящую категорию для каждого сообщения. Возможно использование иерархической системы именования категорий, что значительно упростит [целям лога](#log-targets) фильтрацию сообщений по категориям. Простым и эффективным способом именования категорий является использование магической PHP константы `__METHOD__`. Такой подход используется в ядре фреймворка Yii. Например,
```php
Yii::trace('начало вычисления среднего дохода', __METHOD__);
Yii::debug('начало вычисления среднего дохода', __METHOD__);
```
Константа `__METHOD__` вычисляется как имя метода (включая полное имя класса), в котором она использована. Например, её значение будет вычислено как `'app\controllers\RevenueController::calculate'`, если показанный выше код вызывается в соответствующем методе.
@ -49,7 +49,9 @@ Yii::trace('начало вычисления среднего дохода', __
return [
// Компонент "log" должен быть загружен на этапе предзагрузки
'bootstrap' => ['log'],
// Компонент "log" обрабатывает сообщения с меткой времени timestamp.
// Задайте временную зону для создания корректных меток времени.
'timeZone' => 'Europe/Moscow',
'components' => [
'log' => [
'targets' => [
@ -99,7 +101,7 @@ return [
* `error`: соответствует сообщениям, сохраненным методом [[Yii::error()]].
* `warning`: соответствует сообщениям, сохраненным методом [[Yii::warning()]].
* `info`: соответствует сообщениям, сохраненным методом [[Yii::info()]].
* `trace`: соответствует сообщениям, сохраненным методом [[Yii::trace()]].
* `trace`: соответствует сообщениям, сохраненным методом [[Yii::debug()]].
* `profile`: соответствует сообщениям, сохраненным методами [[Yii::beginProfile()]] и [[Yii::endProfile()]], подробнее о которых написано в подразделе [Профилирование производительности](#performance-profiling).
Если свойство [[yii\log\Target::levels|levels]] не задано, цель логов будет обрабатывать сообщения с *любым* уровнем важности.
@ -220,7 +222,7 @@ return [
]
```
Из-за того, что значения максимального количества сообщений для передачи и выгрузки по умолчанию достаточно велико, при вызове метода `Yii::trace()`, или любого другого метода логгирования, сообщение не появится сразу в файле или таблице базы данных. Такое поведение может стать проблемой, например, в консольных приложениях с большим временем исполнения. Для того, чтобы все сообщения логов сразу же попадали в лог, необходимо установить значения свойств [[yii\log\Dispatcher::flushInterval|flushInterval]] и [[yii\log\Target::exportInterval|exportInterval]] равными 1, например так:
Из-за того, что значения максимального количества сообщений для передачи и выгрузки по умолчанию достаточно велико, при вызове метода `Yii::debug()`, или любого другого метода логгирования, сообщение не появится сразу в файле или таблице базы данных. Такое поведение может стать проблемой, например, в консольных приложениях с большим временем исполнения. Для того, чтобы все сообщения логов сразу же попадали в лог, необходимо установить значения свойств [[yii\log\Dispatcher::flushInterval|flushInterval]] и [[yii\log\Target::exportInterval|exportInterval]] равными 1, например так:
```php
return [

72
docs/guide-ru/security-best-practices.md

@ -162,16 +162,72 @@ CSRF - это аббревиатура для межсайтинговой по
Если это так, то нужно запретить доступ ко всему, кроме директории `web`. Если на вашем хостинге такое невозможно,
рассмотрите возможность смены хостинга.
Как избежать отладочной информации и утилит в продуктиве
--------------------------------------------------------
Как избежать вывода информации отладки и инструментов в рабочем режиме
----------------------------------------------------------------------
В режиме отладки, Yii отображает довольно подробные ошибки, которые полезны во время разработки. Дело в том, что
подробные ошибки удобны для нападающего, так как могут раскрыть структуру базы данных, параметров конфигурации и части
вашего кода. Никогда не запускайте продуктивное приложение с `YII_DEBUG` установленным в `true` в вашем `index.php`.
вашего кода. Никогда не запускайте приложения в рабочем режиме с `YII_DEBUG` установленным в `true` в вашем `index.php`.
Вы никогда не должны включать Gii на продуктиве. Он может быть использован для получения информации о структуре
базы данных, кода и может позволить заменить файлы, генерируемые Gii автоматически.
Вы никогда не должны включать Gii или Debug панель в рабочем режиме. Это может быть использованно для получения информации о структуре базы данных, кода и может позволить заменить файлы, генерируемые Gii автоматически.
Также следует избегать включения на продуктиве панели отладки, если только в этом нет острой необходимости.
Она раскрывает всё приложение и детали конфигурации. Если вам все таки нужно запустить панель отладки на продуктиве,
проверьте дважды что доступ ограничен только вашими IP-адресами.
Следует избегать включения в рабочем режиме панели отладки, если только в этом нет острой необходимости.
Она раскрывает всё приложение и детали конфигурации. Если Вам всё-таки нужно запустить панель отладки в рабочем режиме,
проверьте дважды, что доступ ограничен только вашими IP-адресами.
Далее по теме читайте:
- <https://www.owasp.org/index.php/Exception_Handling>
- <https://www.owasp.org/index.php/Top_10_2007-Information_Leakage>
Использование безопасного подключения через TLS
-----------------------------------------------
Yii предоставляет функции, которые зависят от куки-файлов и/или сессий PHP. Они могут быть уязвимыми, если Ваше соединение
скомпрометированно. Риск снижается, если приложение использует безопасное соединение через TLS (часто называемое как [SSL](https://en.wikipedia.org/wiki/Transport_Layer_Security)).
Инструкции по настройке смотрите в документации к Вашему веб-серверу. Вы также можете проверить примеры конфигураций
предоставленные проектом H5BP:
- [Nginx](https://github.com/h5bp/server-configs-nginx)
- [Apache](https://github.com/h5bp/server-configs-apache).
- [IIS](https://github.com/h5bp/server-configs-iis).
- [Lighttpd](https://github.com/h5bp/server-configs-lighttpd).
Безопасная конфигурация сервера
-------------------------------
Цель этого раздела - выявить риски, которые необходимо учитывать при создании
конфигурации сервера для обслуживания веб-сайта на основе Yii. Помимо перечисленных здесь пунктов есть и
другие параметры, связанные с безопасностью, которые необходимо учитывать, поэтому не рассматривайте этот раздел как завершенный.
### Как избежать атаки типа `Host`-header
Классы типа [[yii\web\UrlManager]] и [[yii\helpers\Url]] могут использовать [[yii\web\Request::getHostInfo()|запрашиваемое имя хоста]]] для генерации ссылок. Если веб-сервер настроен на обслуживание одного и того же сайта независимо от значения заголовка `Host`, эта информация может быть ненадежной и может быть подделана пользователем, отправляющим HTTP-запрос. В таких ситуациях Вы должны либо исправить конфигурацию своего веб-сервера, чтобы обслуживать сайт только для указанных имен узлов, либо явно установить или отфильтровать значение, установив свойство [[yii\web\Request::setHostInfo()|hostInfo]] компонента приложения `request`.
Дополнительные сведения о конфигурации сервера смотрите в документации Вашего веб-сервера:
- Apache 2: <http://httpd.apache.org/docs/trunk/vhosts/examples.html#defaultallports>
- Nginx: <https://www.nginx.com/resources/wiki/start/topics/examples/server_blocks/>
Если у Вас нет доступа к конфигурации сервера, Вы можете настроить фильтр [[yii\filters\HostControl]] уровня приложения для защиты от такого рода атак:
```php
// Файл конфигурации веб-приложения
return [
'as hostControl' => [
'class' => 'yii\filters\HostControl',
'allowedHosts' => [
'example.com',
'*.example.com',
],
'fallbackHostInfo' => 'https://example.com',
],
// ...
];
```
> Note: Вы всегда должны предпочесть конфигурацию веб-сервера для защиты от `атак заголовков узла` вместо использования фильтра.
[[yii\filters\HostControl]] следует использовать, только если настройка конфигурации сервера недоступна.

4
docs/guide-ru/start-installation.md

@ -176,7 +176,7 @@ DocumentRoot "path/to/basic/web"
PHP должен быть установлен как [FPM SAPI](http://php.net/manual/ru/install.fpm.php) для [Nginx](http://wiki.nginx.org/).
Используйте следующие параметры Nginx и не забудьте заменить `path/to/basic/web` на корректный путь к `basic/web` и
`mysite.local` на ваше имя хоста.
`mysite.test` на ваше имя хоста.
```
server {
@ -186,7 +186,7 @@ server {
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## слушаем ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

2
docs/guide-ru/structure-filters.md

@ -87,7 +87,7 @@ class ActionTimeFilter extends ActionFilter
public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::trace("Action '{$action->uniqueId}' spent $time second.");
Yii::debug("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}

7
docs/guide-ru/structure-modules.md

@ -171,6 +171,13 @@ yii <module_id>/<command>/<sub_command>
из идентификатора модуля, то контроллер и действие определяются исходя из свойства [[yii\base\Module::defaultRoute]],
которое по умолчанию равно `default`. Таким образом, маршрут `forum` соответствует контроллеру `default` модуля `forum`.
Добавление маршрутов модуля в URL manager необходимо производить до начала работы [[yii\web\UrlManager::parseRequest()]], что не
позволяет размещать код добавления правил модуля в `init()`, так как инициализация происходит уже после обработки маршрутов. Таким образом, добавление маршрутов необходимо осуществить в [предзагрузке
модуля](structure-extensions.md#bootstrapping-classes). Хорошей практикой, также, будет объединение всех правил модуля
при помощи [[\yii\web\GroupUrlRule]].
Если же вы используете модуль для [версионирования API](rest-versioning.md), добавление маршрутов необходимо
производить непосредственно в конфигурации `urlManager` приложения.
### Получение доступа к модулям <span id="accessing-modules"></span>

9
docs/guide-ru/test-acceptance.md

@ -1,11 +1,16 @@
Приёмочное тестирование
=======================
> Note: Данный раздел находится в разработке.
Приемочный тест проверяет сценарий с точки зрения конечного пользователя. К тестируемому приложению получают доступ либо через PhpBrowser, либо через реальный браузер. В обоих случаях браузеры взаимодействуют с приложением через HTTP, поэтому приложение следует запускать посредством веб-сервера.
Приемочное тестирование реализуется с помощью фреймворка Codeception, который имеет отличную документацию:
- [Codeception for Yii framework](http://codeception.com/for/yii)
- [Codeception Acceptance Tests](http://codeception.com/docs/03-AcceptanceTests)
Запуск тестов в шаблонах проектов basic и advanced
--------------------------------------------------
Инструкции приведены в `apps/advanced/tests/README.md` и `apps/basic/tests/README.md`.
Если вы начали с шаблона advanced, пожалуйста, обратитесь к руководству по ["Тестированию"](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/start-testing.md) для получения более детальной информации о запускаемых тестах.
Если вы начали с шаблона basic, обратитесь к разделу ["Тестирование"](https://github.com/yiisoft/yii2-app-basic/blob/master/README.md#testing) в его README.

1
docs/guide-ru/translators.json

@ -49,5 +49,6 @@
"LAV45",
"Maksim Pestov",
"PendalF89",
"Max Alexandrov",
"and others"
]

2
docs/guide-ru/tutorial-i18n.md

@ -269,7 +269,7 @@ for an argument: U_ARGUMENT_TYPE_MISMATCH":
```
Подробная документация о формах склонений для различных языков доступна на сайте
[unicode.org](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html).
[unicode.org](http://cldr.unicode.org/index/cldr-spec/plural-rules).
#### Вариации

206
docs/guide-ru/tutorial-yii-as-micro-framework.md

@ -0,0 +1,206 @@
# Использование Yii в качестве микро-framework'а
Yii можно легко использовать без функций включенных в базовый и расширенный шаблоны приложений. Другими словами Yii уже является микро-каркасом. Не требуется иметь структуру каталогов предоставляемую этими шаблонами при работе с Yii.
Это особенно удобно, когда Вам не нужен весь пред-установленный шаблонный код, такой как `Assets` или `Views`. Одним из таких случаев является создание JSON API. В следующих разделах будет показано, как это сделать.
## Установка Yii
Создайте каталог для файлов проекта и смените рабочий каталог на этот путь. В примерах используются команды Unix, но аналогичные команды существуют и в Windows.
```bash
mkdir micro-app
cd micro-app
```
> Note: Для продолжения требуется немного знаний о Composer. Если Вы еще не знаете, как использовать Composer, пожалуйста, найдите время, чтобы прочитать [Руководство Composer](https://getcomposer.org/doc/00-intro.md).
Создайте файл `composer.json` в каталоге `micro-app` с помощью Вашего любимого редактора и добавьте следующее:
```json
{
"require": {
"yiisoft/yii2": "~2.0.0"
},
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
]
}
```
Сохраните файл и запустите команду `comper install`. Это установит framework со всеми его зависимостями.
## Создание структуры проекта
После того как Вы установили фреймворк, пришло время создать [входную точку](structure-entry-scripts.md) приложения. Точка входа - это самый первый файл, который будет выполнен при попытке открыть приложение. По соображениям безопасности рекомендуется поместить файл точки входа в отдельный каталог и сделать каталог корнем веб директории.
Создайте каталог `web` и поместите в него файл `index.php` со следующим содержимым:
```php
<?php
// закомментируйте следующие две строки при использовании в рабочем режиме
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
$config = require __DIR__ . '/../config.php';
(new yii\web\Application($config))->run();
```
Также создайте файл с именем `config.php`, который будет содержать всю конфигурацию приложения:
```php
<?php
return [
'id' => 'micro-app',
// basePath (базовый путь) приложения будет каталог `micro-app`
'basePath' => __DIR__,
// это пространство имен где приложение будет искать все контроллеры
'controllerNamespace' => 'micro\controllers',
// установим псевдоним '@micro', чтобы включить автозагрузку классов из пространства имен 'micro'
'aliases' => [
'@micro' => __DIR__,
],
];
```
> Info: Несмотря на то, что конфигурация приложения может находиться в файле `index.php` рекомендуется
> содержать её в отдельном файле. Таким образом её можно также использовать и для консольного приложения, как показано ниже.
Теперь Ваш проект готов к наполнению кодом. Вам решать какую структуру каталогов проекта Вы выберите, пока Вы сможете видеть пространства имен.
## Создание первого контроллера
Создайте каталог `controllers` и добавьте туда файл `SiteController.php` который является контроллером по умолчанию, он будет обрабатывать запрос без пути.
```php
<?php
namespace micro\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public function actionIndex()
{
return 'Hello World!';
}
}
```
Если Вы хотите использовать другое имя для этого контроллера, Вы можете изменить его настроив [[yii\base\Application::$defaultRoute]].
Например для `DefaultController` будет соответственно `'defaultRoute' => 'default/index'`.
На данный момент структура проекта должна выглядеть так:
```
micro-app/
├── composer.json
├── web/
└── index.php
└── controllers/
└── SiteController.php
```
Если Вы еще не настроили веб-сервер, Вы можете взглянуть на [примеры конфигурационных файлов веб-серверов](start-installation.md#Настройка-веб-сервера-).
Другой возможностью является использование команды `yii serve` которая будет использовать встроенный веб-сервер PHP. Вы можете запустить её из каталога `micro-app/` через:
vendor/bin/yii serve --docroot=./web
При открытии URL приложения в браузере, он теперь должен печатать "Hello World!" который был возвращен из `SiteController::actionIndex()`.
> Info: В нашем примере мы изменили пространство имен по умолчанию приложения с `app` на` micro`, чтобы продемонстрировать
> что Вы не привязаны к этому имени (в случае, если Вы считали, что это так), а затем скорректировали
> [[yii\base\Application::$controllerNamespace|controllers namespace]] и установили правильный псевдоним.
## Создание REST API
Чтобы продемонстрировать использование нашей "микроархитектуры" мы создадим простой REST API для сообщений.
Чтобы этот API обслуживал некоторые данные, нам нужна база данных. Добавим конфигурацию подключения базы данных
к конфигурации приложения:
```php
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'sqlite:@micro/database.sqlite',
],
],
```
> Info: Для простоты мы используем базу данных sqlite. Дополнительную информацию см. в [Руководство по базам данных](db-dao.md).
Затем мы создаем [миграции базы данных](db-migrations.md) для создания таблицы сообщений.
Убедитесь, что у Вас есть отдельный файл конфигурации, как описано выше, нам это нужно для того, чтобы запустить консольные команды описанные ниже.
Запуск следующих команд создаст файл миграции базы данных и применит миграцию к базе данных:
vendor/bin/yii migrate/create --appconfig=config.php create_post_table --fields="title:string,body:text"
vendor/bin/yii migrate/up --appconfig=config.php
Создайте каталог `models` и файл` Post.php` в этом каталоге. Это код модели:
```php
<?php
namespace micro\models;
use yii\db\ActiveRecord;
class Post extends ActiveRecord
{
public static function tableName()
{
return '{{posts}}';
}
}
```
> Info: Созданная модель представляет собой класс ActiveRecord, который представляет данные из таблицы `posts`.
> Для получения дополнительной информации обратитесь к [active record руководству](db-active-record.md).
Чтобы обслуживать сообщения в нашем API, добавьте `PostController` в` controllers`:
```php
<?php
namespace micro\controllers;
use yii\rest\ActiveController;
class PostController extends ActiveController
{
public $modelClass = 'micro\models\Post';
public function behaviors()
{
// удаляем rateLimiter, требуется для аутентификации пользователя
$behaviors = parent::behaviors();
unset($behaviors['rateLimiter']);
return $behaviors;
}
}
```
На этом этапе наш API предоставляет следующие URL-адреса:
- `/index.php?r=post` - список всех сообщений
- `/index.php?r=post/view&id=1` - просмотр сообщения с ID 1
- `/index.php?r=post/create` - создание сообщения
- `/index.php?r=post/update&id=1` - обновление сообщения with ID 1
- `/index.php?r=post/delete&id=1` - удаление сообщения with ID 1
Начиная с этого момента Вы можете посмотреть следующие руководства для дальнейшего развития своего приложения:
- API в настоящий момент понимает только данные urlencoded как входные данные, чтобы сделать его настоящим JSON API, Вам
необходимо настроить [[yii\web\JsonParser]].
- Чтобы сделать URL более дружественным, вам необходимо настроить маршрутизацию.
См. [Руководство по маршрутизации REST](rest-routing.md) о том, как это сделать.
- Дополнительную информацию см. в разделе [Взгляд в будущее](start-looking-ahead.md).

4
docs/guide-uk/start-installation.md

@ -193,7 +193,7 @@ DocumentRoot "path/to/basic/web"
Для використання [Nginx](http://wiki.nginx.org/) вам потрібно встановити PHP як [FPM SAPI](http://php.net/install.fpm).
Використовуйте наступні параметри Nginx, замінивши `path/to/basic/web` на коректний шлях до
`basic/web`, а `mysite.local` на актуальний домен.
`basic/web`, а `mysite.test` на актуальний домен.
```
server {
@ -203,7 +203,7 @@ server {
listen 80; ## "слухаємо порт" для ipv4
#listen [::]:80 default_server ipv6only=on; ## "слухаємо порт" для ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

4
docs/guide-vi/start-installation.md

@ -163,7 +163,7 @@ DocumentRoot "path/to/basic/web"
Để sử dụng [Nginx](http://wiki.nginx.org/), bạn cần phải cài đặt [FPM SAPI](http://php.net/install.fpm).
Bạn có thể cấu hình Nginx như sau, thay thế đường dẫn `path/to/basic/web` với đường dẫn thực tế ở
`basic/web``mysite.local` thay thế bằng tên máy chủ thực tế để cung cấp dịch vụ.
`basic/web``mysite.test` thay thế bằng tên máy chủ thực tế để cung cấp dịch vụ.
```
server {
@ -173,7 +173,7 @@ server {
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

4
docs/guide-zh-CN/caching-data.md

@ -74,8 +74,8 @@ Yii 支持一系列缓存存储器,概况如下:
* [[yii\caching\MemCache]]:使用 PHP [memcache](http://php.net/manual/en/book.memcache.php) 和 [memcached](http://php.net/manual/en/book.memcached.php) 扩展。这个选项被看作分布式应用环境中(例如:多台服务器,有负载均衡等)最快的缓存方案。
* [[yii\redis\Cache]]:实现了一个基于 [Redis](http://redis.io/) 键值对存储器的缓存组件(需要 redis 2.6.12 及以上版本的支持 )。
* [[yii\caching\WinCache]]:使用 PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)([另可参考](http://php.net/manual/en/book.wincache.php))扩展.
* [[yii\caching\XCache]]:使用 PHP [XCache](http://xcache.lighttpd.net/)扩展。
* [[yii\caching\ZendDataCache]]:使用 [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) 作为底层缓存媒介。
* [[yii\caching\XCache]] _(deprecated)_:使用 PHP [XCache](http://xcache.lighttpd.net/)扩展。
* [[yii\caching\ZendDataCache]] _(deprecated)_:使用 [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) 作为底层缓存媒介。
> Tip: 你可以在同一个应用程序中使用不同的缓存存储器。一个常见的策略是使用基于内存的缓存存储器存储小而常用的数据(例如:统计数据),使用基于文件或数据库的缓存存储器存储大而不太常用的数据(例如:网页内容)。

2
docs/guide-zh-CN/concept-di-container.md

@ -69,7 +69,7 @@ $container->get('Foo', [], [
这种情况下,容器将使用一个注册过的 PHP 回调创建一个类的新实例。回调负责解决依赖并将其恰当地注入新创建的对象。例如:
```php
$container->set('Foo', function () {
$container->set('Foo', function ($container, $params, $config) {
return new Foo(new Bar);
});

2
docs/guide-zh-CN/concept-events.md

@ -182,7 +182,7 @@ use yii\base\Event;
use yii\db\ActiveRecord;
Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
Yii::trace(get_class($event->sender) . ' is inserted');
Yii::debug(get_class($event->sender) . ' is inserted');
});
```

4
docs/guide-zh-CN/start-installation.md

@ -132,7 +132,7 @@ DocumentRoot "path/to/basic/web"
### 推荐使用的 Nginx 配置 <span id="recommended-nginx-configuration"></span>
为了使用 [Nginx](http://wiki.nginx.org/),你应该已经将 PHP 安装为 [FPM SAPI](http://php.net/install.fpm) 了。使用如下 Nginx 配置,将 `path/to/basic/web` 替换为实际的 `basic/web` 目录,`mysite.local` 替换为实际的主机名以提供服务。
为了使用 [Nginx](http://wiki.nginx.org/),你应该已经将 PHP 安装为 [FPM SAPI](http://php.net/install.fpm) 了。使用如下 Nginx 配置,将 `path/to/basic/web` 替换为实际的 `basic/web` 目录,`mysite.test` 替换为实际的主机名以提供服务。
```
server {
@ -142,7 +142,7 @@ server {
listen 80; ## 监听 ipv4 上的 80 端口
#listen [::]:80 default_server ipv6only=on; ## 监听 ipv6 上的 80 端口
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

2
docs/guide-zh-CN/structure-filters.md

@ -84,7 +84,7 @@ class ActionTimeFilter extends ActionFilter
public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::trace("Action '{$action->uniqueId}' spent $time second.");
Yii::debug("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}

13
docs/guide/README.md

@ -18,6 +18,7 @@ Introduction
Getting Started
---------------
* [What do you need to know](start-prerequisites.md)
* [Installing Yii](start-installation.md)
* [Running Applications](start-workflow.md)
* [Saying Hello](start-hello.md)
@ -30,7 +31,7 @@ Getting Started
Application Structure
---------------------
* [Overview](structure-overview.md)
* [Application Structure Overview](structure-overview.md)
* [Entry Scripts](structure-entry-scripts.md)
* [Applications](structure-applications.md)
* [Application Components](structure-application-components.md)
@ -47,7 +48,7 @@ Application Structure
Handling Requests
-----------------
* [Overview](runtime-overview.md)
* [Request Handling Overview](runtime-overview.md)
* [Bootstrapping](runtime-bootstrapping.md)
* [Routing and URL Creation](runtime-routing.md)
* [Requests](runtime-requests.md)
@ -110,7 +111,7 @@ Displaying Data
Security
--------
* [Overview](security-overview.md)
* [Security Overview](security-overview.md)
* [Authentication](security-authentication.md)
* [Authorization](security-authorization.md)
* [Working with Passwords](security-passwords.md)
@ -122,7 +123,7 @@ Security
Caching
-------
* [Overview](caching-overview.md)
* [Caching Overview](caching-overview.md)
* [Data Caching](caching-data.md)
* [Fragment Caching](caching-fragment.md)
* [Page Caching](caching-page.md)
@ -154,7 +155,7 @@ Development Tools
Testing
-------
* [Overview](test-overview.md)
* [Testing Overview](test-overview.md)
* [Testing environment setup](test-environment-setup.md)
* [Unit Tests](test-unit.md)
* [Functional Tests](test-functional.md)
@ -196,7 +197,7 @@ Widgets
Helpers
-------
* [Overview](helper-overview.md)
* [Helpers Overview](helper-overview.md)
* [ArrayHelper](helper-array.md)
* [Html](helper-html.md)
* [Url](helper-url.md)

4
docs/guide/caching-data.md

@ -125,8 +125,8 @@ Yii supports a wide range of cache storage. The following is a summary:
(redis version 2.6.12 or higher is required).
* [[yii\caching\WinCache]]: uses PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)
([see also](http://php.net/manual/en/book.wincache.php)) extension.
* [[yii\caching\XCache]]: uses PHP [XCache](http://xcache.lighttpd.net/) extension.
* [[yii\caching\ZendDataCache]]: uses
* [[yii\caching\XCache]] _(deprecated)_: uses PHP [XCache](http://xcache.lighttpd.net/) extension.
* [[yii\caching\ZendDataCache]] _(deprecated)_: uses
[Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm)
as the underlying caching medium.

3
docs/guide/caching-fragment.md

@ -174,3 +174,6 @@ if ($this->beginCache($id1)) {
The [[yii\base\View::renderDynamic()|renderDynamic()]] method takes a piece of PHP code as its parameter.
The return value of the PHP code is treated as the dynamic content. The same PHP code will be executed
for every request, no matter the enclosing fragment is being served from cached or not.
> Note: since version 2.0.14 a dynamic content API is exposed via the [[yii\base\DynamicContentAwareInterface]] interface and its [[yii\base\DynamicContentAwareTrait]] trait.
As an example, you may refer to the [[yii\widgets\FragmentCache]] class.

3
docs/guide/concept-aliases.md

@ -19,6 +19,9 @@ Yii::setAlias('@foo', '/path/to/foo');
// an alias of a URL
Yii::setAlias('@bar', 'http://www.example.com');
// an alias of a concrete file that contains a \foo\Bar class
Yii::setAlias('@foo/Bar.php', '/definitely/not/foo/Bar.php');
```
> Note: The file path or URL being aliased may *not* necessarily refer to an existing file or resource.

8
docs/guide/concept-di-container.md

@ -117,7 +117,7 @@ The callable is responsible to resolve the dependencies and inject them appropri
created objects. For example,
```php
$container->set('Foo', function () {
$container->set('Foo', function ($container, $params, $config) {
$foo = new Foo(new Bar);
// ... other initializations ...
return $foo;
@ -131,7 +131,7 @@ To hide the complex logic for building a new object, you may use a static class
```php
class FooBuilder
{
public static function build()
public static function build($container, $params, $config)
{
$foo = new Foo(new Bar);
// ... other initializations ...
@ -421,13 +421,13 @@ $container->setDefinitions([
'class' => 'app\components\Response',
'format' => 'json'
],
'app\storage\DocumentsReader' => function () {
'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);
$reader = $container->get('app\storage\DocumentsReader');
// Will create DocumentReader object with its dependencies as described in the config
```

77
docs/guide/concept-events.md

@ -42,7 +42,7 @@ Attaching Event Handlers <span id="attaching-event-handlers"></span>
You can attach a handler to an event by calling the [[yii\base\Component::on()]] method. For example:
```php
$foo = new Foo;
$foo = new Foo();
// this handler is a global function
$foo->on(Foo::EVENT_HELLO, 'function_name');
@ -212,7 +212,7 @@ use yii\base\Event;
use yii\db\ActiveRecord;
Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
Yii::trace(get_class($event->sender) . ' is inserted');
Yii::debug(get_class($event->sender) . ' is inserted');
});
```
@ -296,7 +296,7 @@ pass the interface class name as the first argument:
```php
Event::on('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) {
Yii::trace(get_class($event->sender) . ' just danced'); // Will log that Dog or Developer danced
Yii::debug(get_class($event->sender) . ' just danced'); // Will log that Dog or Developer danced
});
```
@ -355,3 +355,74 @@ done through the Singleton (e.g. the application instance).
However, because the namespace of the global events is shared by all parties, you should name the global events
wisely, such as introducing some sort of namespace (e.g. "frontend.mail.sent", "backend.mail.sent").
Wildcard Events <span id="wildcard-events"></span>
---------------
Since 2.0.14 you can setup event handler for multiple events matching wildcard pattern.
For example:
```php
use Yii;
$foo = new Foo();
$foo->on('foo.event.*', function ($event) {
// triggered for any event, which name starts on 'foo.event.'
Yii::debug('trigger event: ' . $event->name);
});
```
Wildcard patterns can be used for class-level events as well. For example:
```php
use yii\base\Event;
use Yii;
Event::on('app\models\*', 'before*', function ($event) {
// triggered for any class in namespace 'app\models' for any event, which name starts on 'before'
Yii::debug('trigger event: ' . $event->name . ' for class: ' . get_class($event->sender));
});
```
This allows you catching all application events by single handler using following code:
```php
use yii\base\Event;
use Yii;
Event::on('*', '*', function ($event) {
// triggered for any event at any class
Yii::debug('trigger event: ' . $event->name);
});
```
> Note: usage wildcards for event handlers setup may reduce the application performance.
It is better to be avoided if possible.
In order to detach event handler specified by wildcard pattern, you should repeat same pattern at
[[yii\base\Component::off()]] or [[yii\base\Event::off()]] invocation. Keep in mind that passing wildcard
during detaching of event handler will detach ony the handler specified for this wildcard, while handlers
attached for regular event names will remain even if they match the pattern. For example:
```php
use Yii;
$foo = new Foo();
// attach regular handler
$foo->on('event.hello', function ($event) {
echo 'direct-handler'
});
// attach wildcard handler
$foo->on('*', function ($event) {
echo 'wildcard-handler'
});
// detach wildcard handler only!
$foo->off('*');
$foo->trigger('event.hello'); // outputs: 'direct-handler'
```

63
docs/guide/db-active-record.md

@ -472,7 +472,7 @@ $customer->loadDefaultValues();
### Attributes Typecasting <span id="attributes-typecasting"></span>
Being populated by query results [[yii\db\ActiveRecord]] performs automatic typecast for its attribute values, using
Being populated by query results, [[yii\db\ActiveRecord]] performs automatic typecast for its attribute values, using
information from [database table schema](db-dao.md#database-schema). This allows data retrieved from table column
declared as integer to be populated in ActiveRecord instance with PHP integer, boolean with boolean and so on.
However, typecasting mechanism has several limitations:
@ -490,7 +490,33 @@ converted during saving process.
> Tip: you may use [[yii\behaviors\AttributeTypecastBehavior]] to facilitate attribute values typecasting
on ActiveRecord validation or saving.
Since 2.0.14, Yii ActiveRecord supports complex data types, such as JSON or multidimensional arrays.
#### JSON in MySQL and PostgreSQL
After data population, the value from JSON column will be automatically decoded from JSON according to standard JSON
decoding rules.
To save attribute value to a JSON column, ActiveRecord will automatically create a [[yii\db\JsonExpression|JsonExpression]] object
that will be encoded to a JSON string on [QueryBuilder](db-query-builder.md) level.
#### Arrays in PostgreSQL
After data population, the value from Array column will be automatically decoded from PgSQL notation to an [[yii\db\ArrayExpression|ArrayExpression]]
object. It implements PHP `ArrayAccess` interface, so you can use it as an array, or call `->getValue()` to get the array itself.
To save attribute value to an array column, ActiveRecord will automatically create an [[yii\db\ArrayExpression|ArrayExpression]] object
that will be encoded by [QueryBuilder](db-query-builder.md) to an PgSQL string representation of array.
You can also use conditions for JSON columns:
```php
$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])
```
To learn more about expressions building system read the [Query Builder – Adding custom Conditions and Expressions](db-query-builder.md#adding-custom-conditions-and-expressions)
article.
### Updating Multiple Rows <span id="updating-multiple-rows"></span>
@ -936,6 +962,41 @@ $items = $order->items;
```
### Chaining relation definitions via multiple tables <span id="multi-table-relations"></span>
Its further possible to define relations via multiple tables by chaining relation definitions using [[yii\db\ActiveQuery::via()|via()]].
Considering the examples above, we have classes `Customer`, `Order`, and `Item`.
We can add a relation to the `Customer` class that lists all items from all the orders they placed,
and name it `getPurchasedItems()`, the chaining of relations is show in the following code example:
```php
class Customer extends ActiveRecord
{
// ...
public function getPurchasedItems()
{
// customer's items, matching 'id' column of `Item` to 'item_id' in OrderItem
return $this->hasMany(Item::className(), ['id' => 'item_id'])
->via('orderItems');
}
public function getOrderItems()
{
// customer's order items, matching 'id' column of `Order` to 'order_id' in OrderItem
return $this->hasMany(OrderItem::className(), ['order_id' => 'id'])
->via('orders');
}
public function getOrders()
{
// same as above
return $this->hasMany(Order::className(), ['customer_id' => 'id']);
}
}
```
### Lazy Loading and Eager Loading <span id="lazy-eager-loading"></span>
In [Accessing Relational Data](#accessing-relational-data), we explained that you can access a relation property

37
docs/guide/db-migrations.md

@ -38,6 +38,13 @@ command `yii help migrate`.
> Tip: migrations could affect not only database schema but adjust existing data to fit new schema, create RBAC
hierarchy or clean up cache.
> Note: When manipulating data using a migration you may find that using your [Active Record](db-active-record.md) classes
> for this might be useful because some of the logic is already implemented there. Keep in mind however, that in contrast
> to code written in the migrations, who's nature is to stay constant forever, application logic is subject to change.
> So when using Active Record in migration code, changes to the logic in the Active Record layer may accidentally break
> existing migrations. For this reason migration code should be kept independent from other application logic such
> as Active Record classes.
## Creating Migrations <span id="creating-migrations"></span>
@ -204,7 +211,7 @@ generates
class m150811_220037_create_post_table extends Migration
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function up()
{
@ -214,7 +221,7 @@ class m150811_220037_create_post_table extends Migration
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function down()
{
@ -238,7 +245,7 @@ generates
class m150811_220037_create_post_table extends Migration
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function up()
{
@ -250,7 +257,7 @@ class m150811_220037_create_post_table extends Migration
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function down()
{
@ -275,7 +282,7 @@ generates
class m150811_220037_create_post_table extends Migration
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function up()
{
@ -287,7 +294,7 @@ class m150811_220037_create_post_table extends Migration
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function down()
{
@ -320,7 +327,7 @@ generates
class m160328_040430_create_post_table extends Migration
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function up()
{
@ -368,7 +375,7 @@ class m160328_040430_create_post_table extends Migration
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function down()
{
@ -533,7 +540,7 @@ generates
class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migration
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function up()
{
@ -580,7 +587,7 @@ class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migra
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function down()
{
@ -716,14 +723,6 @@ Below is the list of all these database accessing methods:
> ```
> Note: When manipulating data using a migration you may find that using your [Active Record](db-active-record.md) classes
> for this might be useful because some of the logic is already implemented there. Keep in mind however, that in contrast
> to code written in the migrations, who's nature is to stay constant forever, application logic is subject to change.
> So when using Active Record in migration code, changes to the logic in the Active Record layer may accidentally break
> existing migrations. For this reason migration code should be kept independent from other application logic such
> as Active Record classes.
## Applying Migrations <span id="applying-migrations"></span>
To upgrade a database to its latest structure, you should apply all available new migrations using the following command:
@ -799,7 +798,7 @@ yii migrate/redo 3 # redo the last 3 applied migrations
## Refreshing Migrations <span id="refreshing-migrations"></span>
Since Yii 2.0.13 you can reset the whole database and apply all migrations from the beginning.
Since Yii 2.0.13 you can delete all tables and foreign keys from the database and apply all migrations from the beginning.
```
yii migrate/fresh # Truncate the database and apply all migrations from the beginning.

211
docs/guide/db-query-builder.md

@ -160,12 +160,12 @@ are in the ["Quoting Tables" section of the "Database Access Objects" guide](gui
### [[yii\db\Query::where()|where()]] <span id="where"></span>
The [[yii\db\Query::where()|where()]] method specifies the `WHERE` fragment of a SQL query. You can use one of
the three formats to specify a `WHERE` condition:
the four formats to specify a `WHERE` condition:
- string format, e.g., `'status=1'`
- hash format, e.g. `['status' => 1, 'type' => 2]`
- operator format, e.g. `['like', 'name', 'test']`
- object format, e.g. `new LikeCondition('name', 'LIKE', 'test')`
#### String Format <span id="string-format"></span>
@ -250,9 +250,14 @@ the operator can be one of the following:
- `or`: similar to the `and` operator except that the operands are concatenated using `OR`.
- `not`: requires only operand 1, which will be wrapped in `NOT()`. For example, `['not', 'id=1']` will generate `NOT (id=1)`. Operand 1 may also be an array to describe multiple expressions. For example `['not', ['status' => 'draft', 'name' => 'example']]` will generate `NOT ((status='draft') AND (name='example'))`.
- `between`: operand 1 should be the column name, and operand 2 and 3 should be the
starting and ending values of the range that the column is in.
For example, `['between', 'id', 1, 10]` will generate `id BETWEEN 1 AND 10`.
In case you need to build a condition where value is between two columns (like `11 BETWEEN min_id AND max_id`),
you should use [[yii\db\conditions\BetweenColumnsCondition|BetweenColumnsCondition]].
See [Conditions – Object Format](#object-format) chapter to learn more about object definition of conditions.
- `not between`: similar to `between` except the `BETWEEN` is replaced with `NOT BETWEEN`
in the generated condition.
@ -304,6 +309,41 @@ the operator can be one of the following:
Using the Operator Format, Yii internally uses parameter binding so in contrast to the [string format](#string-format), here
you do not have to add parameters manually.
#### Object Format <span id="object-format"></span>
Object Form is available since 2.0.14 and is both most powerful and most complex way to define conditions.
You need to follow it either if you want to build your own abstraction over query builder or if you want to implement
your own complex conditions.
Instances of condition classes are immutable. Their only purpose is to store condition data and provide getters
for condition builders. Condition builder is a class that holds the logic that transforms data
stored in condition into the SQL expression.
Internally the formats described above are implicitly converted to object format prior to building raw SQL,
so it is possible to combine formats in a single condition:
```php
$query->andWhere(new OrCondition([
new InCondition('type', 'in', $types),
['like', 'name', '%good%'],
'disabled=false'
]))
```
Conversion from operator format into object format is performed according to
[[yii\db\QueryBuilder::conditionClasses|QueryBuilder::conditionClasses]] property, that maps operators names
to representative class names:
- `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`
And so on.
Using the object format makes it possible to create your own conditions or to change the way default ones are built.
See [Creating Custom Conditions and Expressions](#creating-custom-conditions-and-expressions) chapter to learn more.
#### Appending Conditions <span id="appending-conditions"></span>
@ -756,3 +796,170 @@ $unbufferedDb->close();
```
> Note: unbuffered query uses less memory on the PHP-side, but can increase the load on the MySQL server. It is recommended to design your own code with your production practice for extra massive data, [for example, divide the range for integer keys, loop them with Unbuffered Queries](https://github.com/yiisoft/yii2/issues/8420#issuecomment-296109257).
### Adding custom Conditions and Expressions <span id="adding-custom-conditions-and-expressions"></span>
As it was mentioned in [Conditions – Object Format](#object-format) chapter, is is possible to create custom condition
classes. For example, let's create a condition that will check that specific columns are less than some value.
Using the operator format, it would look like the following:
```php
[
'and',
'>', 'posts', $minLimit,
'>', 'comments', $minLimit,
'>', 'reactions', $minLimit,
'>', 'subscriptions', $minLimit
]
```
When such condition applied once, it is fine. In case it is used multiple times in a single query it can
be optimized a lot. Let's create a custom condition object to demonstrate it.
Yii has a [[yii\db\conditions\ConditionInterface|ConditionInterface]], that must be used to mark classes, that represent
a condition. It requires `fromArrayDefinition()` method implementation, in order to make possible to create condition
from array format. In case you don't need it, you can implement this method with exception throwing.
Since we create our custom condition class, we can build API that suits our task the most.
```php
namespace app\db\conditions;
class AllGreaterCondition implements \yii\db\conditions\ConditionInterface
{
private $columns;
private $value;
/**
* @param string[] $columns Array of columns that must be greater, than $value
* @param mixed $value the value to compare each $column against.
*/
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; }
}
```
So we can create a condition object:
```php
$conditon = new AllGreaterCondition(['col1', 'col2'], 42);
```
But `QueryBuilder` still does not know, to to make an SQL condition out of this object.
Now we need to create a builder for this condition. It must implement [[yii\db\ExpressionBuilderInterface]]
that requires us to implement a `build()` method.
```php
namespace app\db\conditions;
class AllGreaterConditionBuilder implements \yii\db\ExpressionBuilderInterface
{
use \yii\db\Condition\ExpressionBuilderTrait; // Contains constructor and `queryBuilder` property.
/**
* @param AllGreaterCondition $condition the condition to be built
* @param array $params the binding parameters.
*/
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);
}
}
```
Then simple let [[yii\db\QueryBuilder|QueryBuilder]] know about our new condition – add a mapping for it to
the `expressionBuilders` array. It could be done right from the application configuration:
```php
'db' => [
'class' => 'yii\db\mysql\Connection',
// ...
'queryBuilder' => [
'expressionBuilders' => [
'app\db\conditions\AllGreaterCondition' => 'app\db\conditions\AllGreaterConditionBuilder',
],
],
],
```
Now we can use our condition in `where()`:
```php
$query->andWhere(new AllGreaterCondition(['posts', 'comments', 'reactions', 'subscriptions'], $minValue));
```
If we want to make it possible to create our custom condition using operator format, we should declare it in
[[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',
],
],
],
```
And create a real implementation of `AllGreaterCondition::fromArrayDefinition()` method
in `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]);
}
}
```
After that, we can create our custom condition using shorter operator format:
```php
$query->andWhere(['ALL>', ['posts', 'comments', 'reactions', 'subscriptions'], $minValue]);
```
You might notice, that there was two concepts used: Expressions and Conditions. There is a [[yii\db\ExpressionInterface]]
that should be used to mark objects, that require an Expression Builder class, that implements
[[yii\db\ExpressionBuilderInterface]] to be built. Also there is a [[yii\db\condition\ConditionInterface]], that extends
[[yii\db\ExpressionInterface|ExpressionInterface]] and should be used to objects, that can be created from array definition
as it was shown above, but require builder as well.
To summarise:
- Expression – is a Data Transfer Object (DTO) for a dataset, that can be somehow compiled to some SQL
statement (an operator, string, array, JSON, etc).
- Condition – is an Expression superset, that aggregates multiple Expressions (or scalar values) that can be compiled
to a single SQL condition.
You can create your own classes that implement [[yii\db\ExpressionInterface|ExpressionInterface]] to hide the complexity
of transforming data to SQL statements. You will learn more about other examples of Expressions in the
[next article](db-active-record.md);

13
docs/guide/input-validation.md

@ -221,7 +221,7 @@ values are stored in an attribute:
```php
['age', 'trim'],
['age', 'default', 'value' => null],
['age', 'integer', 'integerOnly' => true, 'min' => 0],
['age', 'integer', 'min' => 0],
['age', 'filter', 'filter' => 'intval', 'skipOnEmpty' => true],
```
@ -387,8 +387,8 @@ class MyForm extends Model
public function validateCountry($attribute, $params, $validator)
{
if (!in_array($this->$attribute, ['USA', 'Web'])) {
$this->addError($attribute, 'The country must be either "USA" or "Web".');
if (!in_array($this->$attribute, ['USA', 'Indonesia'])) {
$this->addError($attribute, 'The country must be either "USA" or "Indonesia".');
}
}
}
@ -422,7 +422,8 @@ fails the validation, call [[yii\base\Model::addError()]] to save the error mess
with [inline validators](#inline-validators).
For example the inline validator above could be moved into new [[components/validators/CountryValidator]] class.
For example, the inline validator above could be moved into new [[components/validators/CountryValidator]] class.
In this case we can use [[yii\validators\Validator::addError()]] to set customized message for the model.
```php
namespace app\components;
@ -433,8 +434,8 @@ class CountryValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
if (!in_array($model->$attribute, ['USA', 'Web'])) {
$this->addError($model, $attribute, 'The country must be either "USA" or "Web".');
if (!in_array($model->$attribute, ['USA', 'Indonesia'])) {
$this->addError($model, $attribute, 'The country must be either "{country1}" or "{country2}".', ['country1' => 'USA', 'country2' => 'Indonesia']);
}
}
}

2
docs/guide/output-client-scripts.md

@ -183,7 +183,7 @@ $message = \yii\helpers\Json::htmlEncode(
\Yii::t('app', 'Button clicked!')
);
$this->registerJs(<<<JS
$('#myButton').on('click', function() { alert( $message ); });",
$('#myButton').on('click', function() { alert( $message ); });
JS
);
```

70
docs/guide/output-data-providers.md

@ -262,7 +262,7 @@ class CsvDataProvider extends BaseDataProvider
/**
* @inheritdoc
* {@inheritdoc}
*/
public function init()
{
@ -273,7 +273,7 @@ class CsvDataProvider extends BaseDataProvider
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function prepareModels()
{
@ -302,7 +302,7 @@ class CsvDataProvider extends BaseDataProvider
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function prepareKeys($models)
{
@ -318,13 +318,13 @@ class CsvDataProvider extends BaseDataProvider
}
return $keys;
} else {
return array_keys($models);
}
return array_keys($models);
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function prepareTotalCount()
{
@ -339,3 +339,61 @@ class CsvDataProvider extends BaseDataProvider
}
}
```
## Filtering Data Providers using Data Filters <span id="filtering-data-providers-using-data-filters"></span>
While you can build conditions for active data provider manually as described in
[Filtering Data](output-data-widgets.md#filtering-data) and [Separate Filter Form](output-data-widgets.md#separate-filter-form)
sections of data widgets guide, Yii has data filters that are very useful if you need flexible filter condtions.
Data filters could be used as follows:
```php
$filter = new ActiveDataFilter([
'searchModel' => 'app\models\PostSearch'
]);
$filterCondition = null;
// You may load filters from any source. For example,
// if you prefer JSON in request body,
// use Yii::$app->request->getBodyParams() below:
if ($filter->load(\Yii::$app->request->get())) {
$filterCondition = $filter->build();
if ($filterCondition === false) {
// Serializer would get errors out of it
return $filter;
}
}
$query = Post::find();
if ($filterCondition !== null) {
$query->andWhere($filterCondition);
}
return new ActiveDataProvider([
'query' => $query,
]);
```
`PostSearch` model serves the purpose of defining which properties and values are allowed for filtering:
```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],
];
}
}
```
Data filters are quite flexible. You may customize how conditions are built and which operators are allowed.
For details check API docs on [[\yii\data\DataFilter]].

49
docs/guide/output-data-widgets.md

@ -7,7 +7,7 @@ While the [DetailView](#detail-view) widget can be used to display data for a si
providing features like pagination, sorting and filtering.
DetailView <a name="detail-view"></a>
DetailView <span id="detail-view"></span>
----------
The [[yii\widgets\DetailView|DetailView]] widget displays the details of a single data [[yii\widgets\DetailView::$model|model]].
@ -59,7 +59,7 @@ echo DetailView::widget([
]);
```
ListView <a name="list-view"></a>
ListView <span id="list-view"></span>
--------
The [[yii\widgets\ListView|ListView]] widget is used to display data from a [data provider](output-data-providers.md).
@ -124,7 +124,7 @@ echo ListView::widget([
These are then also available as variables in the view.
GridView <a name="grid-view"></a>
GridView <span id="grid-view"></span>
--------
Data grid or [[yii\grid\GridView|GridView]] is one of the most powerful Yii widgets. It is extremely useful if you need to quickly build the admin
@ -155,7 +155,7 @@ The above code first creates a data provider and then uses GridView to display e
the data provider. The displayed table is equipped with sorting and pagination functionality out of the box.
### Grid columns
### Grid columns <span id="grid-columns"></span>
The columns of the grid table are configured in terms of [[yii\grid\Column]] classes, which are
configured in the [[yii\grid\GridView::columns|columns]] property of GridView configuration.
@ -186,7 +186,7 @@ Note that if the [[yii\grid\GridView::columns|columns]] part of the configuratio
Yii tries to show all possible columns of the data provider's model.
### Column classes
### Column classes <span id="column-classes"></span>
Grid columns could be customized by using different column classes:
@ -243,6 +243,13 @@ echo GridView::widget([
'attribute' => 'birthday',
'format' => ['date', 'php:Y-m-d']
],
'created_at:datetime', // shortcut format
[
'label' => 'Education',
'attribute' => 'education',
'filter' => ['0' => 'Elementary', '1' => 'Secondary', '2' => 'Higher'],
'filterInputOptions' => ['prompt' => 'All educations', 'class' => 'form-control', 'id' => null]
],
],
]);
```
@ -256,8 +263,14 @@ For a list of available formatters see the [section about Data Formatting](outpu
For configuring data columns there is also a shortcut format which is described in the
API documentation for [[yii\grid\GridView::columns|columns]].
Use [[yii\grid\DataColumn::filter|filter]] and [[yii\grid\DataColumn::filterInputOptions|filterInputOptions]] to
control HTML for the filter input.
By default, column headers are rendered by [[yii\data\Sort::link]]. It could be adjusted using [[yii\grid\Column::header]].
To change header text you should set [[yii\grid\DataColumn::$label]] like in the example above.
By default the label will be populated from data model. For more details see [[yii\grid\DataColumn::getHeaderCellLabel]].
#### Action column
#### Action column <span id="action-column"></span>
[[yii\grid\ActionColumn|Action column]] displays action buttons such as update or delete for each row.
@ -314,7 +327,7 @@ Available properties you can configure are:
]
```
#### Checkbox column
#### Checkbox column <span id="checkbox-column"></span>
[[yii\grid\CheckboxColumn|Checkbox column]] displays a column of checkboxes.
@ -340,7 +353,7 @@ var keys = $('#grid').yiiGridView('getSelectedRows');
// keys is an array consisting of the keys associated with the selected rows
```
#### Serial column
#### Serial column <span id="serial-column"></span>
[[yii\grid\SerialColumn|Serial column]] renders row numbers starting with `1` and going forward.
@ -355,13 +368,13 @@ echo GridView::widget([
```
### Sorting data
### Sorting data <span id="sorting-data"></span>
> Note: This section is under development.
>
> - https://github.com/yiisoft/yii2/issues/1576
### Filtering data
### Filtering data <span id="filtering-data"></span>
For filtering data, the GridView needs a [model](structure-models.md) that represents the search criteria which is
usually taken from the filter fields in the GridView table.
@ -448,7 +461,7 @@ echo GridView::widget([
]);
```
### Separate filter form
### Separate filter form <span id="separate-filter-form"></span>
Most of the time using GridView header filters is enough, but in case you need a separate filter form,
you can easily add it as well. You can create partial view `_search.php` with the following contents:
@ -526,7 +539,7 @@ And add the representative fields to the filter form:
<?= $form->field($model, 'creationTo') ?>
```
### Working with model relations
### Working with model relations <span id="working-with-model-relations"></span>
When displaying active records in a GridView you might encounter the case where you display values of related
columns such as the post author's name instead of just his `id`.
@ -619,7 +632,7 @@ $query->andFilterWhere(['LIKE', 'author.name', $this->getAttribute('author.name'
> Info: For more information on `joinWith` and the queries performed in the background, check the
> [active record docs on joining with relations](db-active-record.md#joining-with-relations).
#### Using SQL views for filtering, sorting and displaying data
#### Using SQL views for filtering, sorting and displaying data <span id="using-sql-views"></span>
There is also another approach that can be faster and more useful - SQL views. For example, if we need to show the gridview
with users and their profiles, we can do so in this way:
@ -643,7 +656,7 @@ class UserView extends ActiveRecord
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public static function tableName()
{
@ -656,7 +669,7 @@ class UserView extends ActiveRecord
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function rules()
{
@ -666,7 +679,7 @@ class UserView extends ActiveRecord
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function attributeLabels()
{
@ -688,7 +701,7 @@ All attributes will be working out of the box. Note that this approach has sever
`isDeleted` or others that will influence the UI, you will need to duplicate them in this class too.
### Multiple GridViews on one page
### Multiple GridViews on one page <span id="multiple-gridviews"></span>
You can use more than one GridView on a single page but some additional configuration is needed so that
they do not interfere with each other.
@ -721,7 +734,7 @@ echo GridView::widget([
]);
```
### Using GridView with Pjax
### Using GridView with Pjax <span id="using-gridview-with-pjax"></span>
The [[yii\widgets\Pjax|Pjax]] widget allows you to update a certain section of a
page instead of reloading the entire page. You can use it to update only the

7
docs/guide/output-formatting.md

@ -144,12 +144,15 @@ echo Yii::$app->formatter->asTime('2014-10-06 12:41:00'); // 14:41:00
echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00
```
If the [[yii\i18n\Formatter::timeZone|time zone]] is not set explicitly on the formatter component, the
[[yii\base\Application::timeZone|time zone configured in the application]] is used, which is the same time zone
as set in the PHP configuration.
> Note: As time zones are subject to rules made by the governments around the world and may change frequently, it is
> likely that you do not have the latest information in the time zone database installed on your system.
> You may refer to the [ICU manual](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data)
> for details on updating the time zone database. Please also read
> [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment).
> [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment).
## Formatting Numbers <span id="numbers"></span>

8
docs/guide/rest-quick-start.md

@ -8,6 +8,7 @@ In particular, Yii supports the following features about RESTful APIs:
* Response format negotiation (supporting JSON and XML by default);
* Customizable object serialization with support for selectable output fields;
* Proper formatting of collection data and validation errors;
* Collection pagination, filtering and sorting;
* Support for [HATEOAS](http://en.wikipedia.org/wiki/HATEOAS);
* Efficient routing with proper HTTP verb check;
* Built-in support for the `OPTIONS` and `HEAD` verbs;
@ -185,7 +186,12 @@ For example, the URL `http://localhost/users?fields=id,email` will only return t
> Info: You may have noticed that the result of `http://localhost/users` includes some sensitive fields,
> such as `password_hash`, `auth_key`. You certainly do not want these to appear in your API result.
> You can and should filter out these fields as described in the [Resources](rest-resources.md) section.
> You can and should remove these fields from result as described in the [Resources](rest-resources.md) section.
Addionally, you can sort collections like `http://localhost/users?sort=email` or
`http://localhost/users?sort=-email`. Filtering collections like `http://localhost/users?filter[id]=10` or
`http://localhost/users?filter[email][like]=gmail.com` could be implemented using
data filters. See [Resources](rest-resources.md#filtering-collections) section for details.
## Summary <span id="summary"></span>

10
docs/guide/rest-resources.md

@ -244,4 +244,14 @@ will also include the pagination information by the following HTTP headers:
* `X-Pagination-Per-Page`: The number of resources in each page;
* `Link`: A set of navigational links allowing client to traverse the resources page by page.
Since collection in REST APIs is a data provider, it shares all data provider features i.e. pagination and sorting.
An example may be found in the [Quick Start](rest-quick-start.md#trying-it-out) section.
### Filtering collections <span id="filtering-collections"></span>
Since version 2.0.13 Yii provides a facility to filter collections. An example can be found in the
[Quick Start](rest-quick-start.md#trying-it-out) guide. In case you're implementing an endpoint yourself,
filtering could be done as described in
[Filtering Data Providers using Data Filters](output-data-providers.md#filtering-data-providers-using-data-filters)
section of Data Providers guide.

13
docs/guide/runtime-logging.md

@ -18,7 +18,7 @@ In this section, we will mainly describe the first two steps.
Recording log messages is as simple as calling one of the following logging methods:
* [[Yii::trace()]]: record a message to trace how a piece of code runs. This is mainly for development use.
* [[Yii::debug()]]: record a message to trace how a piece of code runs. This is mainly for development use.
* [[Yii::info()]]: record a message that conveys some useful information.
* [[Yii::warning()]]: record a warning message that indicates something unexpected has happened.
* [[Yii::error()]]: record a fatal error that should be investigated as soon as possible.
@ -29,7 +29,7 @@ the log message to be recorded, while `$category` is the category of the log mes
example records a trace message under the default category `application`:
```php
Yii::trace('start calculating average revenue');
Yii::debug('start calculating average revenue');
```
> Info: Log messages can be strings as well as complex data, such as arrays or objects. It is the responsibility
@ -43,7 +43,7 @@ is to use the PHP magic constant `__METHOD__` for the category names. This is al
Yii framework code. For example,
```php
Yii::trace('start calculating average revenue', __METHOD__);
Yii::debug('start calculating average revenue', __METHOD__);
```
The `__METHOD__` constant evaluates as the name of the method (prefixed with the fully qualified class name) where
@ -70,7 +70,8 @@ in the application configuration, like the following:
return [
// the "log" component must be loaded during bootstrapping time
'bootstrap' => ['log'],
// the "log" component process messages with timestamp. Set PHP timezone to create correct timestamp
'timeZone' => 'America/Los_Angeles',
'components' => [
'log' => [
'targets' => [
@ -124,7 +125,7 @@ The [[yii\log\Target::levels|levels]] property takes an array consisting of one
* `error`: corresponding to messages logged by [[Yii::error()]].
* `warning`: corresponding to messages logged by [[Yii::warning()]].
* `info`: corresponding to messages logged by [[Yii::info()]].
* `trace`: corresponding to messages logged by [[Yii::trace()]].
* `trace`: corresponding to messages logged by [[Yii::debug()]].
* `profile`: corresponding to messages logged by [[Yii::beginProfile()]] and [[Yii::endProfile()]], which will
be explained in more details in the [Profiling](#performance-profiling) subsection.
@ -276,7 +277,7 @@ property of individual [log targets](#log-targets), like the following,
]
```
Because of the flushing and exporting level setting, by default when you call `Yii::trace()` or any other logging
Because of the flushing and exporting level setting, by default when you call `Yii::debug()` or any other logging
method, you will NOT see the log message immediately in the log targets. This could be a problem for some long-running
console applications. To make each log message appear immediately in the log targets, you should set both
[[yii\log\Dispatcher::flushInterval|flushInterval]] and [[yii\log\Target::exportInterval|exportInterval]] to be 1,

2
docs/guide/runtime-requests.md

@ -186,7 +186,7 @@ In case your proxies are using different headers you can use the request configu
'X-Forwarded-Proto',
'X-Proxy-User-Ip',
'Front-End-Https',
];'
];
'ipHeaders' => [
'X-Proxy-User-Ip',
],

4
docs/guide/security-authorization.md

@ -225,6 +225,8 @@ return [
'components' => [
'authManager' => [
'class' => 'yii\rbac\DbManager',
// uncomment if you want to cache RBAC items hierarchy
// 'cache' => 'cache',
],
// ...
],
@ -264,7 +266,7 @@ Building authorization data is all about the following tasks:
Depending on authorization flexibility requirements the tasks above could be done in different ways.
If your permissions hierarchy is meant to be changed by developers only, you can use either migrations
or a console command. Migration pro is that it could be executed along with other migrations. Console
command pro is that you have a good overview of the hierarchy in the code rathe than it being scattered
command pro is that you have a good overview of the hierarchy in the code rather than it being scattered
among multiple migrations.
Either way in the end you'll get the following RBAC hierarchy:

2
docs/guide/start-forms.md

@ -59,7 +59,7 @@ of rules for validating the data. The validation rules declared above state that
* the `email` data must be a syntactically valid email address
If you have an `EntryForm` object populated with the data entered by a user, you may call
its [[yii\base\Model::validate()|validate()]] to trigger the data validation routines. A data validation
its [[yii\base\Model::validate()|validate()]] method to trigger the data validation routines. A data validation
failure will set the [[yii\base\Model::hasErrors|hasErrors]] property to `true`, and you may learn what validation
errors occurred through [[yii\base\Model::getErrors|errors]].

31
docs/guide/start-installation.md

@ -111,6 +111,30 @@ But there are other installation options available:
you may consider installing the [Advanced Project Template](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/README.md).
Installing Assets <span id="installing-assets"></span>
-----------------
Yii relies on [Bower](http://bower.io/) and/or [NPM](https://www.npmjs.org/) packages for the asset (CSS and JavaScript) libraries installation.
It uses Composer to obtain these libraries, allowing PHP and CSS/JavaScript package versions to resolve at the same time.
This can be achieved either by usage of [asset-packagist.org](https://asset-packagist.org) or [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/).
Please refer to [Assets documentation](structure-assets.md) for more details.
You may want to either manage your assets via native Bower/NPM client, use CDN or avoid assets installation entirely.
In order to prevent assets installation via Composer, add the following lines to your '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: in case of bypassing asset installation via Composer, you are responsible for the assets installation and resolving
> version collisions. Be prepared for possible inconsistencies among asset files from different extensions.
Verifying the Installation <span id="verifying-installation"></span>
--------------------------
@ -200,6 +224,9 @@ DocumentRoot "path/to/basic/web"
# 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...
</Directory>
```
@ -209,7 +236,7 @@ DocumentRoot "path/to/basic/web"
To use [Nginx](http://wiki.nginx.org/), you should install PHP as an [FPM SAPI](http://php.net/install.fpm).
You may use the following Nginx configuration, replacing `path/to/basic/web` with the actual path for
`basic/web` and `mysite.local` with the actual hostname to serve.
`basic/web` and `mysite.test` with the actual hostname to serve.
```nginx
server {
@ -219,7 +246,7 @@ server {
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name mysite.local;
server_name mysite.test;
root /path/to/basic/web;
index index.php;

22
docs/guide/start-prerequisites.md

@ -0,0 +1,22 @@
# What do you need to know
Yii learning curve is not as steep as other PHP frameworks but still it requires some beforehand knowledge.
## PHP
Yii is a PHP framework so make sure you [read and understand language reference](http://php.net/manual/en/langref.php).
## Object oriented programming
Basic understanding of object oriented programming is required. If you're not familiar with it, check one of the many
tutorials available such as [the one from tuts+](https://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762).
Note that the more complicated your application is the more advanced OOP concepts your should learn in order to successfully
manage that complexity.
## Command line and composer
Yii extensively uses de-facto standard PHP package manager, [Composer](https://getcomposer.org/) so make sure you read
and understand its guide. If you are not familiar with using command line it is time to start trying. Once you'll
learn the basics you'll never want to work without it.

24
docs/guide/structure-assets.md

@ -40,6 +40,7 @@ class AppAsset extends AssetBundle
public $baseUrl = '@web';
public $css = [
'css/site.css',
['css/print.css', 'media' => 'print'],
];
public $js = [
];
@ -68,17 +69,18 @@ explanation about the properties of [[yii\web\AssetBundle]] can be found in the
[[yii\web\AssetBundle::basePath|basePath]]. Like [[yii\web\AssetBundle::basePath|basePath]],
if you specify the [[yii\web\AssetBundle::sourcePath|sourcePath]] property, the [asset manager](#asset-manager)
will publish the assets and overwrite this property accordingly. [Path aliases](concept-aliases.md) can be used here.
* [[yii\web\AssetBundle::js|js]]: an array listing the JavaScript files contained in this bundle. Note that only
forward slash "/" should be used as directory separators. Each JavaScript file can be specified in one of the
following two formats:
* [[yii\web\AssetBundle::css|css]]: an array listing the CSS files contained in this bundle. Note that only forward slash "/"
should be used as directory separators. Each file can be specified on its own as a string or in an array together with
attribute tags and their values.
* [[yii\web\AssetBundle::js|js]]: an array listing the JavaScript files contained in this bundle. The format of this array
is the same as that of [[yii\web\AssetBundle::css|css]]. Each JavaScript file can be specified in one of the following two
formats:
- a relative path representing a local JavaScript file (e.g. `js/main.js`). The actual path of the file
can be determined by prepending [[yii\web\AssetManager::basePath]] to the relative path, and the actual URL
of the file can be determined by prepending [[yii\web\AssetManager::baseUrl]] to the relative path.
- an absolute URL representing an external JavaScript file. For example,
`http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` or
`//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js`.
* [[yii\web\AssetBundle::css|css]]: an array listing the CSS files contained in this bundle. The format of this array
is the same as that of [[yii\web\AssetBundle::js|js]].
* [[yii\web\AssetBundle::depends|depends]]: an array listing the names of the asset bundles that this bundle depends on
(to be explained shortly).
* [[yii\web\AssetBundle::jsOptions|jsOptions]]: specifies the options that will be passed to the
@ -143,8 +145,8 @@ will be passed to the [[yii\web\View::registerCssFile()]] and [[yii\web\View::re
they are called by the [view](structure-views.md) to include CSS and JavaScript files.
> Note: The options you set in a bundle class apply to *every* CSS/JavaScript file in the bundle. If you want to
use different options for different files, you should create separate asset bundles, and use one set of options
in each bundle.
use different options for different files, you should use the format mentioned [[yii\web\AssetBundle::css|above]] or create
separate asset bundles, and use one set of options in each bundle.
For example, to conditionally include a CSS file for browsers that are IE9 or below, you can use the following option:
@ -192,8 +194,8 @@ class FontAwesomeAsset extends AssetBundle
];
public $publishOptions = [
'only' => [
'fonts/',
'css/',
'fonts/*',
'css/*',
]
];
}
@ -248,8 +250,8 @@ Visit [asset-packagist.org](https://asset-packagist.org) to know, how it works.
##### Using fxp/composer-asset-plugin
Comparing to to using asset-packagist, composer-asset-plugin does not require to change application config. Instead, it
requires to install a special Composer plugin globally by running the following command:
Compared to asset-packagist, composer-asset-plugin does not require any changes to application config. Instead, it
requires global installation of a special Composer plugin by running the following command:
```bash
composer global require "fxp/composer-asset-plugin:^1.4.1"

2
docs/guide/structure-filters.md

@ -90,7 +90,7 @@ class ActionTimeFilter extends ActionFilter
public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::trace("Action '{$action->uniqueId}' spent $time second.");
Yii::debug("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}

8
docs/guide/structure-modules.md

@ -176,6 +176,14 @@ only contains the module ID, then the [[yii\base\Module::defaultRoute]] property
will determine which controller/action should be used. This means a route `forum` would represent the `default`
controller in the `forum` module.
URL manager routes should be added before [[yii\web\UrlManager::parseRequest()]] is fired. That means doing it
in module's `init()` won't work because module will be initialized when routes were already processed. Thus, routes
should be added at [bootstrap stage](structure-extensions.md#bootstrapping-classes). It is a also a good practice
to wrap module's URL rules with [[\yii\web\GroupUrlRule]].
In case module is used to [version API](rest-versioning.md), routes should be added directly in `urlManager`
section of the application config.
### Accessing Modules <span id="accessing-modules"></span>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save