Browse Source

Merge branch 'master' into 13614-add-a-failing-test-for-url-rule

tags/2.0.12
Robert Korulczyk 8 years ago committed by GitHub
parent
commit
2d28b585a0
  1. 3
      .dockerignore
  2. 4
      .github/ISSUE_TEMPLATE.md
  3. 1
      .gitignore
  4. 118
      .gitlab-ci.yml
  5. 20
      .travis.yml
  6. 8
      Dockerfile
  7. 2
      README.md
  8. 12
      build/controllers/DevController.php
  9. 4
      build/controllers/MimeTypeController.php
  10. 30
      build/controllers/PhpDocController.php
  11. 46
      build/controllers/ReleaseController.php
  12. 4
      build/controllers/TranslationController.php
  13. 4
      build/controllers/Utf8Controller.php
  14. 4
      build/controllers/views/translation/report_html.php
  15. 6
      composer.json
  16. 109
      composer.lock
  17. 2
      docs/guide-es/input-file-upload.md
  18. 2
      docs/guide-es/start-installation.md
  19. 2
      docs/guide-es/tutorial-start-from-scratch.md
  20. 2
      docs/guide-es/tutorial-yii-integration.md
  21. 404
      docs/guide-fr/helper-array.md
  22. 396
      docs/guide-fr/helper-html.md
  23. 68
      docs/guide-fr/helper-overview.md
  24. 161
      docs/guide-fr/helper-url.md
  25. 2
      docs/guide-fr/input-file-upload.md
  26. 2
      docs/guide-id/start-installation.md
  27. 2
      docs/guide-it/start-installation.md
  28. 2
      docs/guide-ja/input-file-upload.md
  29. 2
      docs/guide-ja/start-installation.md
  30. 2
      docs/guide-ja/tutorial-start-from-scratch.md
  31. 2
      docs/guide-ja/tutorial-yii-integration.md
  32. 20
      docs/guide-pl/README.md
  33. 3
      docs/guide-pl/caching-overview.md
  34. 6
      docs/guide-pl/caching-page.md
  35. 2
      docs/guide-pl/concept-components.md
  36. 170
      docs/guide-pl/db-active-record.md
  37. BIN
      docs/guide-pl/images/start-gii-crud-preview.png
  38. BIN
      docs/guide-pl/images/start-gii-crud.png
  39. BIN
      docs/guide-pl/images/start-gii-model-preview.png
  40. BIN
      docs/guide-pl/images/start-gii-model.png
  41. 2
      docs/guide-pl/input-file-upload.md
  42. 81
      docs/guide-pl/input-forms.md
  43. 144
      docs/guide-pl/input-validation.md
  44. 3
      docs/guide-pl/intro-upgrade-from-v1.md
  45. 8
      docs/guide-pl/intro-yii.md
  46. 2
      docs/guide-pl/start-installation.md
  47. 2
      docs/guide-pl/tutorial-start-from-scratch.md
  48. 2
      docs/guide-pt-BR/start-installation.md
  49. 2
      docs/guide-pt-BR/tutorial-yii-integration.md
  50. 2
      docs/guide-ru/input-file-upload.md
  51. 3
      docs/guide-ru/input-validation.md
  52. 4
      docs/guide-ru/output-data-widgets.md
  53. 2
      docs/guide-ru/rest-rate-limiting.md
  54. 2
      docs/guide-ru/rest-resources.md
  55. 2
      docs/guide-ru/start-installation.md
  56. 22
      docs/guide-ru/test-environment-setup.md
  57. 2
      docs/guide-ru/tutorial-start-from-scratch.md
  58. 2
      docs/guide-ru/tutorial-yii-integration.md
  59. 2
      docs/guide-uk/start-installation.md
  60. 2
      docs/guide-uk/tutorial-start-from-scratch.md
  61. 2
      docs/guide-uk/tutorial-yii-integration.md
  62. 26
      docs/guide-vi/README.md
  63. 18
      docs/guide-vi/intro-yii.md
  64. 39
      docs/guide-vi/start-installation.md
  65. 2
      docs/guide-zh-CN/start-installation.md
  66. 2
      docs/guide-zh-CN/tutorial-yii-integration.md
  67. 2
      docs/guide/helper-overview.md
  68. 2
      docs/guide/input-file-upload.md
  69. 4
      docs/guide/input-forms.md
  70. 6
      docs/guide/input-multiple-models.md
  71. 18
      docs/guide/rest-routing.md
  72. 3
      docs/guide/runtime-logging.md
  73. 35
      docs/guide/security-best-practices.md
  74. 2
      docs/guide/start-installation.md
  75. 4
      docs/guide/structure-widgets.md
  76. 2
      docs/guide/test-fixtures.md
  77. 5
      docs/guide/tutorial-performance-tuning.md
  78. 2
      docs/guide/tutorial-start-from-scratch.md
  79. 2
      docs/guide/tutorial-yii-integration.md
  80. 12
      docs/internals-ja/core-code-style.md
  81. 2
      docs/internals-ja/git-workflow.md
  82. 2
      docs/internals-pl/automation.md
  83. 12
      docs/internals-pl/core-code-style.md
  84. 4
      docs/internals-pl/design-decisions.md
  85. 31
      docs/internals-pl/git-workflow.md
  86. 16
      docs/internals-ru/core-code-style.md
  87. 2
      docs/internals-ru/git-workflow.md
  88. 12
      docs/internals-uk/core-code-style.md
  89. 12
      docs/internals/core-code-style.md
  90. 2
      docs/internals/git-workflow.md
  91. 83
      framework/CHANGELOG.md
  92. 2
      framework/README.md
  93. 13
      framework/UPGRADE.md
  94. 6
      framework/assets/yii.js
  95. 2
      framework/base/Behavior.php
  96. 2
      framework/base/Controller.php
  97. 4
      framework/base/ErrorHandler.php
  98. 16
      framework/base/Event.php
  99. 2
      framework/base/Model.php
  100. 2
      framework/base/Module.php
  101. Some files were not shown because too many files have changed in this diff Show More

3
.dockerignore

@ -0,0 +1,3 @@
.git
vendor
docs

4
.github/ISSUE_TEMPLATE.md

@ -1,3 +1,5 @@
### What steps will reproduce the problem?
### What is the expected result?
@ -10,5 +12,5 @@
| Q | A
| ---------------- | ---
| Yii version | 2.0.?
| PHP version |
| PHP version |
| Operating system |

1
.gitignore vendored

@ -41,3 +41,4 @@ phpunit.phar
# NPM packages
/node_modules
.env

118
.gitlab-ci.yml

@ -0,0 +1,118 @@
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
after_script:
- export ISOLATION=buildpipeline${CI_PIPELINE_ID}${CI_BUILD_NAME}
- export COMPOSE_PROJECT_NAME=${ISOLATION}
# run docker-compose commands from tests environment
- cd tests
- cp .env-dist .env
- docker-compose down -v --remove-orphans
- docker ps -f name=${ISOLATION}
stages:
- travis
- test
- cleanup
test:
stage: test
script:
- docker-compose up --build -d
- docker-compose run --rm php vendor/bin/phpunit -v --exclude caching,db,data --log-junit tests/_junit/test.xml
caching:
stage: test
only:
- tests/caching
- tests/full
script:
- export COMPOSE_FILE=docker-compose.yml:docker-compose.${CI_BUILD_NAME}.yml
- docker-compose up --build -d
- docker-compose run --rm php vendor/bin/phpunit -v --group caching --exclude db
db:
stage: test
only:
- tests/mysql
- tests/full
script:
- docker-compose up --build -d
- docker-compose run --rm php vendor/bin/phpunit -v --group db --exclude caching,mysql,pgsql,mssql,cubrid,oci
mysql:
stage: test
only:
- tests/mysql
- tests/full
script:
- export COMPOSE_FILE=docker-compose.yml:docker-compose.${CI_BUILD_NAME}.yml
- docker-compose up --build -d
# wait for db (retry X times)
- docker-compose run --rm php bash -c "while ! curl mysql:3306; do ((c++)) && ((c==30)) && break; sleep 2; done"
- docker-compose run --rm php vendor/bin/phpunit -v --group mysql
pgsql:
stage: test
only:
- tests/pgsql
- tests/full
script:
- export COMPOSE_FILE=docker-compose.yml:docker-compose.${CI_BUILD_NAME}.yml
- docker-compose up --build -d
# wait for db (retry X times)
- docker-compose run --rm php bash -c 'while [ true ]; do curl postgres:5432; if [ $? == 52 ]; then break; fi; ((c++)) && ((c==25)) && break; sleep 2; done'
- docker-compose run --rm php vendor/bin/phpunit -v --group pgsql
cubrid:
stage: test
only:
- tests/cubrid
- tests/extra
script:
- cd cubrid
- docker-compose up --build -d
# wait for db (retry X times)
- docker-compose run --rm php bash -c 'while [ true ]; do curl cubrid:1523; if [ $? == 56 ]; then break; fi; ((c++)) && ((c==20)) && break; sleep 3; done'
- sleep 5
- docker-compose run --rm php /project/vendor/bin/phpunit -v --group cubrid
mssql:
stage: test
only:
- tests/mssql
- tests/extra
script:
- cd mssql
- docker-compose up --build -d
# wait for db (retry X times)
- docker-compose run --rm php bash -c 'while [ true ]; do curl mssql:1433; if [ $? == 52 ]; then break; fi; ((c++)) && ((c==15)) && break; sleep 5; done'
- sleep 3
# Note: Password has to be the last parameter
- docker-compose run --rm sqlcmd sh -c 'sqlcmd -S mssql -U sa -Q "CREATE DATABASE yii2test" -P Microsoft-12345'
- docker-compose run --rm php vendor/bin/phpunit -v --group mssql
travis:
stage: travis
only:
- travis
script:
- export COMPOSE_FILE=docker-compose.yml:docker-compose.mysql.yml:docker-compose.pgsql.yml
- docker-compose up --build -d
# wait for dbs ...
- sleep 10
- docker-compose run --rm php vendor/bin/phpunit -v --exclude mssql,cubrid,oci,wincache,xcache,zenddata,cubrid

20
.travis.yml

@ -9,10 +9,12 @@ dist: trusty
sudo: false
# build only on master branches
branches:
only:
- master
- 2.1
# commented as this prevents people from running builds on their forks:
# https://github.com/yiisoft/yii2/commit/bd87be990fa238c6d5e326d0a171f38d02dc253a
#branches:
# only:
# - master
# - 2.1
#
@ -77,7 +79,6 @@ matrix:
# disable xdebug for performance in composer
- phpenv config-rm xdebug.ini || echo "xdebug is not installed"
- travis_retry composer self-update && composer --version
- travis_retry composer global require "fxp/composer-asset-plugin:^1.2.0" --no-plugins
- travis_retry composer install --prefer-dist --no-interaction
before_script:
- node --version
@ -111,12 +112,11 @@ addons:
install:
- |
if [[ $TRAVIS_PHP_VERSION != '5.6' && $TRAVIS_PHP_VERSION != hhv* ]]; then
if [[ $TRAVIS_PHP_VERSION != '7.1' && $TRAVIS_PHP_VERSION != hhv* ]]; then
# disable xdebug for performance reasons when code coverage is not needed. note: xdebug on hhvm is disabled by default
phpenv config-rm xdebug.ini || echo "xdebug is not installed"
fi
- travis_retry composer self-update && composer --version
- travis_retry composer global require "fxp/composer-asset-plugin:^1.2.0" --no-plugins
- export PATH="$HOME/.composer/vendor/bin:$PATH"
# core framework:
- travis_retry composer install --prefer-dist --no-interaction
@ -139,9 +139,9 @@ before_script:
- mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'travis'@'localhost' WITH GRANT OPTION;";
- psql -U postgres -c 'CREATE DATABASE yiitest;';
# enable code coverage on PHP 5.6, only one PHP version needs to generate coverage data
# enable code coverage on PHP 7.1, only one PHP version needs to generate coverage data
- |
if [ $TRAVIS_PHP_VERSION = '5.6' ]; then
if [ $TRAVIS_PHP_VERSION = '7.1' ]; then
PHPUNIT_FLAGS="--coverage-clover=coverage.clover"
fi
@ -157,7 +157,7 @@ script:
after_script:
- |
if [ $TRAVIS_PHP_VERSION = '5.6' ]; then
if [ $TRAVIS_PHP_VERSION = '7.1' ]; then
travis_retry wget https://scrutinizer-ci.com/ocular.phar
php ocular.phar code-coverage:upload --format=php-clover coverage.clover
fi

8
Dockerfile

@ -0,0 +1,8 @@
FROM dmstr/php-yii2:7.0-fpm-1.9-beta2-alpine-nginx
# Project source-code
WORKDIR /project
ADD composer.* /project/
RUN /usr/local/bin/composer install --prefer-dist
ADD ./ /project
ENV PATH /project/vendor/bin:${PATH}

2
README.md

@ -58,7 +58,7 @@ You may join us and:
- [Give us feedback or start a design discussion](http://www.yiiframework.com/forum/index.php/forum/42-general-discussions-for-yii-20/)
- [Contribute to the core code or fix bugs](docs/internals/git-workflow.md)
### Reporting Secirity issues
### Reporting Security issues
Please refer to a [special page at the website](http://www.yiiframework.com/security/)
describing proper workflow for security issue reports.

12
build/controllers/DevController.php

@ -70,14 +70,14 @@ class DevController extends Controller
return 1;
}
foreach($this->extensions as $ext => $repo) {
foreach ($this->extensions as $ext => $repo) {
$ret = $this->actionExt($ext);
if ($ret !== 0) {
return $ret;
}
}
foreach($this->apps as $app => $repo) {
foreach ($this->apps as $app => $repo) {
$ret = $this->actionApp($app);
if ($ret !== 0) {
return $ret;
@ -107,7 +107,7 @@ class DevController extends Controller
asort($dirs);
$oldcwd = getcwd();
foreach($dirs as $dir) {
foreach ($dirs as $dir) {
$displayDir = substr($dir, strlen($base));
$this->stdout("Running '$command' in $displayDir...\n", Console::BOLD);
chdir($dir);
@ -252,7 +252,7 @@ class DevController extends Controller
$this->unlink($link);
}
$extensions = $this->findDirs("$dir/vendor/yiisoft");
foreach($extensions as $ext) {
foreach ($extensions as $ext) {
if (is_link($link = "$dir/vendor/yiisoft/yii2-$ext")) {
$this->stdout("Removing symlink $link.\n");
$this->unlink($link);
@ -276,7 +276,7 @@ class DevController extends Controller
symlink("$base/framework", $link);
}
$extensions = $this->findDirs("$dir/vendor/yiisoft");
foreach($extensions as $ext) {
foreach ($extensions as $ext) {
if (is_dir($link = "$dir/vendor/yiisoft/yii2-$ext")) {
$this->stdout("Removing dir $link.\n");
FileHelper::removeDirectory($link);
@ -359,7 +359,7 @@ class DevController extends Controller
}
closedir($handle);
foreach($list as $i => $e) {
foreach ($list as $i => $e) {
if ($e === 'composer') { // skip composer to not break composer update
unset($list[$i]);
}

4
build/controllers/MimeTypeController.php

@ -39,14 +39,14 @@ class MimeTypeController extends Controller
$this->stdout("done.\n", Console::FG_GREEN);
$this->stdout("generating file $outFile...");
$mimeMap = [];
foreach(explode("\n", $content) as $line) {
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) {
foreach ($parts as $ext) {
if (!empty($ext)) {
$mimeMap[$ext] = $mime;
}

30
build/controllers/PhpDocController.php

@ -167,8 +167,8 @@ class PhpDocController extends Controller
'tests/',
'vendor/',
];
foreach($extensionExcept as $ext => $paths) {
foreach($paths as $path) {
foreach ($extensionExcept as $ext => $paths) {
foreach ($paths as $path) {
$except[] = "/extensions/$ext$path";
}
}
@ -184,7 +184,7 @@ class PhpDocController extends Controller
}
if (isset($extensionExcept[$extension])) {
foreach($extensionExcept[$extension] as $path) {
foreach ($extensionExcept[$extension] as $path) {
$except[] = $path;
}
}
@ -255,7 +255,7 @@ class PhpDocController extends Controller
$namespace = false;
$namespaceLine = '';
$contentAfterNamespace = false;
foreach($lines as $i => $line) {
foreach ($lines as $i => $line) {
$line = trim($line);
if (!empty($line)) {
if (strncmp($line, 'namespace', 9) === 0) {
@ -269,7 +269,7 @@ class PhpDocController extends Controller
}
if ($namespace !== false && $contentAfterNamespace !== false) {
while($contentAfterNamespace > 0) {
while ($contentAfterNamespace > 0) {
array_shift($lines);
$contentAfterNamespace--;
}
@ -297,7 +297,7 @@ class PhpDocController extends Controller
$listIndent = '';
$tag = false;
$indent = '';
foreach($lines as $i => $line) {
foreach ($lines as $i => $line) {
if (preg_match('~^(\s*)/\*\*$~', $line, $matches)) {
$docBlock = true;
$indent = $matches[1];
@ -348,8 +348,8 @@ class PhpDocController extends Controller
{
return preg_replace_callback('~@(param|return) ([\w\\|]+)~i', function($matches) {
$types = explode('|', $matches[2]);
foreach($types as $i => $type) {
switch($type){
foreach ($types as $i => $type) {
switch ($type) {
case 'integer': $types[$i] = 'int'; break;
case 'boolean': $types[$i] = 'bool'; break;
}
@ -367,7 +367,7 @@ class PhpDocController extends Controller
// remove blank lines between properties
$skip = true;
$level = 0;
foreach($lines as $i => $line) {
foreach ($lines as $i => $line) {
if (strpos($line, 'class ') !== false) {
$skip = false;
}
@ -402,7 +402,7 @@ class PhpDocController extends Controller
$skip = true;
$level = 0; // track array properties
$property = '';
foreach($lines as $i => $line) {
foreach ($lines as $i => $line) {
if (strpos($line, 'class ') !== false) {
$skip = false;
}
@ -428,10 +428,10 @@ class PhpDocController extends Controller
$endofPrivate = $i;
$property = 'Private';
$level = 0;
} elseif (substr($line,0 , 6) === 'const ') {
} elseif (substr($line, 0, 6) === 'const ') {
$endofConst = $i;
$property = false;
} elseif (substr($line,0 , 4) === 'use ') {
} elseif (substr($line, 0, 4) === 'use ') {
$endofUse = $i;
$property = false;
} elseif (!empty($line) && $line[0] === '*') {
@ -447,7 +447,7 @@ class PhpDocController extends Controller
}
$endofAll = false;
foreach(['Private', 'Protected', 'Public', 'Const', 'Use'] as $var) {
foreach (['Private', 'Protected', 'Public', 'Const', 'Use'] as $var) {
if (${'endof'.$var} !== false) {
$endofAll = ${'endof'.$var};
break;
@ -456,7 +456,7 @@ class PhpDocController extends Controller
// $this->checkPropertyOrder($lineInfo);
$result = [];
foreach($lines as $i => $line) {
foreach ($lines as $i => $line) {
$result[] = $line;
if (!($propertiesOnly && $i === $endofAll)) {
if ($i === $endofUse || $i === $endofConst || $i === $endofPublic ||
@ -753,7 +753,7 @@ class PhpDocController extends Controller
// example: yii\di\ServiceLocator setComponents() is not recognized in the whole but in
// a part of the class.
$parts = $split ? explode("\n\n", $subject) : [$subject];
foreach($parts as $part) {
foreach ($parts as $part) {
preg_match_all($pattern . 'suU', $part, $matches, PREG_SET_ORDER);
foreach ($matches as &$set) {
foreach ($set as $i => $match)

46
build/controllers/ReleaseController.php

@ -105,7 +105,7 @@ class ReleaseController extends Controller
}
if ($this->update) {
foreach($items as $item) {
foreach ($items as $item) {
$this->stdout("fetching tags for $item...");
if ($item === 'framework') {
$this->gitFetchTags("{$this->basePath}");
@ -126,7 +126,7 @@ class ReleaseController extends Controller
// print version table
$w = $this->minWidth(array_keys($versions));
$this->stdout(str_repeat(' ', $w + 2) . "Current Version Next Version\n", Console::BOLD);
foreach($versions as $ext => $version) {
foreach ($versions as $ext => $version) {
$this->stdout($ext . str_repeat(' ', $w + 3 - mb_strlen($ext)) . $version . "");
$this->stdout(str_repeat(' ', 17 - mb_strlen($version)) . $nextVersions[$ext] . "\n");
}
@ -136,7 +136,7 @@ class ReleaseController extends Controller
private function minWidth($a)
{
$w = 1;
foreach($a as $s) {
foreach ($a as $s) {
if (($l = mb_strlen($s)) > $w) {
$w = $l;
}
@ -199,7 +199,7 @@ class ReleaseController extends Controller
if ($this->version !== null) {
// if a version is explicitly given
$newVersions = [];
foreach($versions as $k => $v) {
foreach ($versions as $k => $v) {
$newVersions[$k] = $this->version;
}
} else {
@ -230,7 +230,7 @@ class ReleaseController extends Controller
return 1;
}
foreach($what as $ext) {
foreach ($what as $ext) {
if ($ext === 'framework') {
$this->releaseFramework("{$this->basePath}/framework", $newVersions['framework']);
} elseif (strncmp('app-', $ext, 4) === 0) {
@ -264,7 +264,7 @@ class ReleaseController extends Controller
$versions = $this->getCurrentVersions($what);
$this->stdout("You are about to generate packages for the following things:\n\n");
foreach($what as $ext) {
foreach ($what as $ext) {
if (strncmp('app-', $ext, 4) === 0) {
$this->stdout(" - ");
$this->stdout(substr($ext, 4), Console::FG_RED);
@ -289,7 +289,7 @@ class ReleaseController extends Controller
return 1;
}
foreach($what as $ext) {
foreach ($what as $ext) {
if ($ext === 'framework') {
throw new Exception('Can not package framework.');
} elseif (strncmp('app-', $ext, 4) === 0) {
@ -334,7 +334,7 @@ class ReleaseController extends Controller
protected function printWhat(array $what, $newVersions, $versions)
{
foreach($what as $ext) {
foreach ($what as $ext) {
if (strncmp('app-', $ext, 4) === 0) {
$this->stdout(" - ");
$this->stdout(substr($ext, 4), Console::FG_RED);
@ -353,7 +353,7 @@ class ReleaseController extends Controller
protected function printWhatUrls(array $what, $oldVersions)
{
foreach($what as $ext) {
foreach ($what as $ext) {
if ($ext === 'framework') {
$this->stdout("framework: https://github.com/yiisoft/yii2-framework/compare/{$oldVersions[$ext]}...master\n");
$this->stdout("app-basic: https://github.com/yiisoft/yii2-app-basic/compare/{$oldVersions[$ext]}...master\n");
@ -372,7 +372,7 @@ class ReleaseController extends Controller
*/
protected function validateWhat(array $what, $limit = [], $ensureGitClean = true)
{
foreach($what as $w) {
foreach ($what as $w) {
if (strncmp('app-', $w, 4) === 0) {
if (!empty($limit) && !in_array('app', $limit)) {
throw new Exception("Only the following types are allowed: ".implode(', ', $limit)."\n");
@ -460,7 +460,7 @@ class ReleaseController extends Controller
$this->runGit("git diff --color", $frameworkPath);
$this->stdout("\n\n\nCheck whether the above diff is okay, if not you may change things as needed before continuing.\n");
$this->stdout("You may abort the program with Ctrl + C and reset the changes by running `git checkout -- .` in the repo.\n\n");
} while(!$this->confirm("Type `yes` to continue, `no` to view git diff again. Continue?"));
} while (!$this->confirm("Type `yes` to continue, `no` to view git diff again. Continue?"));
$this->stdout("\n\n");
$this->stdout(" **** RELEASE TIME! ****\n", Console::FG_YELLOW, Console::BOLD);
@ -581,7 +581,7 @@ class ReleaseController extends Controller
$this->runGit("git diff --color", $path);
$this->stdout("\n\n\nCheck whether the above diff is okay, if not you may change things as needed before continuing.\n");
$this->stdout("You may abort the program with Ctrl + C and reset the changes by running `git checkout -- .` in the repo.\n\n");
} while(!$this->confirm("Type `yes` to continue, `no` to view git diff again. Continue?"));
} while (!$this->confirm("Type `yes` to continue, `no` to view git diff again. Continue?"));
$this->stdout("\n\n");
$this->stdout(" **** RELEASE TIME! ****\n", Console::FG_YELLOW, Console::BOLD);
@ -633,7 +633,7 @@ class ReleaseController extends Controller
protected function setAppAliases($app, $path)
{
$this->_oldAlias = Yii::getAlias('@app');
switch($app) {
switch ($app) {
case 'basic':
Yii::setAlias('@app', $path);
break;
@ -699,7 +699,7 @@ class ReleaseController extends Controller
$this->runGit("git diff --color", $path);
$this->stdout("\n\n\nCheck whether the above diff is okay, if not you may change things as needed before continuing.\n");
$this->stdout("You may abort the program with Ctrl + C and reset the changes by running `git checkout -- .` in the repo.\n\n");
} while(!$this->confirm("Type `yes` to continue, `no` to view git diff again. Continue?"));
} while (!$this->confirm("Type `yes` to continue, `no` to view git diff again. Continue?"));
$this->stdout("\n\n");
$this->stdout(" **** RELEASE TIME! ****\n", Console::FG_YELLOW, Console::BOLD);
@ -825,7 +825,7 @@ class ReleaseController extends Controller
{
$headline = "\n$version under development\n";
$headline .= str_repeat('-', strlen($headline) - 2) . "\n\n- no changes in this release.\n";
foreach($this->getChangelogs($what) as $file) {
foreach ($this->getChangelogs($what) as $file) {
$lines = explode("\n", file_get_contents($file));
$hl = [
array_shift($lines),
@ -839,7 +839,7 @@ class ReleaseController extends Controller
protected function resortChangelogs($what, $version)
{
foreach($this->getChangelogs($what) as $file) {
foreach ($this->getChangelogs($what) as $file) {
// split the file into relevant parts
list($start, $changelog, $end) = $this->splitChangelog($file, $version);
$changelog = $this->resortChangelog($changelog);
@ -860,7 +860,7 @@ class ReleaseController extends Controller
$end = [];
$state = 'start';
foreach($lines as $l => $line) {
foreach ($lines as $l => $line) {
// starting from the changelogs headline
if (isset($lines[$l-2]) && strpos($lines[$l-2], $version) !== false &&
isset($lines[$l-1]) && strncmp($lines[$l-1], '---', 3) === 0) {
@ -886,7 +886,7 @@ class ReleaseController extends Controller
protected function resortChangelog($changelog)
{
// cleanup whitespace
foreach($changelog as $i => $line) {
foreach ($changelog as $i => $line) {
$changelog[$i] = rtrim($line);
}
$changelog = array_filter($changelog);
@ -926,7 +926,7 @@ class ReleaseController extends Controller
protected function getExtensionChangelogs($what)
{
return array_filter(glob($this->basePath . '/extensions/*/CHANGELOG.md'), function($elem) use ($what) {
foreach($what as $ext) {
foreach ($what as $ext) {
if (strpos($elem, "extensions/$ext/CHANGELOG.md") !== false) {
return true;
}
@ -979,7 +979,7 @@ class ReleaseController extends Controller
protected function sed($pattern, $replace, $files)
{
foreach((array) $files as $file) {
foreach ((array) $files as $file) {
file_put_contents($file, preg_replace($pattern, $replace, file_get_contents($file)));
}
}
@ -987,7 +987,7 @@ class ReleaseController extends Controller
protected function getCurrentVersions(array $what)
{
$versions = [];
foreach($what as $ext) {
foreach ($what as $ext) {
if ($ext === 'framework') {
chdir("{$this->basePath}/framework");
} elseif (strncmp('app-', $ext, 4) === 0) {
@ -1011,13 +1011,13 @@ class ReleaseController extends Controller
protected function getNextVersions(array $versions, $type)
{
foreach($versions as $k => $v) {
foreach ($versions as $k => $v) {
if (empty($v)) {
$versions[$k] = '2.0.0';
continue;
}
$parts = explode('.', $v);
switch($type) {
switch ($type) {
case self::MINOR:
$parts[1]++;
$parts[2] = 0;

4
build/controllers/TranslationController.php

@ -47,7 +47,7 @@ class TranslationController extends Controller
$errors = $this->checkFiles($translatedFilePath);
$diff = empty($errors) ? $this->getDiff($translatedFilePath, $sourceFilePath) : '';
if(!empty($diff)) {
if (!empty($diff)) {
$errors[] = 'Translation outdated.';
}
@ -68,7 +68,7 @@ class TranslationController extends Controller
$translatedFilePath = $translationPath . '/' . $fileinfo->getFilename();
$errors = $this->checkFiles(null, $translatedFilePath);
if(!empty($errors)) {
if (!empty($errors)) {
$results[$fileinfo->getFilename()]['errors'] = $errors;
}
}

4
build/controllers/Utf8Controller.php

@ -39,14 +39,14 @@ class Utf8Controller extends Controller
]);
}
foreach($files as $file) {
foreach ($files as $file) {
$content = file_get_contents($file);
$chars = preg_split('//u', $content, null, PREG_SPLIT_NO_EMPTY);
$line = 1;
$pos = 0;
foreach($chars as $c) {
foreach ($chars as $c) {
$ord = $this->unicodeOrd($c);

4
build/controllers/views/translation/report_html.php

@ -36,9 +36,9 @@ use yii\helpers\Html;
<li><strong>Translation:</strong> <?= Html::encode($translationPath) ?></li>
</ul>
<?php foreach($results as $name => $result): ?>
<?php foreach ($results as $name => $result): ?>
<h2 class="<?= empty($result['errors']) ? 'ok' : 'errors' ?>"><?= $name ?></h2>
<?php foreach($result['errors'] as $error): ?>
<?php foreach ($result['errors'] as $error): ?>
<p><?= Html::encode($error) ?></p>
<?php endforeach ?>
<?php if (!empty($result['diff'])): ?>

6
composer.json

@ -84,6 +84,12 @@
"phpunit/phpunit": "~4.4",
"cebe/indent": "~1.0.2"
},
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
],
"suggest": {
"yiisoft/yii2-coding-standards": "you can use this package to check for code style issues when contributing to yii"
},

109
composer.lock generated

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "30a97926034335c40273795ce316f36c",
"content-hash": "58ccdf60f6da90c6d1623d9755c0b830",
"hash": "db4e038c0e8ca747784fb195c82bfdad",
"content-hash": "cc4b01a602c948040169ebbc1ac30186",
"packages": [
{
"name": "bower-asset/jquery",
@ -44,12 +44,12 @@
"source": {
"type": "git",
"url": "https://github.com/RobinHerbots/jquery.inputmask.git",
"reference": "5a72c563b502b8e05958a524cdfffafe9987be38"
"reference": "ec7726993217ee7b01023ad4f7f1b6a51446a39d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/RobinHerbots/jquery.inputmask/zipball/5a72c563b502b8e05958a524cdfffafe9987be38",
"reference": "5a72c563b502b8e05958a524cdfffafe9987be38",
"url": "https://api.github.com/repos/RobinHerbots/jquery.inputmask/zipball/ec7726993217ee7b01023ad4f7f1b6a51446a39d",
"reference": "ec7726993217ee7b01023ad4f7f1b6a51446a39d",
"shasum": ""
},
"require": {
@ -114,16 +114,16 @@
},
{
"name": "bower-asset/yii2-pjax",
"version": "dev-master",
"version": "v2.0.6",
"source": {
"type": "git",
"url": "https://github.com/yiisoft/jquery-pjax.git",
"reference": "3f20897307cca046fca5323b318475ae9dac0ca0"
"reference": "60728da6ade5879e807a49ce59ef9a72039b8978"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/3f20897307cca046fca5323b318475ae9dac0ca0",
"reference": "3f20897307cca046fca5323b318475ae9dac0ca0",
"url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/60728da6ade5879e807a49ce59ef9a72039b8978",
"reference": "60728da6ade5879e807a49ce59ef9a72039b8978",
"shasum": ""
},
"require": {
@ -136,18 +136,15 @@
".travis.yml",
"Gemfile",
"Gemfile.lock",
"CONTRIBUTING.md",
"vendor/",
"script/",
"test/"
],
"branch-alias": {
"dev-master": "2.0.3-dev"
}
]
},
"license": [
"MIT"
],
"time": "2015-03-08 21:03:11"
]
},
{
"name": "cebe/markdown",
@ -255,21 +252,24 @@
},
{
"name": "yiisoft/yii2-composer",
"version": "2.0.4",
"version": "2.0.5",
"source": {
"type": "git",
"url": "https://github.com/yiisoft/yii2-composer.git",
"reference": "7452fd908a5023b8bb5ea1b123a174ca080de464"
"reference": "3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/7452fd908a5023b8bb5ea1b123a174ca080de464",
"reference": "7452fd908a5023b8bb5ea1b123a174ca080de464",
"url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2",
"reference": "3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0"
},
"require-dev": {
"composer/composer": "^1.0"
},
"type": "composer-plugin",
"extra": {
"class": "yii\\composer\\Plugin",
@ -298,7 +298,7 @@
"extension installer",
"yii2"
],
"time": "2016-02-06 00:49:24"
"time": "2016-12-20 13:26:02"
}
],
"packages-dev": [
@ -440,16 +440,16 @@
},
{
"name": "phpspec/prophecy",
"version": "v1.6.1",
"version": "v1.6.2",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "58a8137754bc24b25740d4281399a4a3596058e0"
"reference": "6c52c2722f8460122f96f86346600e1077ce22cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0",
"reference": "58a8137754bc24b25740d4281399a4a3596058e0",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb",
"reference": "6c52c2722f8460122f96f86346600e1077ce22cb",
"shasum": ""
},
"require": {
@ -457,10 +457,11 @@
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
"sebastian/comparator": "^1.1",
"sebastian/recursion-context": "^1.0"
"sebastian/recursion-context": "^1.0|^2.0"
},
"require-dev": {
"phpspec/phpspec": "^2.0"
"phpspec/phpspec": "^2.0",
"phpunit/phpunit": "^4.8 || ^5.6.5"
},
"type": "library",
"extra": {
@ -498,7 +499,7 @@
"spy",
"stub"
],
"time": "2016-06-07 08:13:47"
"time": "2016-11-21 14:58:47"
},
{
"name": "phpunit/php-code-coverage",
@ -564,16 +565,16 @@
},
{
"name": "phpunit/php-file-iterator",
"version": "1.4.1",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
"reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
"reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
"shasum": ""
},
"require": {
@ -607,7 +608,7 @@
"filesystem",
"iterator"
],
"time": "2015-06-21 13:08:43"
"time": "2016-10-03 07:40:28"
},
{
"name": "phpunit/php-text-template",
@ -696,16 +697,16 @@
},
{
"name": "phpunit/php-token-stream",
"version": "1.4.8",
"version": "1.4.9",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
"reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b",
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b",
"shasum": ""
},
"require": {
@ -741,20 +742,20 @@
"keywords": [
"tokenizer"
],
"time": "2015-09-15 10:49:45"
"time": "2016-11-15 14:06:22"
},
{
"name": "phpunit/phpunit",
"version": "4.8.27",
"version": "4.8.31",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90"
"reference": "98b2b39a520766bec663ff5b7ff1b729db9dbfe3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c062dddcb68e44b563f66ee319ddae2b5a322a90",
"reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/98b2b39a520766bec663ff5b7ff1b729db9dbfe3",
"reference": "98b2b39a520766bec663ff5b7ff1b729db9dbfe3",
"shasum": ""
},
"require": {
@ -770,7 +771,7 @@
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "^1.0.6",
"phpunit/phpunit-mock-objects": "~2.3",
"sebastian/comparator": "~1.1",
"sebastian/comparator": "~1.2.2",
"sebastian/diff": "~1.2",
"sebastian/environment": "~1.3",
"sebastian/exporter": "~1.2",
@ -813,7 +814,7 @@
"testing",
"xunit"
],
"time": "2016-07-21 06:48:14"
"time": "2016-12-09 02:45:31"
},
{
"name": "phpunit/phpunit-mock-objects",
@ -873,22 +874,22 @@
},
{
"name": "sebastian/comparator",
"version": "1.2.0",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
"reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
"reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f",
"reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.2",
"sebastian/exporter": "~1.2"
"sebastian/exporter": "~1.2 || ~2.0"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
@ -933,7 +934,7 @@
"compare",
"equality"
],
"time": "2015-07-26 15:48:44"
"time": "2016-11-19 09:18:40"
},
{
"name": "sebastian/diff",
@ -1245,16 +1246,16 @@
},
{
"name": "symfony/yaml",
"version": "v2.8.13",
"version": "v2.8.16",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "396784cd06b91f3db576f248f2402d547a077787"
"reference": "dbe61fed9cd4a44c5b1d14e5e7b1a8640cfb2bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/396784cd06b91f3db576f248f2402d547a077787",
"reference": "396784cd06b91f3db576f248f2402d547a077787",
"url": "https://api.github.com/repos/symfony/yaml/zipball/dbe61fed9cd4a44c5b1d14e5e7b1a8640cfb2bf2",
"reference": "dbe61fed9cd4a44c5b1d14e5e7b1a8640cfb2bf2",
"shasum": ""
},
"require": {
@ -1290,7 +1291,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2016-10-21 20:59:10"
"time": "2017-01-03 13:49:52"
}
],
"aliases": [],

2
docs/guide-es/input-file-upload.md

@ -77,7 +77,7 @@ use yii\widgets\ActiveForm;
Es importante recordad que agregues la opción `enctype` al formulario para que el archivo pueda ser subido apropiadamente.
La llamada a `fileInput()` renderizará un tag `<input type="file">` que le permitirá al usuario seleccionar el archivo a subir.
> Tip: desde la versión 2.0.8, [[yii\web\widgets\ActiveField::fileInput|fileInput]] agrega la opción `enctype` al formulario
> Tip: desde la versión 2.0.8, [[yii\widgets\ActiveField::fileInput|fileInput]] agrega la opción `enctype` al formulario
automáticamente cuando se utiliza una campo de subida de archivo.
## Uniendo Todo <span id="wiring-up"></span>

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

@ -40,7 +40,7 @@ ejecutando el comando `composer self-update`
Teniendo Composer instalado, puedes instalar Yii ejecutando los siguientes comandos en un directorio accesible vía Web:
```bash
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
```

2
docs/guide-es/tutorial-start-from-scratch.md

@ -50,6 +50,6 @@ Utilizar el Template
Eso es todo lo que se necesita para crear un nuevo template de proyecto Yii. Ahora puedes crear tus propios proyectos a partir de este template:
```
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist --stability=dev mysoft/yii2-app-coolone new-project
```

2
docs/guide-es/tutorial-yii-integration.md

@ -82,7 +82,7 @@ instalar Yii , e iniciar Yii.
Si el sistema de terceros usa Composer para manejar sus dependencias, simplemente ejecuta estos comandos
para instalar Yii:
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer require yiisoft/yii2
composer install

404
docs/guide-fr/helper-array.md

@ -0,0 +1,404 @@
Classe assistante ArrayHelper
=============================
En plus du jeu riche de [fonctions de tableaux](http://php.net/manual/en/book.array.php) qu'offre PHP, la classe assistante traitant les tableaux dans Yii fournit des méthodes statiques supplémentaires qui vous permettent de traiter les tableaux avec plus d'efficacité.
## Obtention de valeurs <span id="getting-values"></span>
Récupérer des valeurs d'un tableau ou d'un objet ou une structure complexe écrits tous deux en PHP standard est un processus assez répétitif. Vous devez d'abord vérifier que la clé existe avec `isset`, puis si c'est le cas, vous récupérez la valeur associée, sinon il vous faut fournir une valeur par défaut :
```php
class User
{
public $name = 'Alex';
}
$array = [
'foo' => [
'bar' => new User(),
]
];
$value = isset($array['foo']['bar']->name) ? $array['foo']['bar']->name : null;
```
Yii fournit une méthode très pratique pour faire cela :
```php
$value = ArrayHelper::getValue($array, 'foo.bar.name');
```
Le premier argument de la méthode indique de quelle source nous voulons récupérer une valeur. Le deuxième spécifie comment récupérer la donnée. Il peut s'agir d'un des éléments suivants :
- Nom d'une clé de tableau ou de la propriété d'un objet de laquelle récupérer une valeur.
- Un jeu de noms de clé de tableau ou de propriétés d'objet séparées par des points, comme dans l'exemple que nous venons de présenter ci-dessus.
- Une fonction de rappel qui retourne une valeur.
Le fonction de rappel doit être la suivante :
```php
$fullName = ArrayHelper::getValue($user, function ($user, $defaultValue) {
return $user->firstName . ' ' . $user->lastName;
});
```
Le troisième argument facultatif est la valeur par défaut qui est `null` si on ne la spécifie pas. Il peut être utilisé comme ceci :
```php
$username = ArrayHelper::getValue($comment, 'user.username', 'Unknown');
```
Dans le cas où vous voulez récupérer la valeur tout en la retirant immédiatement du tableau, vous pouvez utiliser la méthode `remove` :
```php
$array = ['type' => 'A', 'options' => [1, 2]];
$type = ArrayHelper::remove($array, 'type');
```
Après exécution du code, `$array` contiendra `['options' => [1, 2]]` et `$type` sera `A`. Notez que contrairement à la méthode `getValue`, `remove` accepte seulement les noms de clé.
## Tester l'existence des clés <span id="checking-existence-of-keys"></span>
`ArrayHelper::keyExists` fonctionne comme [array_key_exists](http://php.net/manual/en/function.array-key-exists.php) sauf qu'elle prend également en charge la comparaison de clés insensible à la casse. Par exemple,
```php
$data1 = [
'userName' => 'Alex',
];
$data2 = [
'username' => 'Carsten',
];
if (!ArrayHelper::keyExists('username', $data1, false) || !ArrayHelper::keyExists('username', $data2, false)) {
echo "Veuillez fournir un nom d'utilisateur (username).";
}
```
## Récupération de colonnes <span id="retrieving-columns"></span>
Il arrive souvent que vous ayez à récupérer une colonne de valeurs d'un tableau de lignes de données ou d'objets. Un exemple courant est l'obtention d'une liste d'identifiants.
```php
$array = [
['id' => '123', 'data' => 'abc'],
['id' => '345', 'data' => 'def'],
];
$ids = ArrayHelper::getColumn($array, 'id');
```
Le résultat sera `['123', '345']`.
Si des transformations supplémentaires sont nécessaires ou si la manière de récupérer les valeurs est complexe, le second argument peut être formulé sous forme de fonction anonyme :
```php
$result = ArrayHelper::getColumn($array, function ($element) {
return $element['id'];
});
```
## Réindexation de tableaux <span id="reindexing-arrays"></span>
La méthode `index` peut être utilisées pour indexer un tableau selon une clé spécifiée. L'entrée doit être soit un tableau multidimensionnel, soit un tableau d'objets. `$key` peut être un nom de clé du sous-tableau, un nom de propriété d'objet ou une fonction anonyme qui doit retourner la valeur à utiliser comme clé.
L'attribut `$groups` est un tableau de clés qui est utilisé pour regrouper le tableau d'entrée en un ou plusieurs sous-tableaux basés sur les clés spécifiées.
Si l'argument `$key` ou sa valeur pour l'élément particulier est `null` alors que `$groups` n'est pas défini, l'élément du tableau est écarté. Autrement, si `$groups` est spécifié, l'élément du tableau est ajouté au tableau résultant sans aucune clé.
Par exemple :
```php
$array = [
['id' => '123', 'data' => 'abc', 'device' => 'laptop'],
['id' => '345', 'data' => 'def', 'device' => 'tablet'],
['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],
];
$result = ArrayHelper::index($array, 'id');
```
Le résultat est un tableau associatif, dans lequel la clé est la valeur de l'attribut `id` :
```php
[
'123' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop'],
'345' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']
// Le second élément du tableau d'origine est écrasé par le dernier élément parce que les identifiants sont identiques.
]
```
Une fonction anonyme passée en tant que `$key`, conduit au même résultat :
```php
$result = ArrayHelper::index($array, function ($element) {
return $element['id'];
});
```
Passer `id` comme troisième argument regroupe `$array` par `id`:
```php
$result = ArrayHelper::index($array, null, 'id');
```
Le résultat est un tableau multidimensionnel regroupé par `id` au premier niveau et non indexé au deuxième niveau :
```php
[
'123' => [
['id' => '123', 'data' => 'abc', 'device' => 'laptop']
],
'345' => [ // all elements with this index are present in the result array
['id' => '345', 'data' => 'def', 'device' => 'tablet'],
['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],
]
]
```
Une fonction anonyme peut également être utilisée dans le tableau de regroupement :
```php
$result = ArrayHelper::index($array, 'data', [function ($element) {
return $element['id'];
}, 'device']);
```
Le résultat est un tableau multidimensionnel regroupé par `id` au premier niveau, par `device` au deuxième niveau et par `data` au troisième niveau :
```php
[
'123' => [
'laptop' => [
'abc' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop']
]
],
'345' => [
'tablet' => [
'def' => ['id' => '345', 'data' => 'def', 'device' => 'tablet']
],
'smartphone' => [
'hgi' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']
]
]
]
```
## Construction de tableaux de mise en correspondance <span id="building-maps"></span>
Afin de construire un tableau de mise en correspondance (paires clé-valeur) sur la base d'un tableau multidimensionnel ou d'un tableau d'objets, vous pouvez utiliser la méthode `map`.
Les paramètres `$from` et `$to` spécifient les noms de clé ou les noms des propriétés pour construire le tableau de mise en correspondance. Le paramètre facultatif `$group` est un nom de clé ou de propriété qui permet de regrouper les éléments du tableau au premier niveau. Par exemple :
```php
$array = [
['id' => '123', 'name' => 'aaa', 'class' => 'x'],
['id' => '124', 'name' => 'bbb', 'class' => 'x'],
['id' => '345', 'name' => 'ccc', 'class' => 'y'],
];
$result = ArrayHelper::map($array, 'id', 'name');
// le résultat est :
// [
// '123' => 'aaa',
// '124' => 'bbb',
// '345' => 'ccc',
// ]
$result = ArrayHelper::map($array, 'id', 'name', 'class');
// le résultat est :
// [
// 'x' => [
// '123' => 'aaa',
// '124' => 'bbb',
// ],
// 'y' => [
// '345' => 'ccc',
// ],
// ]
```
## Tri multidimensionnel <span id="multidimensional-sorting"></span>
La méthode `multisort` facilite le tri d'un tableau d'objets ou de tableaux imbriqués selon une ou plusieurs clés. Par exemple :
```php
$data = [
['age' => 30, 'name' => 'Alexander'],
['age' => 30, 'name' => 'Brian'],
['age' => 19, 'name' => 'Barney'],
];
ArrayHelper::multisort($data, ['age', 'name'], [SORT_ASC, SORT_DESC]);
```
Après le tri, `data` contient ce qui suit :
```php
[
['age' => 19, 'name' => 'Barney'],
['age' => 30, 'name' => 'Brian'],
['age' => 30, 'name' => 'Alexander'],
];
```
Le deuxième argument, qui spécifie les clés de tri peut être une chaîne de caractères si la clé est unique, un tableau dans le cas de clés multiples, ou une fonction anonyme telle que celle qui suit :
```php
ArrayHelper::multisort($data, function($item) {
return isset($item['age']) ? ['age', 'name'] : 'name';
});
```
Le troisième argument précise la direction. Dans le cas d'un tri selon une clé unique, il s'agit soit de `SORT_ASC`, soit de `SORT_DESC`. Si le tri se fait selon des valeurs multiples, vous pouvez préciser des directions de tri différentes pour chacune des clés en présentant ces directions sous forme de tableau.
Le dernier argument est une option de tri de PHP qui peut prendre les mêmes valeurs que celles acceptées par la fonction [sort()](http://php.net/manual/en/function.sort.php) de PHP.
## Détection des types de tableau <span id="detecting-array-types"></span>
Il est pratique de savoir si un tableau est indexé ou associatif. Voici un exemple :
```php
// aucune clé spécifiée
$indexed = ['Qiang', 'Paul'];
echo ArrayHelper::isIndexed($indexed);
// toutes les clés sont des chaînes de caractères
$associative = ['framework' => 'Yii', 'version' => '2.0'];
echo ArrayHelper::isAssociative($associative);
```
## Encodage et décodage de valeurs HTML <span id="html-encoding-values"></span>
Afin d'encoder ou décoder des caractères spéciaux dans un tableau de chaînes de caractères en/depuis des entités HTML, vous pouvez utiliser les fonctions suivantes :
```php
$encoded = ArrayHelper::htmlEncode($data);
$decoded = ArrayHelper::htmlDecode($data);
```
Seules les valeurs sont encodées par défaut. En passant un deuxième argument comme `false` vous pouvez également encoder les clés d'un tableau. L'encodage utilise le jeu de caractères de l'application et on peut le changer via un troisième argument.
## Fusion de tableaux <span id="merging-arrays"></span>
La fonction [[yii\helpers\ArrayHelper::merge()|ArrayHelper::merge()]] vous permet de fusionner deux, ou plus, tableaux en un seul de manière récursive. Si chacun des tableaux possède un élément avec la même chaîne clé valeur, le dernier écrase le premier (ce qui est un fonctionnement différent de [array_merge_recursive()](http://php.net/manual/en/function.array-merge-recursive.php)).
La fusion récursive est entreprise si les deux tableaux possèdent un élément de type tableau avec la même clé. Pour des éléments dont la clé est un entier, les éléments du deuxième tableau sont ajoutés aux éléments du premier tableau. Vous pouvez utiliser l'objet [[yii\helpers\UnsetArrayValue]] pour supprimer la valeur du premier tableau ou [[yii\helpers\ReplaceArrayValue]] pour forcer le remplacement de la première valeur au lieu de la fusion récursive.
Par exemple :
```php
$array1 = [
'name' => 'Yii',
'version' => '1.1',
'ids' => [
1,
],
'validDomains' => [
'example.com',
'www.example.com',
],
'emails' => [
'admin' => 'admin@example.com',
'dev' => 'dev@example.com',
],
];
$array2 = [
'version' => '2.0',
'ids' => [
2,
],
'validDomains' => new \yii\helpers\ReplaceArrayValue([
'yiiframework.com',
'www.yiiframework.com',
]),
'emails' => [
'dev' => new \yii\helpers\UnsetArrayValue(),
],
];
$result = ArrayHelper::merge($array1, $array2);
```
Le résultat est :
```php
[
'name' => 'Yii',
'version' => '2.0',
'ids' => [
1,
2,
],
'validDomains' => [
'yiiframework.com',
'www.yiiframework.com',
],
'emails' => [
'admin' => 'admin@example.com',
],
]
```
## Conversion d'objets en tableaux <span id="converting-objects-to-arrays"></span>
Il arrive souvent que vous ayez besoin de convertir un objet, ou un tableau d'objets, en tableau. Le cas le plus courant est la conversion de modèles d'enregistrements actifs afin de servir des tableaux de données via une API REST ou pour un autre usage. Le code suivant peut alors être utilisé :
```php
$posts = Post::find()->limit(10)->all();
$data = ArrayHelper::toArray($posts, [
'app\models\Post' => [
'id',
'title',
// the key name in array result => property name
'createTime' => 'created_at',
// the key name in array result => anonymous function
'length' => function ($post) {
return strlen($post->content);
},
],
]);
```
Le premier argument contient les données à convertir. Dans notre cas, nous convertissons un modèle d'enregistrements actifs `Post`.
The second argument est un tableau de mise en correspondance de conversions par classe. Nous définissons une mise en correspondance pour le modèle `Post`. Chaque tableau de mise en correspondance contient un jeu de mise en correspondance. Chaque mise en correspondance peut être :
- Un nom de champ à inclure tel quel.
- Une paire clé-valeur dans laquelle la clé est donnée sous forme de chaîne de caractères et la valeur sous forme du nom de la colonne dont on doit prendre la valeur.
- Une paire clé-valeur dans laquelle la clé est donnée sous forme de chaîne de caractères et la valeur sous forme de fonction de rappel qui la retourne.
Le résultat de la conversion ci-dessus pour un modèle unique est :
```php
[
'id' => 123,
'title' => 'test',
'createTime' => '2013-01-01 12:00AM',
'length' => 301,
]
```
Il est possible de fournir une manière par défaut de convertir un objet en tableau pour une classe spécifique en implémentant l'interface [[yii\base\Arrayable|Arrayable]] dans cette classe.
## Test de l'appartenance à un tableau <span id="testing-arrays"></span>
Souvent, vous devez savoir si un élément se trouve dans un tableau ou si un jeu d'éléments est un sous-ensemble d'un autre. Bien que PHP offre la fonction `in_array()`, cette dernière ne prend pas en charge les sous-ensembles ou les objets `\Traversable`.
Pour faciliter ce genre de tests, [[yii\helpers\ArrayHelper]] fournit les méthodes [[yii\helpers\ArrayHelper::isIn()|isIn()]]
et [[yii\helpers\ArrayHelper::isSubset()|isSubset()]] avec la même signature que [in_array()](http://php.net/manual/en/function.in-array.php).
```php
// true
ArrayHelper::isIn('a', ['a']);
// true
ArrayHelper::isIn('a', new ArrayObject(['a']));
// true
ArrayHelper::isSubset(new ArrayObject(['a', 'c']), new ArrayObject(['a', 'b', 'c']));
```

396
docs/guide-fr/helper-html.md

@ -0,0 +1,396 @@
Classe assistante Html
======================
Toutes les applications Web génèrent un grand nombre de balises HTML. Si le code HTML est statique, il peut être créé efficacement sous forme de [mélange de code PHP et de code HTML dans un seul fichier](http://php.net/manual/en/language.basic-syntax.phpmode.php), mais lorsqu'il est généré dynamiquement, cela commence à être compliqué à gérer sans une aide supplémentaire. Yii fournit une telle aide sous la forme de la classe assistante Html, qui offre un jeu de méthodes statiques pour manipuler les balises Html les plus courantes, leurs options et leur contenu.
> Note: si votre code HTML est presque statique, il vaut mieux utiliser HTML directement. Il n'est pas nécessaire d'envelopper tout dans des appels aux méthodes de la classe assistante Html.
## Les bases <span id="basics"></span>
Comme la construction de code HTML dynamique en concaténant des chaînes de caractère peut très vite tourner à la confusion, Yii fournit un jeu de méthodes pour manipuler les options de balises et construire des balises s'appuyant sur ces options.
### Génération de balises <span id="generating-tags"></span>
Le code pour générer une balise ressemble à ceci :
```php
<?= Html::tag('p', Html::encode($user->name), ['class' => 'username']) ?>
```
Le premier argument est le nom de la balise. Le deuxième est le contenu qui apparaît entre l'ouverture de la balise et sa fermeture.
Notez que nous utilisons `Html::encode` – c'est parce que le contenu n'est pas encodé automatiquement pour permetre l'utilisation de HTML quand c'est nécessaire.
Le troisième est un tableau d'options HTML ou, en d'autres mots, les attributs de la balise.
Dans ce tableau, la clé est le nom de l'attribut (comme `class`, `href` ou `target`) et la valeur est sa valeur.
Le code ci-dessus génère le code HTML suivant :
```html
<p class="username">samdark</p>
```
Dans le cas où vous avez simplement besoin d'ouvrir ou de fermer la balise, vous pouvez utiliser les méthodes `Html::beginTag()` et `Html::endTag()`.
Des options sont utilisées dans de nombreuses méthodes de la classe assistante Html et de nombreux composants graphiques (widgets). Dans tous ces cas, il y a quelques manipulations supplémentaires à connaître :
- Si une valeur est `null`, l'attribut correspondant n'est pas rendu.
- Les attributs du type booléen sont traités comme des
[attributs booléens ](http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes).
- Les valeurs des attributs sont encodés HTML à l'aide de la méthode [[yii\helpers\Html::encode()|Html::encode()]].
- Si la valeur d'un attribut est un tableau, il est géré comme suit :
* Si l'attribut est un attribut de donnée tel que listé dans [[yii\helpers\Html::$dataAttributes]], tel que `data` ou `ng`,
une liste d'attributs est rendue, un pour chacun des élément dans le tableau de valeurs. Par exemple,
`'data' => ['id' => 1, 'name' => 'yii']` génère `data-id="1" data-name="yii"`; et
`'data' => ['params' => ['id' => 1, 'name' => 'yii'], 'status' => 'ok']` génère
`data-params='{"id":1,"name":"yii"}' data-status="ok"`. Notez que dans le dernier exemple le format JSON est utilisé pour rendre le sous-tableau.
* Si l'attribut n'est PAS un attribut de donnée, la valeur est encodée JSON. Par exemple,
`['params' => ['id' => 1, 'name' => 'yii']` génère `params='{"id":1,"name":"yii"}'`.
### Formation des classes et des styles CSS <span id="forming-css"></span>
Lors de la construction des options pour des balises HTML, nous démarrons souvent avec des valeurs par défaut qu'il faut modifier. Afin d'ajouter ou de retirer une classe, vous pouvez utiliser ce qui suit :
```php
$options = ['class' => 'btn btn-default'];
if ($type === 'success') {
Html::removeCssClass($options, 'btn-default');
Html::addCssClass($options, 'btn-success');
}
echo Html::tag('div', 'Pwede na', $options);
// si la valeur de $type est 'success' le rendu sera
// <div class="btn btn-success">Pwede na</div>
```
Vous pouvez spécifier de multiples classe CSS en utilisant le tableau de styles également :
```php
$options = ['class' => ['btn', 'btn-default']];
echo Html::tag('div', 'Save', $options);
// rend '<div class="btn btn-default">Save</div>'
```
Vous pouvez aussi utiliser le tableau de styles pour ajouter ou retirer des classes :
```php
$options = ['class' => 'btn'];
if ($type === 'success') {
Html::addCssClass($options, ['btn-success', 'btn-lg']);
}
echo Html::tag('div', 'Save', $options);
// rend '<div class="btn btn-success btn-lg">Save</div>'
```
`Html::addCssClass()` empêche la duplication, vous n'avez donc pas à vous préoccuper de savoir si une classe apparaît deux fois :
```php
$options = ['class' => 'btn btn-default'];
Html::addCssClass($options, 'btn-default'); // class 'btn-default' is already present
echo Html::tag('div', 'Save', $options);
// rend '<div class="btn btn-default">Save</div>'
```
Si l'option classe CSS est spécifiée en utilisant le tableau de styles, vous pouvez utiliser une clé nommée pour indiquer le but logique de la classe. Dans ce cas, une classe utilisant la même clé dans le tableau de styles passé à `Html::addClass()` est ignorée :
```php
$options = [
'class' => [
'btn',
'theme' => 'btn-default',
]
];
Html::addCssClass($options, ['theme' => 'btn-success']); // la clé 'theme' est déjà utilisée
echo Html::tag('div', 'Save', $options);
// rend '<div class="btn btn-default">Save</div>'
```
Les styles CSS peuvent être définis d'une façon similaire en utilisant l'attribut `style` :
```php
$options = ['style' => ['width' => '100px', 'height' => '100px']];
// donne style="width: 100px; height: 200px; position: absolute;"
Html::addCssStyle($options, 'height: 200px; position: absolute;');
// gives style="position: absolute;"
Html::removeCssStyle($options, ['width', 'height']);
```
Lors de l'utilisation de [[yii\helpers\Html::addCssStyle()|addCssStyle()]], vous pouvez spécifier soit un tableau de paires clé-valeur qui correspond aux propriétés CSS noms et valeurs, soit une chaîne de caractères telle que `width: 100px; height: 200px;`. Ces formats peuvent être convertis de l'un en l'autre en utilisant les méthodes [[yii\helpers\Html::cssStyleFromArray()|cssStyleFromArray()]] et
[[yii\helpers\Html::cssStyleToArray()|cssStyleToArray()]]. La méthode [[yii\helpers\Html::removeCssStyle()|removeCssStyle()]]
accepte un tableau de propriétés à retirer. S'il s'agit d'une propriété unique, elle peut être spécifiée sous forme de chaîne de caractères.
### Encodage et décodage du contenu <span id="encoding-and-decoding-content"></span>
Pour que le contenu puisse être affiché en HTML de manière propre et en toute sécurité, les caractères spéciaux du contenu doivent être encodés. En PHP, cela s'obtient avec [htmlspecialchars](http://www.php.net/manual/en/function.htmlspecialchars.php) et
[htmlspecialchars_decode](http://www.php.net/manual/en/function.htmlspecialchars-decode.php). Le problème rencontré en utilisant ces méthodes directement est que vous devez spécifier l'encodage et des options supplémentaires tout le temps. Comme ces options restent toujours les mêmes et que l'encodage doit correspondre à celui de l'application pour éviter les problèmes de sécurité, Yii fournit deux méthodes compactes et faciles à utiliser :
```php
$userName = Html::encode($user->name);
echo $userName;
$decodedUserName = Html::decode($userName);
```
## Formulaires <span id="forms"></span>
Manipuler des formulaires dans le code HTML est tout à fait répétitif et sujet à erreurs. À cause de cela, il existe un groupe de méthodes pour aider à les manipuler.
> Note : envisagez d'utiliser [[yii\widgets\ActiveForm|ActiveForm]] dans le cas où vous avez affaire à des modèles et que ces derniers doivent être validés.
### Création de formulaires <span id="creating-forms"></span>
Les formulaires peut être ouverts avec la méthode [[yii\helpers\Html::beginForm()|beginForm()]] comme ceci :
```php
<?= Html::beginForm(['order/update', 'id' => $id], 'post', ['enctype' => 'multipart/form-data']) ?>
```
Le premier argument est l'URL à laquelle le formulaire sera soumis. Il peut être spécifié sous la forme d'une route Yii et de paramètres acceptés par [[yii\helpers\Url::to()|Url::to()]].
Le deuxième est la méthode à utiliser. `post` est la méthode par défaut. Le troisième est un tableau d'options pour la balise form. Dans ce cas, nous modifions l'encodage des données du formulaire dans la requête POST en `multipart/form-data`, ce qui est requis pour envoyer des fichiers.
La fermeture du formulaire se fait simplement par :
```php
<?= Html::endForm() ?>
```
### Boutons <span id="buttons"></span>
Pour générer des boutons, vous pouvez utiliser le code suivant :
```php
<?= Html::button('Pressez-mo!', ['class' => 'teaser']) ?>
<?= Html::submitButton('Envoyer', ['class' => 'submit']) ?>
<?= Html::resetButton('Ré-initialiser', ['class' => 'reset']) ?>
```
Le premier argument pour les trois méthodes est l'intitulé du bouton, le deuxième est un tableau d'options.
L'intitulé n'est pas encodé, mais si vous affichez des données en provenance de l'utilisateur, encodez les avec [[yii\helpers\Html::encode()|Html::encode()]].
### Champs d'entrée <span id="input-fields"></span>
Il y a deux groupes de méthodes d'entrée de données. Celles qui commencent par `active`, est qui sont appelées entrées actives, et celles qui ne commencent pas par ce mot. Les entrées actives prennent leurs données dans le modèle à partir des attributs spécifiés, tandis que pour les entrées régulières, les données sont spécifiées directement.
Les méthodes les plus génériques sont :
```php
type, nom de l'entrée, valeur de l'entrée, options
<?= Html::input('text', 'username', $user->name, ['class' => $username]) ?>
type, modèle, nom de l'attribut du modèle, options
<?= Html::activeInput('text', $user, 'name', ['class' => $username]) ?>
```
Si vous connaissez le type de l'entrée à l'avance, il est plus commode d'utiliser les méthodes raccourcis :
- [[yii\helpers\Html::buttonInput()]]
- [[yii\helpers\Html::submitInput()]]
- [[yii\helpers\Html::resetInput()]]
- [[yii\helpers\Html::textInput()]], [[yii\helpers\Html::activeTextInput()]]
- [[yii\helpers\Html::hiddenInput()]], [[yii\helpers\Html::activeHiddenInput()]]
- [[yii\helpers\Html::passwordInput()]] / [[yii\helpers\Html::activePasswordInput()]]
- [[yii\helpers\Html::fileInput()]], [[yii\helpers\Html::activeFileInput()]]
- [[yii\helpers\Html::textarea()]], [[yii\helpers\Html::activeTextarea()]]
Les listes radio et les boîtes à cocher sont un peu différentes en matière de signature de méthode :
```php
<?= Html::radio('agree', true, ['label' => 'I agree']);
<?= Html::activeRadio($model, 'agree', ['class' => 'agreement'])
<?= Html::checkbox('agree', true, ['label' => 'I agree']);
<?= Html::activeCheckbox($model, 'agree', ['class' => 'agreement'])
```
Les listes déroulantes et les boîtes listes peuvent être rendues comme suit :
```php
<?= Html::dropDownList('list', $currentUserId, ArrayHelper::map($userModels, 'id', 'name')) ?>
<?= Html::activeDropDownList($users, 'id', ArrayHelper::map($userModels, 'id', 'name')) ?>
<?= Html::listBox('list', $currentUserId, ArrayHelper::map($userModels, 'id', 'name')) ?>
<?= Html::activeListBox($users, 'id', ArrayHelper::map($userModels, 'id', 'name')) ?>
```
Le premier argument est le nom de l'entrée, le deuxième est la valeur sélectionnée actuelle et le troisième est un tableau de paires clé-valeur, dans lequel la clé est la valeur d'entrée dans la liste et la valeur est l'étiquette qui correspond à cette valeur dans la liste.
Si vous désirez que des choix multiples soient sélectionnables, vous pouvez utiliser la liste à sélection multiples (checkbox list) :
```php
<?= Html::checkboxList('roles', [16, 42], ArrayHelper::map($roleModels, 'id', 'name')) ?>
<?= Html::activeCheckboxList($user, 'role', ArrayHelper::map($roleModels, 'id', 'name')) ?>
```
Sinon utilisez la liste radio :
```php
<?= Html::radioList('roles', [16, 42], ArrayHelper::map($roleModels, 'id', 'name')) ?>
<?= Html::activeRadioList($user, 'role', ArrayHelper::map($roleModels, 'id', 'name')) ?>
```
### Étiquettes et erreurs <span id="labels-and-errors"></span>
Comme pour les entrées, il existe deux méthodes pour générer les étiquettes de formulaire. Celles pour les entrées « actives » qui prennent leurs étiquettes dans le modèle, et celles « non actives » qui sont étiquetées directement :
```php
<?= Html::label('User name', 'username', ['class' => 'label username']) ?>
<?= Html::activeLabel($user, 'username', ['class' => 'label username']) ?>
```
Pour afficher les erreurs de formulaire à partir d'un modèle ou sous forme de résumé pour un modèle, vous pouvez utiliser :
```php
<?= Html::errorSummary($posts, ['class' => 'errors']) ?>
```
Pour afficher une erreur individuellement :
```php
<?= Html::error($post, 'title', ['class' => 'error']) ?>
```
### Nom et valeur des entrées <span id="input-names-and-values"></span>
Il existe deux méthodes pour obtenir des noms, des identifiants et des valeurs pour des champs d'entrée basés sur un modèle. Elles sont essentiellement utilisées en interne, mais peuvent être pratiques quelques fois :
```php
// Post[title]
echo Html::getInputName($post, 'title');
// post-title
echo Html::getInputId($post, 'title');
// my first post
echo Html::getAttributeValue($post, 'title');
// $post->authors[0]
echo Html::getAttributeValue($post, '[0]authors[0]');
```
Dans ce qui précède, le premier argument est le modèle, tandis que le deuxième est l'expression d'attribut. Dans sa forme la plus simple, l'expression est juste un nom d'attribut, mais il peut aussi s'agir d'un nom d'attribut préfixé et-ou suffixé par des index de tableau, ce qui est essentiellement le cas pour des entrées tabulaires :
- `[0]content` est utilisé dans des entrées de données tabulaires pour représenter l'attribut `content` pour le premier modèle des entrées tabulaires ;
- `dates[0]` représente le premier élément du tableau de l'attribut `dates` ;
- `[0]dates[0]` représente le premier élément du tableau de l'attribut `dates` pour le premier modèle des entrées tabulaires.
Afin d'obtenir le nom de l'attribut sans suffixe ou préfixe, vous pouvez utiliser ce qui suit :
```php
// dates
echo Html::getAttributeName('dates[0]');
```
## Styles et scripts <span id="styles-and-scripts"></span>
Il existe deux méthodes pour générer les balises enveloppes des styles et des scripts :
```php
<?= Html::style('.danger { color: #f00; }') ?>
Produit
<style>.danger { color: #f00; }</style>
<?= Html::script('alert("Hello!");', ['defer' => true]);
Produit
<script defer>alert("Hello!");</script>
```
Si vous désirez utiliser utiliser un style externe d'un fichier CSS :
```php
<?= Html::cssFile('@web/css/ie5.css', ['condition' => 'IE 5']) ?>
génère
<!--[if IE 5]>
<link href="http://example.com/css/ie5.css" />
<![endif]-->
```
Le premier argument est l'URL. Le deuxième est un tableau d'options. En plus des options normales, vous pouvez spécifier :
- `condition` pour envelopper `<link` dans des commentaires conditionnels avec la condition spécifiée. Nous espérons que vous n'aurez jamais besoin de commentaires conditionnels ;
- `noscript` peut être défini à `true` pour envelopper `<link` dans une balise `<noscript>` de façon à ce qu'elle soit incluse seulement si le navigateur ne prend pas en charge JavaScript ou si l'utilisateur l'a désactivé.
Pour lier un fichier JavaScript :
```php
<?= Html::jsFile('@web/js/main.js') ?>
```
Se passe comme avec CSS, le premier argument spécifie l'URL du fichier à inclure. Les options sont passées via le deuxième argument. Dans les options vous pouvez spécifier `condition` de la même manière que dans les options pour un fichier CSS (méthode `cssFile`).
## Hyperliens <span id="hyperlinks"></span>
Il y a une méthode commode pour générer les hyperliens :
```php
<?= Html::a('Profile', ['user/view', 'id' => $id], ['class' => 'profile-link']) ?>
```
Le premier argument est le titre. Il n'est pas encodé, mais si vous utilisez des données entrées par l'utilisateur, vous devez les encoder avec `Html::encode()`. Le deuxième argument est ce qui se retrouvera dans l'attribut `href` de la balise `<a`.
Voir [Url::to()](helper-url.md) pour les détails sur les valeurs acceptées.
Le troisième argument est un tableau pour les attributs de la balise.
Si vous devez générer des liens `mailto`, vous pouvez utiliser le code suivant :
```php
<?= Html::mailto('Contact us', 'admin@example.com') ?>
```
## Images <span id="images"></span>
Pour générer une balise image, utilisez le code suivant :
```php
<?= Html::img('@web/images/logo.png', ['alt' => 'My logo']) ?>
qui génère
<img src="http://example.com/images/logo.png" alt="My logo" />
```
En plus des [alias](concept-aliases.md), le premier argument accepte les routes, les paramètres et les URL, tout comme [Url::to()](helper-url.md).
## Listes <span id="lists"></span>
Les listes non ordonnées peuvent être générées comme suit :
```php
<?= Html::ul($posts, ['item' => function($item, $index) {
return Html::tag(
'li',
$this->render('post', ['item' => $item]),
['class' => 'post']
);
}]) ?>
```
Pour une liste ordonnée, utilisez plutôt `Html::ol()`.

68
docs/guide-fr/helper-overview.md

@ -0,0 +1,68 @@
Classes assistantes
===================
> Note: cette section est en cours de développement.
Yii procure de nombreuses classes qui vous aident à simplifier le code de tâches courantes, telles que la manipulation de chaînes de caractères ou de tableaux, la génération de code HTML, et ainsi de suite. Ces classes assistantes sont organisées dans l'espace de noms `yii\helpers` et sont toutes des classes statiques (ce qui signifie qu'elles ne contiennent que des propriétés et des méthodes statiques et ne doivent jamais être instanciées).
Vous utilisez une classe assistante en appelant directement une de ses méthodes statiques, comme ceci :
```php
use yii\helpers\Html;
echo Html::encode('Test > test');
```
> Note: pour prendre en charge la [personnalisation des classes assistantes](#customizing-helper-classes), Yii éclate chacune des classes assistantes du noyau en deux classes : une classe de base (p. ex. `BaseArrayHelper`) et une classe concrète (p. ex. `ArrayHelper`). Lorsque vous utilisez une classe assistante, vous devez utiliser la version concrète uniquement et ne jamais utiliser la classe de base.
Classes assistantes du noyau
----------------------------
Les versions de Yii fournissent les classes assistantes du noyau suivantes :
- [ArrayHelper](helper-array.md)
- Console
- FileHelper
- FormatConverter
- [Html](helper-html.md)
- HtmlPurifier
- Imagine (provided by yii2-imagine extension)
- Inflector
- Json
- Markdown
- StringHelper
- [Url](helper-url.md)
- VarDumper
Personnalisation des classes assistantes <span id="customizing-helper-classes"></span>
----------------------------------------
Pour personnaliser une classe assistante du noyau (p. ex. [[yii\helpers\ArrayHelper]]), vous devez créer une nouvelle classe qui étend la classe de base correspondant à la classe assistante (p. ex. [[yii\helpers\ArrayHelper]]), y compris son espace de noms. Cette classe sera ensuite configurée pour remplacer l'implémentation originale de Yii.
L'exemple qui suit montre comment personnaliser la méthode [[yii\helpers\ArrayHelper::merge()|merge()]] de la classe [[yii\helpers\ArrayHelper]] :
```php
<?php
namespace yii\helpers;
class ArrayHelper extends BaseArrayHelper
{
public static function merge($a, $b)
{
// votre implémentation personnalisée
}
}
```
Sauvegardez votre classe dans un fichier nommé `ArrayHelper.php`. Le fichier peut se trouver dans n'importe quel dossier, par exemple, `@app/components`.
Ensuite, dans le [script d'entrée](structure-entry-scripts.md) de votre application, ajoutez la ligne de code suivante, après l'inclusion du fichier `yii.php` pour dire à la [classe autoloader de Yii](concept-autoloading.md) de charger votre classe personnalisée au lieu de la classe assistance originale de Yii.
```php
Yii::$classMap['yii\helpers\ArrayHelper'] = '@app/components/ArrayHelper.php';
```
Notez que la personnalisation d'une classe assistante n'est utile que si vous désirez changer le comportement d'une fonction existante de la classe assistante. Si vous désirez ajouter une fonction additionnelle à utiliser dans votre application, le mieux est de créer une classe assistante séparée pour cela.

161
docs/guide-fr/helper-url.md

@ -0,0 +1,161 @@
Classe assistante Url
=====================
La classe assistante Url fournit un jeu de méthodes statiques pour gérer les URL.
## Obtenir des URL communes <span id="getting-common-urls"></span>
Vous pouvez utiliser deux méthodes pour obtenir des URL communes : l'URL de la page d'accueil et l'URL de base de la requête courante. Pour obtenir l'URL de la page d'accueil, utilisez ce qui suit :
```php
$relativeHomeUrl = Url::home();
$absoluteHomeUrl = Url::home(true);
$httpsAbsoluteHomeUrl = Url::home('https');
```
Si aucun paramètre n'est passé, l'URL générée est relative. Vous pouvez passer `true` pour obtenir une URL absolue pour le schéma courant ou spécifier un schéma explicitement (`https`, `http`).
Pour obtenir l'URL de base de la requête courante utilisez ceci :
```php
$relativeBaseUrl = Url::base();
$absoluteBaseUrl = Url::base(true);
$httpsAbsoluteBaseUrl = Url::base('https');
```
L'unique paramètre de la méthode fonctionne comme pour `Url::home()`.
## Création d'URL <span id="creating-urls"></span>
En vue de créer une URL pour une route donnée, utilisez la méthode `Url::toRoute()`. La méthode utilise [[\yii\web\UrlManager]] pour créer une URL :
```php
$url = Url::toRoute(['product/view', 'id' => 42]);
```
Vous pouvez spécifier la route sous forme de chaîne de caractère, p. ex. `site/index`. Vous pouvez également utiliser un tableau si vous désirez spécifier des paramètres de requête supplémentaires pour l'URL créée. Le format du tableau doit être :
```php
// génère : /index.php?r=site%2Findex&param1=value1&param2=value2
['site/index', 'param1' => 'value1', 'param2' => 'value2']
```
Si vous voulez créer une URL avec une ancre, vous pouvez utiliser le format de tableau avec un paramètre `#`. Par exemple :
```php
// génère: /index.php?r=site%2Findex&param1=value1#name
['site/index', 'param1' => 'value1', '#' => 'name']
```
Une route peut être ,soit absolue, soit relative. Une route absolue commence par une barre oblique de division (p. ex. `/site/index`) tandis que route relative commence sans ce caractère (p. ex. `site/index` ou `index`). Une route relative peut être convertie en une route absolue en utilisant une des règles suivantes :
- Si la route est une chaîne de caractères vide, la [[\yii\web\Controller::route|route]] est utilisée ;
- Si la route ne contient aucune barre oblique de division (p. ex. `index`), elle est considérée être un identifiant d'action dans le contrôleur courant et sera préfixée par l'identifiant du contrôleur ([[\yii\web\Controller::uniqueId]]);
- Si la route ne commence pas par une barre oblique de division (p. ex. `site/index`), elle est considérée être une route relative au module courant et sera préfixée par l'identifiant du module ([[\yii\base\Module::uniqueId|uniqueId]]).
Depuis la version 2.0.2, vous pouvez spécifier une route sous forme d'[alias](concept-aliases.md). Si c'est le cas, l'alias sera d'abord converti en la route réelle puis transformé en une route absolue en respectant les règles ci-dessus.
Voci quelques exemple d'utilisation de cette méthode :
```php
// /index.php?r=site%2Findex
echo Url::toRoute('site/index');
// /index.php?r=site%2Findex&src=ref1#name
echo Url::toRoute(['site/index', 'src' => 'ref1', '#' => 'name']);
// /index.php?r=post%2Fedit&id=100 assume the alias "@postEdit" is defined as "post/edit"
echo Url::toRoute(['@postEdit', 'id' => 100]);
// http://www.example.com/index.php?r=site%2Findex
echo Url::toRoute('site/index', true);
// https://www.example.com/index.php?r=site%2Findex
echo Url::toRoute('site/index', 'https');
```
Il existe une autre méthode `Url::to()` très similaire à [[toRoute()]]. La seule différence est que cette méthode requiert la spécification d'une route sous forme de tableau seulement. Si une chaîne de caractères est données, elle est traitée comme une URL.
Le premier argument peut être :
- un tableau : [[toRoute()]] sera appelée pour générer l'URL. Par exemple :
`['site/index']`, `['post/index', 'page' => 2]`. Reportez-vous à la méthode [[toRoute()]] pour plus de détails sur la manière de spécifier une route.
- une chaîne de caractères commençant par `@`: elle est traitée commme un alias, et la chaine aliasée correspondante est retournée ;
- une chaîne de caractères vide : l'URL couramment requise est retournée ;
- une chaîne de caractères normale : elle est retournée telle que.
Lorsque `$scheme` est spécifié (soit une chaîne de caractères, soit `true`), une URL absolue avec l'information hôte tirée de [[\yii\web\UrlManager::hostInfo]]) est retournée. Si`$url` est déjà une URL absolue, son schéma est remplacé par celui qui est spécifié.
Voici quelques exemples d'utilisation :
```php
// /index.php?r=site%2Findex
echo Url::to(['site/index']);
// /index.php?r=site%2Findex&src=ref1#name
echo Url::to(['site/index', 'src' => 'ref1', '#' => 'name']);
// /index.php?r=post%2Fedit&id=100 assume the alias "@postEdit" is defined as "post/edit"
echo Url::to(['@postEdit', 'id' => 100]);
// l'URL couramment requise
echo Url::to();
// /images/logo.gif
echo Url::to('@web/images/logo.gif');
// images/logo.gif
echo Url::to('images/logo.gif');
// http://www.example.com/images/logo.gif
echo Url::to('@web/images/logo.gif', true);
// https://www.example.com/images/logo.gif
echo Url::to('@web/images/logo.gif', 'https');
```
Depuis la version 2.0.3, vous pouvez utiliser [[yii\helpers\Url::current()]] pour créer une URL basée sur la route couramment requise et sur les paramètres de la méthode GET. Vous pouvez modifier ou retirer quelques uns des paramètres GET et en ajouter d'autres en passant le paramètre `$params` à la méthode. Par exemple :
```php
// suppose que $_GET = ['id' => 123, 'src' => 'google'],et que la route courante est "post/view"
// /index.php?r=post%2Fview&id=123&src=google
echo Url::current();
// /index.php?r=post%2Fview&id=123
echo Url::current(['src' => null]);
// /index.php?r=post%2Fview&id=100&src=google
echo Url::current(['id' => 100]);
```
## Se souvenir d'URL <span id="remember-urls"></span>
Il y a des cas dans lesquels vous avez besoin de mémoriser une URL et ensuite de l'utiliser durant le traitement d'une des requêtes séquentielles. Cela peut être fait comme suit :
```php
// se souvenir de l'URL courante
Url::remember();
// Se souvenir de l'URL spécifiée. Voir Url::to() pour le format des arguments.
Url::remember(['product/view', 'id' => 42]);
// Se souvenir de l'URL spécifiée avec un nom
Url::remember(['product/view', 'id' => 42], 'product');
```
Dans la prochaine requête, vous pouvez récupérer l'URL mémorisée comme ceci :
```php
$url = Url::previous();
$productUrl = Url::previous('product');
```
## Vérification des URL relatives <span id="checking-relative-urls"></span>
Pour savoir si une URL est relative, c.-à-d. n'a pas de partie « hôte », vous pouvez utiliser le code suivant :
```php
$isRelative = Url::isRelative('test/it');
```

2
docs/guide-fr/input-file-upload.md

@ -67,7 +67,7 @@ use yii\widgets\ActiveForm;
Il est important de se rappeler que vous devez ajouter l'option `enctype` au formulaire afin que le fichier soit proprement chargé sur le serveur. L'appel de `fileInput()` rend une balise `<input type="file">` qui permet à l'utilisateur de sélectionner un fichier à charger sur le serveur.
> Tip: depuis la version 2.0.8, [[yii\web\widgets\ActiveField::fileInput|fileInput]] ajoute l'option `enctype` au formulaire automatiquement lorsqu'un champ d'entrée de fichier est utilisé.
> Tip: depuis la version 2.0.8, [[yii\widgets\ActiveField::fileInput|fileInput]] ajoute l'option `enctype` au formulaire automatiquement lorsqu'un champ d'entrée de fichier est utilisé.
## Câblage <span id="wiring-up"></span>

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

@ -40,7 +40,7 @@ dengan menjalankan `composer self-update`.
Dengan Komposer diinstal, Anda dapat menginstal Yii dengan menjalankan perintah berikut di bawah folder yang terakses web:
```bash
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
```

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

@ -27,7 +27,7 @@ Se hai già Composer installato assicurati di avere una versione aggiornata. Puo
Una volta installato Composer, puoi installare Yii eseguendo questo comando in una directory accessbile via web:
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
Il primo comando installa il [plugin composer asset](https://github.com/francoispluchino/composer-asset-plugin/)

2
docs/guide-ja/input-file-upload.md

@ -79,7 +79,7 @@ use yii\widgets\ActiveForm;
ファイルが正しくアップロードされるように、フォームに `enctype` オプションを追加することを憶えておくのは重要なことです。
`fileInput()` を呼ぶと `<input type="file">` のタグがレンダリングされて、ユーザがアップロードするファイルを選ぶことが出来るようになります。
> Tip: バージョン 2.0.8 以降では、ファイルインプットのフィールドが使われているときは、[[yii\web\widgets\ActiveField::fileInput|fileInput]] がフォームに `enctype` オプションを自動的に追加します。
> Tip: バージョン 2.0.8 以降では、ファイルインプットのフィールドが使われているときは、[[yii\widgets\ActiveField::fileInput|fileInput]] がフォームに `enctype` オプションを自動的に追加します。
## 繋ぎ合せる <span id="wiring-up"></span>

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

@ -55,7 +55,7 @@ Composer は `composer self-update` コマンドを実行してアップデー
Composer がインストールされたら、ウェブからアクセスできるフォルダで下記のコマンドを実行することによって Yii をインストールすることが出来ます。
```bash
composer global require "fxp/composer-asset-plugin:~1.2.0"
composer global require "fxp/composer-asset-plugin:~1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
```

2
docs/guide-ja/tutorial-start-from-scratch.md

@ -54,6 +54,6 @@ Yii の新しいプロジェクトテンプレートを作成するのに必要
これで、あなたのテンプレートを使ってプロジェクトを作成することが出来ます。
```
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist --stability=dev mysoft/yii2-app-coolone new-project
```

2
docs/guide-ja/tutorial-yii-integration.md

@ -77,7 +77,7 @@ Yii は数多くの優れた機能を提供していますので、サードパ
サードパーティのシステムが Composer を使って依存を管理している場合は、単に下記のコマンドを実行すれば Yii をインストールすることが出来ます。
composer global require "fxp/composer-asset-plugin:~1.2.0"
composer global require "fxp/composer-asset-plugin:~1.3.1"
composer require yiisoft/yii2
composer install

20
docs/guide-pl/README.md

@ -147,7 +147,7 @@ Narzędzia wspomagające tworzenie aplikacji
* [Pasek debugowania i debuger](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide/README.md)
* [Generowanie kodu przy użyciu Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide/README.md)
* **TBD** [Generowanie dokumentacji API](https://github.com/yiisoft/yii2-apidoc)
* [Generowanie dokumentacji API](https://github.com/yiisoft/yii2-apidoc)
Testowanie
@ -179,16 +179,16 @@ Tematy specjalne
Widżety
-------
* GridView: **TBD** link to demo page
* ListView: **TBD** link to demo page
* DetailView: **TBD** link to demo page
* ActiveForm: **TBD** link to demo page
* Pjax: **TBD** link to demo page
* Menu: **TBD** link to demo page
* LinkPager: **TBD** link to demo page
* LinkSorter: **TBD** link to demo page
* [GridView](http://www.yiiframework.com/doc-2.0/yii-grid-gridview.html)
* [ListView](http://www.yiiframework.com/doc-2.0/yii-widgets-listview.html)
* [DetailView](http://www.yiiframework.com/doc-2.0/yii-widgets-detailview.html)
* [ActiveForm](http://www.yiiframework.com/doc-2.0/guide-input-forms.html#activerecord-based-forms-activeform)
* [Pjax](http://www.yiiframework.com/doc-2.0/yii-widgets-pjax.html)
* [Menu](http://www.yiiframework.com/doc-2.0/yii-widgets-menu.html)
* [LinkPager](http://www.yiiframework.com/doc-2.0/yii-widgets-linkpager.html)
* [LinkSorter](http://www.yiiframework.com/doc-2.0/yii-widgets-linksorter.html)
* [Widżety Bootstrapowe](https://github.com/yiisoft/yii2-bootstrap/blob/master/docs/guide/README.md)
* [Widżety Jquery UI](https://github.com/yiisoft/yii2-jui/blob/master/docs/guide/README.md)
* [Widżety jQuery UI](https://github.com/yiisoft/yii2-jui/blob/master/docs/guide/README.md)
Klasy pomocnicze

3
docs/guide-pl/caching-overview.md

@ -2,8 +2,7 @@ Pamięć podręczna
================
Mechanizmy wykorzystujące pamięć podręczną pozwalają na poprawienie wydajności aplikacji sieciowej w tani i efektywny sposób.
Zapisanie mniej lub bardziej statycznych danych w pamięci podręcznej i serwowanie ich stamtąd, zamiast generować je od podstaw przy każdym
wywołaniu, pozwala na znaczne zaoszczędzenie czasu odpowiedzi aplikacji.
Zapisanie statycznych danych w pamięci podręcznej, zamiast generowania ich od podstaw przy każdym wywołaniu, pozwala na znaczne zaoszczędzenie czasu odpowiedzi aplikacji.
Zapis pamięci podręcznej może odbywać się na wielu poziomach i w wielu miejscach aplikacji. Po stronie serwera, na niskim poziomie,
można wykorzystać pamięć podręczną do zapisania podstawowych danych, takich jak zbiór informacji o najnowszych artykułach pobieranych z bazy danych.

6
docs/guide-pl/caching-page.md

@ -5,7 +5,7 @@ Pamięć podręczna stron odnosi się do zapisu zawartości całej strony po str
zawartość zostanie wyświetlona od razu z pamięci podręcznej zamiast generować ją ponownie od podstaw.
Pamięć podręczna stron jest obsługiwana przez [filtr akcji](structure-filters.md) [[yii\filters\PageCache|PageCache]].
Poniżej znajdziesz przykładowy sposób użycia w klasie kontrolera:
Poniżej znajdziesz przykładowy sposób użycia go w klasie kontrolera:
```php
public function behaviors()
@ -27,13 +27,13 @@ public function behaviors()
}
```
W powyższym przykładzie kod zakłada użycie pamięci tylko dla akcji `index` - zawartość strony powinna zostać zapisana na maksymalnie
W powyższym przykładzie zakładamy użycie pamięci podręcznej tylko dla akcji `index` - zawartość strony powinna zostać zapisana na maksymalnie
60 sekund i powinna różnić się w zależności od wybranego w aplikacji języka. Dodatkowo, jeśli całkowita liczba postów w bazie danych ulegnie zmianie,
zawartość pamięci powinna natychmiast stracić ważność i zostać pobrana ponownie.
Jak widać, pamięć podręczna stron jest bardzo podobna do [pamięci podręcznej fragmentów](caching-fragment.md). W obu przypadkach można
użyć opcji takich jak `duration` (czas ważności), `dependencies` (zależności), `variations` (warianty) oraz `enabled` (flaga aktywowania).
Główną różnicą tych dwóch przypadków jest to, że pamięć podręczna stron jest implemetowana jako [filtr akcji](structure-filters.md), a
Główną różnicą w tych dwóch przypadkach jest to, że pamięć podręczna stron jest implemetowana jako [filtr akcji](structure-filters.md), a
pamięć podręczna fragmentów jako [widżet](structure-widgets.md).
Oczywiście nic nie stoi na przeszkodzie, aby używać [pamięci podręcznej fragmentów](caching-fragment.md) jak

2
docs/guide-pl/concept-components.md

@ -9,7 +9,7 @@ Trzy główne funkcjonalności, które zapewniają komponenty innym klasom to:
* [Behaviory (zachowania)](concept-behaviors.md)
Wszystkie razem i każda z tych funkcjonalności osobno zapewnia klasom Yii o wiele większą elastyczność i łatwość użycia. Dla przykładu,
dołączony [[yii\jui\DatePicker|widżet wybierania daty]], komponent interfejsu użytkownika, może być użyty w [widoku](structure-view.md),
dołączony [[yii\jui\DatePicker|widżet wybierania daty]], komponent interfejsu użytkownika, może być użyty w [widoku](structure-views.md),
aby wygenerować interaktywny kalendarz:
```php

170
docs/guide-pl/db-active-record.md

@ -47,9 +47,19 @@ W tej sekcji przewodnika opiszemy sposób użycia Active Record dla baz relacyjn
## Deklarowanie klas Active Record <span id="declaring-ar-classes"></span>
Na początek zadeklaruj klasę typu Active Record rozszerzając [[yii\db\ActiveRecord|ActiveRecord]]. Ponieważ każda klasa Active Record
jest powiązana z tabelą bazy danych, należy nadpisać metodę [[yii\db\ActiveRecord::tableName()|tableName()]], aby wskazać
odpowiednią tabelę.
Na początek zadeklaruj klasę typu Active Record rozszerzając [[yii\db\ActiveRecord|ActiveRecord]].
### Deklarowanie nazwy tabeli
Domyślnie każda klasa Active Record jest powiązana ze swoją tabelą w bazie danych.
Metoda [[yii\db\ActiveRecord::tableName()|tableName()]] zwraca nazwę tabeli konwertując nazwę klasy za pomocą [[yii\helpers\Inflector::camel2id()]].
Możesz przeciążyć tę metodę, jeśli tabela nie jest nazwana zgodnie z tą konwencją.
Identycznie zastosowany może być domyślny prefiks tabeli [[yii\db\Connection::$tablePrefix|tablePrefix]]. Przykładowo, jeśli
[[yii\db\Connection::$tablePrefix|tablePrefix]] to `tbl_`, tabelą klasy `Customer` staje się `tbl_customer`, a dla `OrderItem` jest to `tbl_order_item`.
Jeśli nazwa tabeli zostanie podana jako `{{%NazwaTabeli}}`, znak procent `%` zostanie zamieniony automatycznie na prefiks tabeli.
Dla przykładu, `{{%post}}` staje się `{{tbl_post}}`. Nawiasy wokół nazwy tabeli są używane dla odpowiedniego [podawania nazw w kwerendach SQL](db-dao.md#quoting-table-and-column-names).
W poniższym przykładzie deklarujemy klasę Active Record nazwaną `Customer` dla tabeli `customer` w bazie danych.
@ -68,11 +78,12 @@ class Customer extends ActiveRecord
*/
public static function tableName()
{
return 'customer';
return '{{customer}}';
}
}
```
### Aktywne rekordy nazywane są "modelami"
Instancje Active Record są traktowane jak [modele](structure-models.md). Z tego powodu zwykle dodajemy klasy Active Record
do przestrzeni nazw `app\models` (lub innej, przeznaczonej dla klas modeli).
@ -444,6 +455,26 @@ $customer->loadDefaultValues();
```
### Rzutowanie typów atrybutów <span id="attributes-typecasting"></span>
Po wypełnieniu rezultatem kwerendy, [[yii\db\ActiveRecord]] przeprowadza automatyczne rzutowanie typów na wartościach swoich atrybutów,
używając do tego celu informacji zawartych w [schemacie tabeli bazy danych](db-dao.md#database-schema). Pozwala to na prawidłowe przedstawienie
danych pobranych z kolumny tabeli zadeklarowanej jako liczba całkowita, w postaci wartości typu PHP integer w instancji klasy ActiveRecord (typu boolean jako boolean itp.).
Mechanizm rzutowania ma jednak kilka ograniczeń:
* Wartości typu zmiennoprzecinkowego nie są konwertowane na float, a zamiast tego są przedstawiane jako łańcuch znaków, aby zachować dokładność ich liczbowej prezentacji.
* Konwersja typu integer zależy od zakresu liczb całkowitych używanego systemu operacyjnego.
Wartości kolumn zadeklarowanych jako 'unsigned integer' lub 'big integer' będą przekonwertowane do PHP integer tylko na systemach 64-bitowych,
a na 32-bitowych będą przedstawione jako łańcuchy znaków.
Zwróć uwagę na to, że rzutowanie typów jest wykonywane tylko podczas wypełniania instancji ActiveRecord rezultatem kwerendy. Automatyczna konwersja nie jest przeprowadzana
dla wartości załadowanych poprzez żądanie HTTP lub ustawionych bezpośrednio dla właściwości klasy.
Schemat tabeli będzie również użyty do przygotowania instrukcji SQL przy zapisywaniu danych ActiveRecord, aby upewnić się, że wartości są przypisane w kwerendzie z prawidłowymi typami.
Atrybuty instancji ActiveRecord nie będą jednak przekonwertowane w procesie zapisywania.
> Tip: możesz użyć [[yii\behaviors\AttributeTypecastBehavior]], aby skonfigurować proces rzutowania typów dla wartości atrybutów w momencie ich walidacji lub zapisu.
### Aktualizowanie wielu wierszy jednocześnie <span id="updating-multiple-rows"></span>
Metody przedstawione powyżej działają na pojedynczych instancjach Active Record, dodając lub aktualizując indywidualne wiersze tabeli.
@ -575,9 +606,16 @@ try {
} catch(\Exception $e) {
$transaction->rollBack();
throw $e;
} catch(\Throwable $e) {
$transaction->rollBack();
throw $e;
}
```
> Note: w powyższym kodzie znajdują się dwa bloki catch dla kompatybilności
> z PHP 5.x i PHP 7.x. `\Exception` implementuje [interfejs `\Throwable`](http://php.net/manual/en/class.throwable.php)
> od PHP 7.0, zatem można pominąć część z `\Exception`, jeśli Twoja aplikacja używa tylko PHP 7.0 lub wyższego.
Drugi sposób polega na utworzeniu listy operacji bazodanowych, które wymagają transakcji za pomocą metody [[yii\db\ActiveRecord::transactions()|transactions()]].
Dla przykładu:
@ -961,7 +999,7 @@ W powyższym przykładzie modyfikujemy relacyjną kwerendę dodając warunek ze
>
> ```php
> $orders = Order::find()->select(['id', 'amount'])->with('customer')->all();
> // $orders[0]->customer ma zawsze wartość null. Aby rozwiązać ten problem, należy użyć:
> // $orders[0]->customer ma zawsze wartość `null`. Aby rozwiązać ten problem, należy użyć:
> $orders = Order::find()->select(['id', 'amount', 'customer_id'])->with('customer')->all();
> ```
@ -1065,6 +1103,16 @@ Od wersji 2.0.7, Yii udostępnia do tego celu skróconą metodę. Możliwe jest
$query->joinWith(['orders o'])->orderBy('o.id');
```
Powyższy kod działa dla prostych relacji. Jeśli jednak potrzebujesz aliasu dla tabeli dołączonej w zagnieżdżonej relacji,
np. `$query->joinWith(['orders.product'])`, musisz rozwinąć wywołanie `joinWith` jak w poniższym przykładzie:
```php
$query->joinWith(['orders o' => function($q) {
$q->joinWith('product p');
}])
->where('o.amount > 100');
```
### Odwrócone relacje <span id="inverse-relations"></span>
Deklaracje relacji są zazwyczaj obustronne dla dwóch klas Active Record. Przykładowo `Customer` jest powiązany z `Order` poprzez relację `orders`,
@ -1253,10 +1301,10 @@ Domyślnie wszystkie kwerendy Active Record używają klasy [[yii\db\ActiveQuery
należy nadpisać metodę [[yii\db\ActiveRecord::find()|find()]], aby zwracała instancję żądanej klasy kwerend. Przykład:
```php
// plik Comment.php
namespace app\models;
use yii\db\ActiveRecord;
use yii\db\ActiveQuery;
class Comment extends ActiveRecord
{
@ -1265,33 +1313,39 @@ class Comment extends ActiveRecord
return new CommentQuery(get_called_class());
}
}
class CommentQuery extends ActiveQuery
{
// ...
}
```
Od tego momentu, za każdym razem, gdy wykonywana będzie kwerenda (np. `find()`, `findOne()`) lub pobierana relacja (np. `hasOne()`) klasy `Comment`,
praca będzie odbywać się na instancji `CommentQuery` zamiast `ActiveQuery`.
> Tip: Dla dużych projektów rekomendowane jest, aby używać własnych, odpowiednio dopasowanych do potrzeb, klas kwerend, dzięki czemu klasy Active Record
> pozostają przejrzyste.
Możesz dopasować klasę kwerend do własnych potrzeb na wiele kreatywnych sposobów. Przykładowo, możesz zdefiniować nowe metody konstruujące zapytanie:
Teraz należy zdefiniować klasę `CommentQuery`, którą można dopasować do własnych kreatywnych potrzeb, dzięki czemu budowanie zapytań bazodanowych będzie o wiele bardziej ułatwione. Dla przykładu,
```php
// plik CommentQuery.php
namespace app\models;
use yii\db\ActiveQuery;
class CommentQuery extends ActiveQuery
{
// dodatkowe warunki relacyjnej kwerendy dołączone jako domyślne (ten krok można pominąć)
public function init()
{
$this->andOnCondition(['deleted' => false]);
parent::init();
}
// ... dodaj zmodyfikowane metody kwerend w tym miejscu ...
public function active($state = true)
{
return $this->andWhere(['active' => $state]);
return $this->andOnCondition(['active' => $state]);
}
}
```
> Note: Zwykle, zamiast wywoływać metodę [[yii\db\ActiveQuery::where()|where()]], powinno się używać metody
> [[yii\db\ActiveQuery::andWhere()|andWhere()]] lub [[yii\db\ActiveQuery::orWhere()|orWhere()]], aby dołączać kolejne warunki zapytania w
> Note: Zwykle, zamiast wywoływać metodę [[yii\db\ActiveQuery::onCondition()|onCondition()]], powinno się używać metody
> [[yii\db\ActiveQuery::andOnCondition()|andOnCondition()]] lub [[yii\db\ActiveQuery::orOnCondition()|orOnCondition()]], aby dołączać kolejne warunki zapytania w
> konstruktorze kwerend, dzięki czemu istniejące warunki nie zostaną nadpisane.
Powyższy przykład pozwala na użycie następującego kodu:
@ -1301,6 +1355,9 @@ $comments = Comment::find()->active()->all();
$inactiveComments = Comment::find()->active(false)->all();
```
> Tip: Dla dużych projektów rekomendowane jest, aby używać własnych, odpowiednio dopasowanych do potrzeb, klas kwerend, dzięki czemu klasy Active Record
> pozostają przejrzyste.
Możesz także użyć nowych metod budowania kwerend przy definiowaniu relacji z `Comment` lub wykonywaniu relacyjnych kwerend:
```php
@ -1312,11 +1369,18 @@ class Customer extends \yii\db\ActiveRecord
}
}
$customers = Customer::find()->with('activeComments')->all();
$customers = Customer::find()->joinWith('activeComments')->all();
// lub alternatywnie
$customers = Customer::find()->with([
class Customer extends \yii\db\ActiveRecord
{
public function getComments()
{
return $this->hasMany(Comment::className(), ['customer_id' => 'id']);
}
}
$customers = Customer::find()->joinWith([
'comments' => function($q) {
$q->active();
}
@ -1394,8 +1458,9 @@ $customers = Customer::find()
->all();
```
Wadą tej metody jest to, że jeśli informacja nie może zostać pobrana za pomocą kwerendy SQL, musi ona być obliczona oddzielnie,
co oznacza rónież, że świeżo zapisane rekordy nie będą zawierały informacji z dodatkowych pól:
Wadą tej metody jest to, że jeśli informacja nie może zostać pobrana za pomocą kwerendy SQL, musi ona być obliczona oddzielnie.
Zatem po pobraniu konkretnego wiersza tabeli za pomocą regularnej kwerendy bez dodatkowej instrukcji select, niemożliwym będzie
zwrócenie wartości dla dodatkowych pól. Tak samo stanie się w przypadku świeżo zapisanych rekordów.
```php
$room = new Room();
@ -1403,7 +1468,7 @@ $room->length = 100;
$room->width = 50;
$room->height = 2;
$room->volume; // ta wartość będzie wynosić null ponieważ nie została jeszcze zadeklarowana
$room->volume; // ta wartość będzie wynosić `null` ponieważ nie została jeszcze zadeklarowana
```
Używając magicznych metod [[yii\db\BaseActiveRecord::__get()|__get()]] i [[yii\db\BaseActiveRecord::__set()|__set()]], możemy emulować
@ -1438,9 +1503,9 @@ class Room extends \yii\db\ActiveRecord
}
```
Kiedy kwerenda nie zapewnii wartości kubatury, model będzie w stanie automatycznie ją obliczyć, używając swoich atrybutów.
Kiedy kwerenda nie zapewni wartości kubatury, model będzie w stanie automatycznie ją obliczyć, używając swoich atrybutów.
Podobnego sposobu można użyć na dodatkowych polach zależnych od danych tabel relacji:
Możesz obliczyć sumaryczne pola rónież korzystając ze zdefiniowanych relacji:
```php
class Customer extends \yii\db\ActiveRecord
@ -1459,7 +1524,7 @@ class Customer extends \yii\db\ActiveRecord
}
if ($this->_ordersCount === null) {
$this->setOrdersCount(count($this->orders));
$this->setOrdersCount($this->getOrders()->count()); // oblicz sumę na żądanie z relacji
}
return $this->_ordersCount;
@ -1473,3 +1538,54 @@ class Customer extends \yii\db\ActiveRecord
}
}
```
Dla powyższego kodu, kiedy 'ordersCount' występuje w instrukcji 'select' - `Customer::ordersCount` zostanie wypełnione
rezultatem kwerendy, w pozostałych przypadkach zostanie obliczone na żądanie używając relacji `Customer::orders`.
Takie podejście może być równie dobrze użyte do stworzenia skrótów dla niektórych danych relacji, zwłąszcza tych służących do obliczania sumarycznego.
Przykładowo:
```php
class Customer extends \yii\db\ActiveRecord
{
/**
* Deklaracja wirtualnej właściwości tylko do odczytu dla danych sumarycznych.
*/
public function getOrdersCount()
{
if ($this->isNewRecord) {
return null; // to pozwala na uniknięcie uruchamiania wyszukującej kwerendy dla pustych kluczy głównych
}
return empty($this->ordersAggregation) ? 0 : $this->ordersAggregation[0]['counted'];
}
/**
* Deklaracja zwykłej relacji 'orders'.
*/
public function getOrders()
{
return $this->hasMany(Order::className(), ['customer_id' => 'id']);
}
/**
* Deklaracja nowej relacji bazującej na 'orders', ale zapewniającej pobranie danych sumarycznych.
*/
public function getOrdersAggregation()
{
return $this->getOrders()
->select(['customer_id', 'counted' => 'count(*)'])
->groupBy('customer_id')
->asArray(true);
}
// ...
}
foreach (Customer::find()->with('ordersAggregation')->all() as $customer) {
echo $customer->ordersCount; // wyświetla dane sumaryczne z relacji bez dodatkowej kwerendy dzięki gorliwemu pobieraniu
}
$customer = Customer::findOne($pk);
$customer->ordersCount; // wyświetla dane sumaryczne z relacji pobranej leniwie
```

BIN
docs/guide-pl/images/start-gii-crud-preview.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 59 KiB

BIN
docs/guide-pl/images/start-gii-crud.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 55 KiB

BIN
docs/guide-pl/images/start-gii-model-preview.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 64 KiB

BIN
docs/guide-pl/images/start-gii-model.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 50 KiB

2
docs/guide-pl/input-file-upload.md

@ -74,7 +74,7 @@ use yii\widgets\ActiveForm;
Należy pamiętać, aby dodać opcję `enctype` do formularza, przez co plik będzie mógł być prawidłowo przesłany.
Wywołanie `fileInput()` spowoduje wyrenderowanie tagu `<input type="file">`, który pozwala użytkownikowi na wybranie oraz przesłanie pliku.
> Tip: od wersji 2.0.8, [[yii\web\widgets\ActiveField::fileInput|fileInput]] dodaje automatycznie opcję `enctype` do formularza, kiedy pole typu 'file input' jest używane.
> Tip: od wersji 2.0.8, [[yii\widgets\ActiveField::fileInput|fileInput]] dodaje automatycznie opcję `enctype` do formularza, kiedy pole typu 'file input' jest używane.
## Implementacja kontrolera <span id="wiring-up"></span>

81
docs/guide-pl/input-forms.md

@ -1,6 +1,8 @@
Tworzenie formularzy
==============
====================
Formularze oparte na ActiveRecord: ActiveForm
---------------------------------------------
Podstawowym sposobem korzystania z formularzy w Yii jest użycie [[yii\widgets\ActiveForm|ActiveForm]]. Ten sposób powinien być używany, jeśli formularz jest bazowany na modelu.
Dodatkowo, klasa [[yii\helpers\Html|Html]] zawiera sporo użytecznych metod, które zazwyczaj używane są do dodawania przycisków i tekstów pomocniczych do każdego formularza.
@ -9,7 +11,11 @@ stronie serwera (sprawdź sekcję [Walidacja danych wejściowych](input-validati
Podczas tworzenia formularza na podstawie modelu, pierwszym krokiem jest zdefiniowanie samego modelu.
Model może być bazowany na klasie [Active Record](db-active-record.md), reprezentując dane z bazy danych, lub może być też bazowany na klasie generycznej [[yii\base\Model|Model]],
aby przechwytywać dowolne dane wejściowe, np. formularz logowania.
W poniższym przykładzie pokażemy, jak model generyczny może być użyty do formularza logowania:
> Tip: Jeśli pola formularza są różne od kolumn tabeli w bazie danych lub też występuje tu formatowanie i logika specyficzna tylko dla tego formularza,
> zaleca się stworzenie oddzielnego modelu rozszerzającego [[yii\base\Model]].
W poniższym przykładzie pokażemy, jak model generyczny może być użyty do stworzenia formularza logowania:
```php
<?php
@ -50,6 +56,7 @@ $form = ActiveForm::begin([
<?php ActiveForm::end() ?>
```
### Otaczanie kodu przez `begin()` i `end()` <span id="wrapping-with-begin-and-end"></span>
W powyższym kodzie, [[yii\widgets\ActiveForm::begin()|begin()]] nie tylko tworzy instancję formularza, ale zaznacza też jego początek.
Cała zawartość położona pomiędzy [[yii\widgets\ActiveForm::begin()|begin()]] i [[yii\widgets\ActiveForm::end()|end()]] zostanie otoczona tagiem HTML'owym `<form>`.
Jak w przypadku każdego widżetu, możesz określić kilka opcji z jakimi widżet powinien być skonfigurowany przez przekazanie tablicy do metody `begin`.
@ -110,25 +117,75 @@ tak jak było to zrobione w przykładzie wyżej z [[yii\helpers\Html::submitButt
> }
> ```
Tworzenie listy rozwijanej <span id="creating-activeform-dropdownlist"></span>
---------------------
Tworzenie list <span id="creating-activeform-lists"></span>
--------------
Możemy użyć metody klasy ActiveForm [[yii\widgets\ActiveForm::dropDownList()|dropDownList()]] do utworzenia rozwijanej listy:
Wyróżniamy trzy typy list:
* Listy rozwijane
* Listy opcji typu radio
* Listy opcji typu checkbox
Aby stworzyć listę, musisz najpierw przygotować jej elementy. Można to zrobić ręcznie:
```php
use app\models\ProductCategory;
$items = [
1 => 'item 1',
2 => 'item 2'
]
```
lub też pobierając elementy z bazy danych:
/* @var $this yii\web\View */
```php
$items = Category::find()
->select(['label'])
->indexBy('id')
->column();
```
Elementy `$items` muszą być następnie przetworzone przez odpowiednie widżety list.
Wartość pola formularza (i aktualnie aktywny element) będzie automatycznie ustawiony przez aktualną wartość atrybutu `$model`.
#### Tworzenie listy rozwijanej <span id="creating-activeform-dropdownlist"></span>
Możemy użyć metody klasy ActiveForm [[yii\widgets\ActiveForm::dropDownList()|dropDownList()]] do utworzenia rozwijanej listy:
```php
/* @var $form yii\widgets\ActiveForm */
/* @var $model app\models\Product */
echo $form->field($model, 'product_category')->dropdownList(
ProductCategory::find()->select(['category_name', 'id'])->indexBy('id')->column(),
['prompt'=>'Select Category']
echo $form->field($model, 'category')->dropdownList([
1 => 'item 1',
2 => 'item 2'
],
['prompt'=>'Wybierz kategorię']
);
```
Wartość z Twojego modelu będzie automatycznie wybrana po wyświetleniu formularza.
#### Tworzenie radio listy <span id="creating-activeform-radioList"></span>
Do stworzenia takiej listy możemy użyć metody ActiveField [[\yii\widgets\ActiveField::radioList()]]:
```php
/* @var $form yii\widgets\ActiveForm */
echo $form->field($model, 'category')->radioList([
1 => 'radio 1',
2 => 'radio 2'
]);
```
#### Tworzenie checkbox listy <span id="creating-activeform-checkboxList"></span>
Do stworzenia takiej listy możemy użyć metody ActiveField [[\yii\widgets\ActiveField::checkboxList()]]:
```php
/* @var $form yii\widgets\ActiveForm */
echo $form->field($model, 'category')->checkboxList([
1 => 'checkbox 1',
2 => 'checkbox 2'
]);
```
Praca z Pjaxem <span id="working-with-pjax"></span>
-----------------------

144
docs/guide-pl/input-validation.md

@ -317,8 +317,10 @@ Wbudowany walidator jest zdefiniowaną w modelu metodą lub funkcją anonimową.
/**
* @param string $attribute atrybut podlegający walidacji
* @param mixed $params wartość parametru podanego w zasadzie walidacji
* @param \yii\validators\InlineValidator $validator powiązana instancja InlineValidator
* Ten parametr jest dostępny od wersji 2.0.11.
*/
function ($attribute, $params)
function ($attribute, $params, $validator)
```
Jeśli atrybut nie przejdzie walidacji, metoda/funkcja powinna wywołać metodę [[yii\base\Model::addError()|addError()]] do zapisania wiadomości o błędzie w modelu,
@ -341,7 +343,7 @@ class MyForm extends Model
['country', 'validateCountry'],
// Wbudowany walidator zdefiniowany jako funkcja anonimowa
['token', function ($attribute, $params) {
['token', function ($attribute, $params, $validator) {
if (!ctype_alnum($this->$attribute)) {
$this->addError($attribute, 'Token musi zawierać litery lub cyfry.');
}
@ -349,7 +351,7 @@ class MyForm extends Model
];
}
public function validateCountry($attribute, $params)
public function validateCountry($attribute, $params, $validator)
{
if (!in_array($this->$attribute, ['USA', 'Web'])) {
$this->addError($attribute, 'Wybrany kraj musi być jednym z: "USA", "Web".');
@ -358,6 +360,14 @@ class MyForm extends Model
}
```
> Note: Począwszy od wersji 2.0.11 możesz użyć [[yii\validators\InlineValidator::addError()]], aby dodać błędy bezpośrednio. W tym sposobie treść błędu
> może być sformatowana bezpośrednio za pomocą [[yii\i18n\I18N::format()]]. Użyj `{attribute}` i `{value}` w treści błędu, aby odwołać się odpowiednio
> do etykiety atrybutu (bez konieczności pobierania jej ręcznie) i wartości atrybutu:
>
> ```php
> $validator->addError($this, $attribute, 'Wartość "{value}" nie jest poprawna dla {attribute}.');
> ```
> Note: Domyślnie wbudowane walidatory nie zostaną zastosowane, jeśli ich powiązane atrybuty otrzymają puste wartości lub wcześniej nie przeszły którejś z zasad walidacji.
> Jeśli chcesz się upewnić, że zasada zawsze zostanie zastosowana, możesz skonfigurować właściwość [[yii\validators\Validator::skipOnEmpty|skipOnEmpty]] i/lub
> [[yii\validators\Validator::skipOnError|skipOnError]], przypisując jej wartość `false` w deklaracji zasady walidacji. Dla przykładu:
@ -425,6 +435,118 @@ class EntryForm extends Model
}
```
## Walidacja wielu atrybutów na raz <span id="multiple-attributes-validation"></span>
Zdarza się, że walidatory sprawdzają wiele atrybutów jednocześnie. Rozważmy następujący formularz:
```php
class MigrationForm extends \yii\base\Model
{
/**
* Kwota minimalnych funduszy dla jednej dorosłej osoby
*/
const MIN_ADULT_FUNDS = 3000;
/**
* Kwota minimalnych funduszy dla jednego dziecka
*/
const MIN_CHILD_FUNDS = 1500;
public $personalSalary;
public $spouseSalary;
public $childrenCount;
public $description;
public function rules()
{
return [
[['personalSalary', 'description'], 'required'],
[['personalSalary', 'spouseSalary'], 'integer', 'min' => self::MIN_ADULT_FUNDS],
['childrenCount', 'integer', 'min' => 0, 'max' => 5],
[['spouseSalary', 'childrenCount'], 'default', 'value' => 0],
['description', 'string'],
];
}
}
```
### Tworzenie walidatora <span id="multiple-attributes-validator"></span>
Powiedzmy, że chcemy sprawdzić, czy dochód rodziny jest wystarczający do utrzymania dzieci. W tym celu możemy utworzyć wbudowany walidator
`validateChildrenFunds`, który będzie uruchamiany tylko jeśli `childrenCount` będzie większe niż 0.
Zwróć uwagę na to, że nie możemy użyć wszystkich walidowanych atrybutów (`['personalSalary', 'spouseSalary', 'childrenCount']`) przy dołączaniu walidatora.
Wynika to z tego, że ten sam walidator będzie uruchomiony dla każdego z atrybutów oddzielnie (łącznie 3 razy), a musimy użyć go tylko raz dla całego zestawu atrybutów.
Możesz użyć dowolnego z tych atrybutów zamiast podanego poniżej (lub też tego, który uważasz za najbardziej tu odpowiedni):
```php
['childrenCount', 'validateChildrenFunds', 'when' => function ($model) {
return $model->childrenCount > 0;
}],
```
Implementacja `validateChildrenFunds` może wyglądać następująco:
```php
public function validateChildrenFunds($attribute, $params)
{
$totalSalary = $this->personalSalary + $this->spouseSalary;
// Podwój minimalny fundusz dorosłych, jeśli ustalono zarobki współmałżonka
$minAdultFunds = $this->spouseSalary ? self::MIN_ADULT_FUNDS * 2 : self::MIN_ADULT_FUNDS;
$childFunds = $totalSalary - $minAdultFunds;
if ($childFunds / $this->childrenCount < self::MIN_CHILD_FUNDS) {
$this->addError('childrenCount', 'Twoje zarobki nie są wystarczające, aby utrzymać dzieci.');
}
}
```
Możesz zignorować parametr `$attribute`, ponieważ walidacja nie jest powiązana bezpośrednio tylko z jednym atrybutem.
### Dodawanie informacji o błędach <span id="multiple-attributes-errors"></span>
Dodawanie błędów walidacji w przypadku wielu atrybutów może różnić się w zależności od ustalonej metodyki pracy z formularzami:
- Można wybrać najbardziej w naszej opinii pole i dodać błąd do jego atrybutu:
```php
$this->addError('childrenCount', 'Twoje zarobki nie są wystarczające dla potrzeb dzieci.');
```
- Można wybrać wiele ważnych odpowiednich atrybutów lub też wszystkie i dodać ten sam błąd do każdego z nich. Możemy przechować
treść w oddzielnej zmiennej przed przekazaniem jej do `addError`, aby nie powtarzać się w kodzie (zasada DRY - Don't Repeat Yourself).
```php
$message = 'Twoje zarobki nie są wystarczające dla potrzeb dzieci.';
$this->addError('personalSalary', $message);
$this->addError('wifeSalary', $message);
$this->addError('childrenCount', $message);
```
Lub też użyć pętli:
```php
$attributes = ['personalSalary, 'wifeSalary', 'childrenCount'];
foreach ($attributes as $attribute) {
$this->addError($attribute, 'Twoje zarobki nie są wystarczające dla potrzeb dzieci.');
}
```
- Można też dodać ogólny błąd (niepowiązany z żadnym szczególnym atrybutem). Do tego celu możemy wykorzystać nazwę nieistniejącego atrybutu,
na przykład `*`, ponieważ to, czy atrybut istnieje, nie jest sprawdzane w tym kroku.
```php
$this->addError('*', 'Twoje zarobki nie są wystarczające dla potrzeb dzieci.');
```
W rezultacie takiej operacji nie zobaczymy błędu zaraz obok pól formularza. Aby go wyświetlić, możemy dodać do widoku podsumowanie błędów formularza:
```php
<?= $form->errorSummary($model) ?>
```
> Note: Tworzenie walidatora operującego na wielu atrybutach jednocześnie jest dobrze opisane w [książce kucharskiej społeczności Yii](https://github.com/samdark/yii2-cookbook/blob/master/book/forms-validator-multiple-attributes.md).
## Walidacja po stronie klienta <span id="client-side-validation"></span>
@ -496,6 +618,22 @@ Możesz również wyłączyć ten rodzaj walidacji dla konkretnego pola, przez u
[[yii\widgets\ActiveField::enableClientValidation|enableClientValidation]] na `false`. Jeśli właściwość `enableClientValidation` zostanie skonfigurowana na poziomie pola
formularza i w samym formularzu jednocześnie, pierwszeństwo będzie miała opcja określona w formularzu.
> Info: Od wersji 2.0.11 wszystkie walidatory rozszerzające klasę [[yii\validators\Validator]] używają opcji klienta przekazywanych
> z oddzielnej metody - [[yii\validators\Validator::getClientOptions()]]. Możesz jej użyć:
>
> - jeśli chcesz zaimplementować swoją własną walidację po stronie klienta, ale pozostawić synchronizację z opcjami walidatora po stronie serwera;
> - do rozszerzenia lub zmodyfikowania dla uzyskania specjalnych korzyści:
>
> ```php
> public function getClientOptions($model, $attribute)
> {
> $options = parent::getClientOptions($model, $attribute);
> // Zmodyfikuj $options w tym miejscu
>
> return $options;
> }
> ```
### Implementacja walidacji po stronie klienta <span id="implementing-client-side-validation"></span>

3
docs/guide-pl/intro-upgrade-from-v1.md

@ -513,4 +513,5 @@ Zapoznaj się z sekcją dotyczącą [ID kontrolerów](structure-controllers.md#c
Korzystanie z Yii 1.1 i 2.x jednocześnie
----------------------------------------
Jeśli chciałbyś skorzystać z kodu napisanego dla Yii 1.1 w aplikacji Yii 2.0, prosimy o zapoznanie się z sekcją [Praca z kodem zewnętrznym](tutorial-yii-integration.md).
Jeśli chciałbyś skorzystać z kodu napisanego dla Yii 1.1 w aplikacji Yii 2.0,
prosimy o zapoznanie się z sekcją [Używanie Yii 1.1 i 2.0 razem](tutorial-yii-integration.md#using-both-yii2-yii1).

8
docs/guide-pl/intro-yii.md

@ -30,12 +30,10 @@ oraz ActiveRecord dla baz danych relacyjnych i NoSQL, wsparcia dla tworzenia RES
Dodatkowo Yii wykorzystuje architekturę rozszerzeń, dzięki czemu możesz w prosty sposób stworzyć i opublikować swoje własne moduły i widżety.
* Podstawowym celem, do którego Yii zawsze dąży, jest wysoka wydajność.
Yii nie jest efektem pracy pojedynczego programisty - projekt wspiera zarówno [grupa doświadczonych deweloperów][about_yii], jak i ogromna społeczność programistyczna, nieustannie
Yii nie jest efektem pracy pojedynczego programisty - projekt wspiera zarówno [grupa doświadczonych deweloperów][http://www.yiiframework.com/team/], jak i ogromna społeczność programistyczna, nieustannie
przyczyniając się do jego rozwoju. Deweloperzy trzymają rękę na pulsie najnowszych trendów Internetu, za pomocą prostych i eleganckich interfejsów wzbogacając Yii w najlepsze sprawdzone
rozwiązania i funkcjonalności, dostępne w innych frameworkach i projektach.
[about_yii]: http://www.yiiframework.com/about/
Wersje Yii
----------
@ -48,8 +46,8 @@ Ten przewodnik opisuje wersję 2.0.
Wymagania i zależności
----------------------
Yii 2.0 wymaga PHP w wersji 5.4.0 lub nowszej. Aby otrzymać więcej informacji na temat wymagań i indywidualnych funkcjonalności,
uruchom specjalny skrypt testujący system `requirements.php`, dołączony w każdym wydaniu Yii.
Yii 2.0 wymaga PHP w wersji 5.4.0 lub nowszej i pracuje najwydajniej na najnowszej wersji PHP 7. Aby otrzymać więcej
informacji na temat wymagań i indywidualnych funkcjonalności, uruchom specjalny skrypt testujący system dołączony w każdym wydaniu Yii.
Używanie Yii wymaga podstawowej wiedzy o programowaniu obiektowym w PHP (OOP), ponieważ Yii
jest frameworkiem czysto obiektowym. Yii 2.0 wykorzystuje ostatnie udoskonalenia w PHP, jak

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

@ -56,7 +56,7 @@ Jeśli jesteś już posiadaczem Composera, upewnij się, że jest on zaktualizow
Teraz możesz przejść już do instalacji samego Yii, wywołując poniższe komendy w katalogu dostępnym z poziomu sieci web:
```bash
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
```

2
docs/guide-pl/tutorial-start-from-scratch.md

@ -52,6 +52,6 @@ Użycie szablonu
Tylko tyle jest wymagane, aby stworzyć nowy szablon projektu Yii. Teraz już możesz rozpocząć pracę nad świeżym projektem, używając swojego szablonu, za pomocą komend:
```
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist --stability=dev mojafirma/yii2-app-fajna nowy-projekt
```

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

@ -46,7 +46,7 @@ Você pode atualizar o Composer executando o comando `composer self-update`.
Com o Composer instalado, você pode instalar o Yii executando o seguinte comando
em um diretório acessível pela Web:
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
O primeiro comando instala o [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/)

2
docs/guide-pt-BR/tutorial-yii-integration.md

@ -66,7 +66,7 @@ Como o Yii fornece muitas características excelentes, algumas vezes você pode
Se o sistema em questão utilizar o Composer para gerenciar suas dependências, você pode simplesmente executar o seguinte comando para instalar o Yii:
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer require yiisoft/yii2
composer install

2
docs/guide-ru/input-file-upload.md

@ -77,7 +77,7 @@ use yii\widgets\ActiveForm;
Важно помнить, что для корректной загрузки файла, необходим параметр формы `enctype`. Метод `fileInput()`
выведет тег `<input type="file">`, позволяющий пользователю выбрать файл для загрузки.
> Tip: начиная с версии 2.0.8, [[yii\web\widgets\ActiveField::fileInput|fileInput]] автоматически добавляет
> Tip: начиная с версии 2.0.8, [[yii\widgets\ActiveField::fileInput|fileInput]] автоматически добавляет
к форме свойство `enctype`, если в ней есть поле для загрузки файла.
## Загрузка <span id="wiring-up"></span>

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

@ -499,8 +499,7 @@ HTML-форма построена с помощью следующего код
- `messages`: массив, используемый для хранения сообщений об ошибках, проверки значения атрибута.
- `deferred`: массив, который содержит отложенные объекты (описано в следующем подразделе).
В следующем примере мы создаем `StatusValidator` который проверяет, if an input is a valid
status input against the existing status data.
В следующем примере мы создаем `StatusValidator` который проверяет значение поля на соответствие допустимым статусам.
Валидатор поддерживает оба способа проверки и на стороне сервера и на стороне клиента.
```php

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

@ -607,7 +607,7 @@ CREATE OR REPLACE VIEW vw_user_info AS
WHERE user.id = user_profile.user_id
```
Теперь необходимо создать ActiveRecord, которая будет отображение данных из этого вида:
Теперь вам необходимо создать ActiveRecord, через который будут доступны данные из вида выше:
```php
@ -650,8 +650,6 @@ class UserView extends ActiveRecord
// здесь определяйте ваши метки атрибутов
];
}
}
```

2
docs/guide-ru/rest-rate-limiting.md

@ -2,7 +2,7 @@
===============================
Чтобы избежать злоупотреблений, вам следует подумать о добавлении ограничения частоты запросов к вашим API. Например,
вы можете ограничить использование API 100 вызовов API в течение 10 минут для каждого пользователя. Если от пользователя
вы можете ограничить использование API до 100 вызовов в течение 10 минут для каждого пользователя. Если от пользователя
в течение этого периода времени приходит большее количество запросов, будет возвращаться ответ с кодом состояния 429
(«слишком много запросов»).

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

@ -5,7 +5,7 @@ RESTful API строятся вокруг доступа к *ресурсам*
о [моделях](structure-models.md) из [MVC](http://ru.wikipedia.org/wiki/Model-View-Controller).
Хотя не существует никаких ограничений на то, как представить ресурс, в Yii ресурсы обычно представляются
как объекты [[yii\base\Model]] или дочерних классов (например [[yii\db\ActiveRecord]]), потому как:
как объекты [[yii\base\Model]] или дочерние классы (например [[yii\db\ActiveRecord]]), потому как:
* [[yii\base\Model]] реализует интерфейс [[yii\base\Arrayable]], который позволяет задать способ отдачи данных
ресурса через RESTful API.

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

@ -47,7 +47,7 @@ mv composer.phar /usr/local/bin/composer
### Установка Yii
```bash
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
```

22
docs/guide-ru/test-environment-setup.md

@ -47,3 +47,25 @@ Changed current directory to <directory>
путём запуска команды `codecept` без указания пути. Тем не менее, данный подход может не подойти. К примеру, в двух
разных проектах может потребоваться установить разные версии Codeception. Для простоты все команды в разделах про
тестирование используются так, будто Codeception установлен глобально.
### Настройка веб-сервера Apache
Если вы используете Apache и настроили его как описано в разделе «[Установка Yii](start-installation.md)», то для тестов вам необходимо создать отдельный виртуальный хост который будет работать с той же папкой, но использовать входной скрипт `index-test.php`:
```
<VirtualHost *:80>
DocumentRoot "path/to/basic/webb"
ServerName mysite-test
<Directory "path/to/basic/web">
Order Allow,Deny
Allow from all
AddDefaultCharset utf-8
DirectoryIndex index-test.php
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index-test.php
</Directory>
</VirtualHost>
```
Так мы укажем веб серверу перенаправлять все запросы на скрипт `index-test.php`.
> Note: Обратите внимание, что здесь мы указываем параметр `DirectoryIndex`, помимо тех параметров, которые были указаны для первого хоста. Это сделано с той целью, чтобы при обращении к главной странице по адресу `mysite-test` также использовался бы скрипт `index-test.php`.

2
docs/guide-ru/tutorial-start-from-scratch.md

@ -46,6 +46,6 @@ git clone git@github.com:yiisoft/yii2-app-basic.git
Это все, что требуется для создания нового шаблона проекта в Yii. Сейчас вы можете создавать проекты, использующие ваш шаблон:
```
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist --stability=dev mysoft/yii2-app-coolone new-project
```

2
docs/guide-ru/tutorial-yii-integration.md

@ -63,7 +63,7 @@ Yii::$classMap['Class2'] = 'path/to/Class2.php';
Если сторонняя система использует для управления зависимостями Composer, Yii можно просто установить с помощью следующих команд:
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer require yiisoft/yii2
composer install

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

@ -40,7 +40,7 @@
Після встановлення Composer, встановити Yii можна виконавши наступну команду з директорії, яка доступна через Web:
```bash
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
```

2
docs/guide-uk/tutorial-start-from-scratch.md

@ -57,6 +57,6 @@ git clone git@github.com:yiisoft/yii2-app-basic.git
Тепер ви можете створювати проекти, використовуючи свій шаблон:
```
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist --stability=dev mysoft/yii2-app-coolone new-project
```

2
docs/guide-uk/tutorial-yii-integration.md

@ -84,7 +84,7 @@ Yii::$classMap['Class2'] = 'path/to/Class2.php';
Якщо стороння система використовує управління залежностями Composer, ви можете встановити Yii за допомогою наступних команд:
```bash
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer require yiisoft/yii2
composer install
```

26
docs/guide-vi/README.md

@ -3,7 +3,7 @@ The Definitive Guide to Yii 2.0
Các hướng dẫn được phát hành theo [Các điều khoản về tài liệu Yii](http://www.yiiframework.com/doc/terms/).
All Rights Reserved.
Tất cả bản quyền đã được bảo hộ (All Rights Reserved).
2014 (c) Yii Software LLC.
@ -12,7 +12,7 @@ Giới thiệu
------------
* [Về Yii](intro-yii.md)
* [Nâng cấp lên từ phiên bản 1.1](intro-upgrade-from-v1.md)
* [Hướng dẫn nâng cấp lên từ phiên bản 1.1](intro-upgrade-from-v1.md)
Bắt đầu
@ -20,11 +20,11 @@ Bắt đầu
* [Cài đặt Yii](start-installation.md)
* [Thực hiện chạy ứng dụng](start-workflow.md)
* [Viết lời chào đầu tiên](start-hello.md)
* [Viết chương trình đầu tiên](start-hello.md)
* [Làm việc với Forms](start-forms.md)
* [Làm việc với Databases](start-databases.md)
* [Sử dụng Gii để sinh code](start-gii.md)
* [Mức cao hơn](start-looking-ahead.md)
* [Sử dụng Gii để sinh mã tự động](start-gii.md)
* [Nâng cao](start-looking-ahead.md)
Kiến trúc ứng dụng (Application Structure)
@ -33,8 +33,8 @@ Kiến trúc ứng dụng (Application Structure)
* [Tổng quan về kiến trúc ứng dụng](structure-overview.md)
* [Mục Scripts](structure-entry-scripts.md)
* [Ứng dụng (Applications)](structure-applications.md)
* [Thành phần ứng dụng](structure-application-components.md)
* [Bộ điều khiển (Controllers)](structure-controllers.md)
* [Các thành phần bên trong ứng dụng](structure-application-components.md)
* [Controllers](structure-controllers.md)
* [Models](structure-models.md)
* [Views](structure-views.md)
* [Modules](structure-modules.md)
@ -44,14 +44,14 @@ Kiến trúc ứng dụng (Application Structure)
* [Phần mở rộng (Extensions)](structure-extensions.md)
Yêu cầu xử lý (Handling Requests)
Xử lý yêu cầu (Handling Requests)
-----------------
* [Tổng quan](runtime-overview.md)
* [Bootstrapping](runtime-bootstrapping.md)
* [Routing và URL Creation](runtime-routing.md)
* [Khởi động](runtime-bootstrapping.md)
* [Định tuyến (Routing)khởi tạo đường dẫn (URL Creation)](runtime-routing.md)
* [Yêu cầu (Requests)](runtime-requests.md)
* [Responses](runtime-responses.md)
* [Kết quả (Responses)](runtime-responses.md)
* [Sessions và Cookies](runtime-sessions-cookies.md)
* [Xử lý lỗi (Handling Error)](runtime-handling-errors.md)
* [Logging](runtime-logging.md)
@ -77,7 +77,7 @@ Làm việc với Databases
* [Data Access Objects](db-dao.md): Kết nối cơ sở dữ liệu, truy vấn cơ bản, giao dịch và phương thức hoạt động
* [Query Builder](db-query-builder.md): Sử dụng một truy vấn đơn giản, các lớp cơ sở dữ liệu trừu tượng
* [Active Record](db-active-record.md): The Active Record ORM, truy vấn và thao tác với dữ liệu, định nghĩa các mối quan hệ giữa các bảng
* [Migrations](db-migrations.md): Cung cấp cho đội dự án dễ dàng trong việc quản lý những schema CSDL trong ứng dụng
* [Migrations](db-migrations.md): Cung cấp cho đội dự án một công cụ dễ dàng trong việc quản lý những schema CSDL trong ứng dụng
* **TBD** [Sphinx](db-sphinx.md)
* **TBD** [Redis](db-redis.md)
* **TBD** [MongoDB](db-mongodb.md)
@ -171,7 +171,7 @@ Chủ đề năng cao
* [Tối ưu hiệu năng ứng dụng (Performance Tuning)](tutorial-performance-tuning.md)
* [Shared Hosting Environment](tutorial-shared-hosting.md)
* [Template Engines](tutorial-template-engines.md)
* [Working with Third-Party Code](tutorial-yii-integration.md)
* [Tích hợp mã nguồn của bên thứ ba (Working with Third-Party Code)](tutorial-yii-integration.md)
Widgets

18
docs/guide-vi/intro-yii.md

@ -1,28 +1,28 @@
Yii là gì
===========
Yii có hiệu suất cao, được dựa trên các thành phần PHP framework cho việc phát triển các ứng dụng Web hiện đại.
Yii là một PHP Framework mã nguồn mở và hoàn toàn miễn phí, có hiệu năng xử lý cao, phát triển tốt nhất trên các ứng dụng Web 2.0, sử dụng tối đa các thành phần (component-based PHP framework) để tăng tốc độ viết ứng dụng.
Tên Yii (được phát âm là `Yee` hoặc `[ji:]`) ở Trung Quốc có nghĩa là "thật đơn giản và luôn phát triển". Nghĩa thứ hai có thể đọc ngắn gọn là **Yes It Is**!
Yii thích hợp nhất để làm gì?
---------------------
Yii là một framework lập trình Web chung chung mà có thể được sử dụng để phát triển một loạt các ứng dụng Web
được xây dựng với PHP. Bởi vì dựa trên kiến trúc thành phần và có bộ nhớ đệm hoàn hảo,
nó là đặc biệt thích hợp cho việc phát triển các ứng dụng quy mô lớn, chẳng hạn như các cổng thông tin,
diễn đàn, hệ thống quản lý nội dung (CMS), các dự án thương mại điện tử và các dịch vụ Web RESTful.
Yii, nói chung, là một framework phát triển ứng dụng Web nên có thể dùng để viết mọi loại ứng dụng Web
và sử dụng ngôn ngữ lập trình PHP. Yii rất nhẹ và được trang bị giải pháp cache tối ưu nên đặc biệt
hữu dụng cho ứng dụng web có dung lượng dữ liệu trên đường truyền lớn như web portal, forum, CMS, e-commerce,
các dự án thương mại điện tử và các dịch vụ Web RESTful..
So sánh Yii Với các Frameworks khác?
-------------------------------------------
Nếu bạn có kinh nghiệm với các framework khác, bạn sẽ rất vui mừng khi thấy những nỗ lực của Yii:
Nếu bạn có kinh nghiệm làm việc với các framework khác, bạn sẽ rất vui mừng khi thấy những nỗ lực của Yii:
- Giống như những PHP frameworks khác, Yii sử dụng mô hình MVC (Model-View-Controller) tổ chức code một cách hợp lý và có hệ thống hơn .
- Giống như những PHP frameworks khác, Yii sử dụng mô hình MVC (Model-View-Controller) tổ chức code một cách hợp lý và có hệ thống.
- Yii tạo ra code đơn giản và thanh lịch, đây là triết lý trong chương trình. Yii sẽ không bao giờ
cố gắng tạo ra những mấu thiết kế quá an toàn và ít có sự thay đổi.
- Yii là framework hoàn chình, cung cấp nhiều tính năng và được xác minh như: query builders, thao tác dữ liệu với
- Yii là framework hoàn chnh, cung cấp nhiều tính năng và được xác minh như: query builders, thao tác dữ liệu với
ActiveRecord được dùng cho CSDL quan hệ và NoSQL; hỗ trợ phát triển RESTful API; sự hỗ trợ đa bộ nhớ cache; và nhiều hơn.
- Yii rất dễ mở rộng. Bạn có thể tùy chình hoặc thay thế bất kỳ một trong những bộ code chuẩn. Bạn cũng có thể
tận dụng lợi thế của kiến trúc mở rộng chuẩn Yii để sử dụng hoặc phát triển mở rộng phân phối..
@ -39,7 +39,7 @@ Các phiên bản Yii
------------
Yii Hiện nay có hai phiên bản chính: 1.1 và 2.0. Phiên bản 1.1 là phiên bản cũ và bây giờ là trong chế độ bảo trì. Tiếp đến, phiên bản 2.0 là phiên bản đuọc viết lại hoàn toàn Yii, sử dụng các
công nghệ mới và giao thức, bao gồm trình quản lý gói Composer, các tiêu chuẩn code PHP PSR, namespaces, traits, và như vậy. Phiên bản 2.0 đại diện cho sự hình thành của framework
công nghệ mới và giao thức mới, bao gồm trình quản lý gói Composer, các tiêu chuẩn code PHP PSR, namespaces, traits, và như vậy. Phiên bản 2.0 đại diện cho sự hình thành của framework
và sẽ nhận được những nỗ lực phát triển chính trong vài năm tới.
Hướng dẫn này chủ yếu là về phiên bản 2.0.

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

@ -1,20 +1,19 @@
Cài đặt Yii
==============
Bạn có thể cài đặt Yii theo hai cách, dùng trình quản lý gói [Composer](http://getcomposer.org/) hoặc tải về một tập tin lưu trữ.
Cách thứ nhất thường được hay dùng hơn, vì nó cho phép bạn cài đặt các [Gói mở rộng (extensions)](structure-extensions.md) mới hoặc cập nhật Yii đơn giản chỉ mới một câu lệnh.
Bạn có thể cài đặt Yii theo hai cách, dùng trình quản lý gói [Composer](http://getcomposer.org/) hoặc tải toàn bộ mã nguồn Yii về.
Cách thứ nhất thường được khuyến khích dùng hơn, vì nó cho phép bạn cài đặt thêm các [Gói mở rộng (extensions)](structure-extensions.md) hoặc cập nhật Yii đơn giản chỉ mới một dòng lệnh.
Ứng dụng Yii cần được tải về và cài đặt, điều này có kết quả giống nhau khi thực hiện cài đặt theo chuẩn.
Những ứng dụng Yii khi đã cài đặt đều được triển khai một số tính năng cơ bản, như đăng nhập (login), form liên hệ (contact form), vv.
Những tính năng trên đều được khuyến khích. Vì thế, nó có thể hữu ích như là một điểm bắt đầu tốt cho các dự án của bạn.
Mặc định, sau khi cài đặt Yii sẽ cung cấp cho bạn một số tính năng cơ bản, như đăng nhập (login), form liên hệ (contact form), vv.
Những tính năng trên đều được khuyến khích và sử dụng rộng rãi, vì thế, nó có thể hữu ích cho các dự án của bạn.
Trong bài hướng dẫn này và các phần tiếp theo, chúng ta sẽ tìm hiều cách cài ứng dụng Yii với tên *Basic Application Template*
làm thế nào để thực hiện các tính năng mới trên mẫu ứng dụng này. Yii đồng thời cũng cung cấp mẫu ứng dụng tên là [Advanced Application Template](tutorial-advanced-app.md)
mẫu này được dùng tốt hơn cho những đội dự án cần phát triển ứng dụng có nhiều tầng.
Trong bài hướng dẫn này và các phần tiếp theo, chúng ta sẽ tìm hiều cách cài ứng dụng Yii với tên *Basic Application Template*
làm thế nào để triển khai các tính năng mới trên mẫu ứng dụng này. Yii đồng thời cũng cung cấp mẫu ứng dụng tên là [Advanced Application Template](tutorial-advanced-app.md)
Template này hướng đến những đội dự án cần phát triển ứng dụng có nhiều tầng (multiple tiers).
> Lưu ý: Các mẫu ứng dụng *Basic Application Template* là thích hợp cho việc phát triển 90% của các ứng dụng Web. nó khác
với các mẫu ứng dụng [Advanced Application Template](tutorial-advanced-app.md). Nếu bạn là người mới tìm hiều về Yii, chúng tôi khuyến khích
bạn bắt đầu với các ứng dụng *Basic Application Template* , ứng dụng này đơn giản và ít chức năng thích hợp hơn cho việc tìm hiểu về Yii.
> Lưu ý: *Basic Application Template* thích hợp đến 90% cho việc phát triển web. Nó khác
với [Advanced Application Template](tutorial-advanced-app.md) trong cách tổ chức mã nguồn. Nếu bạn là người mới tìm hiều về Yii, chúng tôi khuyến khích
bạn bắt đầu với *Basic Application Template* , ứng dụng này đơn giản và ít chức năng. Thích hợp hơn cho việc tìm hiểu về Yii.
@ -22,25 +21,25 @@ Cài đặt qua trinh quản lý gói Composer <span id="installing-via-composer
-----------------------
Nếu bạn chưa cài Composer, bạn có thể cài đặt theo đường link sau
[getcomposer.org](https://getcomposer.org/download/). Trong hệ điều hành Linux và Mac OS X, bạn có thể chạy các lệnh sau đây:
[getcomposer.org](https://getcomposer.org/download/). Đối với hệ điều hành Linux và Mac OS X, bạn có thể chạy các lệnh sau đây:
curl -s http://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
Còn trên HDH Windows, bạn có thể tải về và chạy [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe).
Còn trên HĐH Windows, bạn có thể tải về và chạy [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe).
Nếu bạn có bất kỳ thắc mắc hoặc muốn biết thêm nghiên cứu chuyên sâu Composer, vui lòng tham khảo [Tài liệu Composer](https://getcomposer.org/doc/)
Nếu bạn có bất kỳ thắc mắc hoặc muốn biết thêm nghiên cứu chuyên sâu về Composer, vui lòng tham khảo [Tài liệu Composer](https://getcomposer.org/doc/)
Nếu bạn đã cài Composer rồi, hãy chắc chắn rằng bạn đang sử dụng phiên bản mới nhất. Bạn có thể cập nhật Composer bằng cách thực hiện lệnh
`composer self-update`.
Sau khi cài đặt Composer, bạn có thể cài đặt Yii bằng cách chạy lệnh sau ở thư mục Web mà ứng dụng cần chạy:
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
Câu lệnh đầu tiên sẽ cài đặt [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/)
Nó là thông qua Composer để quản lý bower và npm dùng cho việc quản lý các gói cần thiết. Bạn cần chạy câu lệnh này để có hiệu lực toàn hệ thống.
và cho phép Composer có thể quản lý những package dependencies của bower và npm. Câu lệnh này chỉ cần chạy một lần.
Câu lệnh thứ hai sẽ cài đặt phiên bản Yii có tên là `basic`. Bạn có thể chọn một tên thư mục khác nếu bạn muốn.
> Chú ý: Trong quá trình cài đặt Composer có thể yêu cầu thông tin đăng nhập từ tài khoản Github của bạn. điều này là bình thường bởi vì Composer
@ -62,12 +61,12 @@ Việc cài đặt Yii từ một tập tin lưu trữ bao gồm ba bước:
1. Tải gói cài đặt từ [yiiframework.com](http://www.yiiframework.com/download/).
2. Giải nén file tải về vào một thư mục Web của ứng dụng cần chạy.
3. Sửa đồi file `config/web.php` bởi nhập thông tin secret key (khóa bí mật) `cookieValidationKey` ở mục cấu hình
3. Sửa đồi file `config/web.php` bởi nhập thông tin secret key `cookieValidationKey` ở mục cấu hình
(này được thực hiện tự động nếu bạn đang cài đặt Yii sử dụng Composer):
```php
// !!! chèn một khóa bí mật trong phần sau (nếu rỗng) - điều này được yêu cầu cho cookie validation
'cookieValidationKey' => 'Nhập khóa bí mật vào đây',
// !!! chèn một secret key trong phần sau (nếu rỗng) - Việc này là cần thiết để xác thực cookie trong ứng dụng
'cookieValidationKey' => 'Nhập secret key tuỳ chọn vào đây',
```
@ -88,7 +87,7 @@ Nhưng cũng có những phương pháp cài đặt khác:
Kết quả cài đặt <span id="verifying-installation"></span>
--------------------------
Sau khi cài đặt, bạn có thể sử dụng trình duyệt để truy cập các ứng dụng Yii được cài đặt với các URL sau đây:
Sau khi cài đặt, bạn có thể sử dụng trình duyệt để truy cập ứng dụng Yii được cài đặt với URL dưới đây:
```
http://localhost/basic/web/index.php

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

@ -22,7 +22,7 @@
Composer 安装后,切换到一个可通过 Web 访问的目录,执行如下命令即可安装 Yii :
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
第一条命令安装 [Composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/),它是通过 Composer 管理 bower 和 npm 包所必须的,此命令全局生效,一劳永逸。

2
docs/guide-zh-CN/tutorial-yii-integration.md

@ -68,7 +68,7 @@ Yii::$classMap['Class2'] = 'path/to/Class2.php';
若这个第三方系统支持 Composer 管理他的依赖文件,你可以直接运行一下命令来安装 Yii:
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer require yiisoft/yii2
composer install

2
docs/guide/helper-overview.md

@ -76,5 +76,5 @@ Yii::$classMap['yii\helpers\ArrayHelper'] = '@app/components/ArrayHelper.php';
```
Note that customizing of helper classes is only useful if you want to change the behavior of an existing function
of the helpers. If you want to add additional functions to use in your application you may better create a separate
of the helpers. If you want to add additional functions to use in your application, you may be better off creating a separate
helper for that.

2
docs/guide/input-file-upload.md

@ -77,7 +77,7 @@ use yii\widgets\ActiveForm;
It is important to remember that you add the `enctype` option to the form so that the file can be properly uploaded.
The `fileInput()` call will render a `<input type="file">` tag which will allow users to select a file to upload.
> Tip: since version 2.0.8, [[yii\web\widgets\ActiveField::fileInput|fileInput]] adds `enctype` option to the form
> Tip: since version 2.0.8, [[yii\widgets\ActiveField::fileInput|fileInput]] adds `enctype` option to the form
automatically when file input field is used.
## Wiring Up <span id="wiring-up"></span>

4
docs/guide/input-forms.md

@ -12,6 +12,10 @@ to validate its input on the server-side (Check the [Validating Input](input-val
When creating model-based forms, the first step is to define the model itself. The model can be either based upon
an [Active Record](db-active-record.md) class, representing some data from the database, or a generic Model class
(extending from [[yii\base\Model]]) to capture arbitrary input, for example a login form.
> Tip: If the form fields are different from database columns or there are formatting and logic that is specific to that
> form only, prefer creating a separate model extended from [[yii\base\Model]].
In the following example, we show how a generic model can be used for a login form:
```php

6
docs/guide/input-multiple-models.md

@ -59,8 +59,10 @@ class UserController extends Controller
```
In the `update` action, we first load the `$user` and `$profile` models to be updated from the database. We then call
[[yii\base\Model::load()]] to populate these two models with the user input. If successful we will validate
the two models and save them. Otherwise we will render the `update` view which has the following content:
[[yii\base\Model::load()]] to populate these two models with the user input. If loading is successful, we will validate
the two models and then save them &mdash; please note that we use `save(false)` to skip over validations inside the models
as the user input data have already been validated. If loading is not successful, we will render the `update` view which
has the following content:
```php
<?php

18
docs/guide/rest-routing.md

@ -90,3 +90,21 @@ a controller ID. For example, the following code maps the name `u` to the contro
'controller' => ['u' => 'user'],
]
```
## Extra configuration for contained rules
It could be useful to specify extra configuration that is applied to each rule contained within [[yii\rest\UrlRule]].
A good example would be specifying defaults for `expand` parameter:
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => ['user'],
'ruleConfig' => [
'class' => 'yii\web\UrlRule',
'defaults' => [
'expand' => 'profile',
]
],
],
```

3
docs/guide/runtime-logging.md

@ -340,6 +340,9 @@ sending the content of the [[yii\log\Target::messages]] array to a designated me
[[yii\log\Target::formatMessage()]] method to format each message. For more details, you may refer to any of the
log target classes included in the Yii release.
> Tip: Instead of creating your own loggers you may try any PSR-3 compatible logger such
as [Monolog](https://github.com/Seldaek/monolog) by using
[PSR log target extension](https://github.com/samdark/yii2-psr-log-target).
## Performance Profiling <span id="performance-profiling"></span>

35
docs/guide/security-best-practices.md

@ -209,11 +209,44 @@ class SiteController extends Controller
}
```
Disabling CSRF validation in [standalone actions](structure-controllers.md#standalone-actions) must be done in `init()`
method. Do not place this code into `beforeRun()` method because it won't have effect.
```php
<?php
namespace app\components;
use yii\base\Action;
class ContactAction extends Action
{
public function init()
{
parent::init();
$this->controller->enableCsrfValidation = false;
}
public function run()
{
$model = new ContactForm();
$request = Yii::$app->request;
if ($request->referrer === 'yiipowered.com'
&& $model->load($request->post())
&& $model->validate()
) {
$model->sendEmail();
}
}
}
```
> Warning: Disabling CSRF will allow any site to send POST requests to your site. It is important to implement extra validation such as checking an IP address or a secret token in this case.
Further reading on the topic:
- <https://www.owasp.org/index.php/CSRF>
Avoiding file exposure
----------------------

2
docs/guide/start-installation.md

@ -58,7 +58,7 @@ by running `composer self-update`.
With Composer installed, you can install Yii by running the following commands under a Web-accessible folder:
```bash
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
```

4
docs/guide/structure-widgets.md

@ -34,9 +34,7 @@ use yii\jui\DatePicker;
'model' => $model,
'attribute' => 'from_date',
'language' => 'ru',
'clientOptions' => [
'dateFormat' => 'yy-mm-dd',
],
'dateFormat' => 'php:Y-m-d',
]) ?>
```

2
docs/guide/test-fixtures.md

@ -295,6 +295,8 @@ change this behavior with config or command options. You can exclude some fixtur
To load fixture, run the following command:
> Note: Prior to loading data unload sequence is executed. Usually that results in cleaning up all the existing data inserted by previous fixture executions.
```
yii fixture/load <fixture_name>
```

5
docs/guide/tutorial-performance-tuning.md

@ -187,6 +187,11 @@ by executing the following command:
composer dumpautoload -o
```
Additionally you may consider using
[authoritative class maps](https://getcomposer.org/doc/articles/autoloader-optimization.md#optimization-level-2-a-authoritative-class-maps)
and [APCu cache](https://getcomposer.org/doc/articles/autoloader-optimization.md#optimization-level-2-b-apcu-cache).
Note that both opmizations may or may not be suitable for your particular case.
## Processing Data Offline <span id="processing-data-offline"></span>

2
docs/guide/tutorial-start-from-scratch.md

@ -50,6 +50,6 @@ Use the Template
That's all that's required to create a new Yii project template. Now you can create projects using your template:
```
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer create-project --prefer-dist --stability=dev mysoft/yii2-app-coolone new-project
```

2
docs/guide/tutorial-yii-integration.md

@ -82,7 +82,7 @@ take two steps: install Yii, and bootstrap Yii.
If the third-party system uses Composer to manage its dependencies, you can simply run the following commands
to install Yii:
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer require yiisoft/yii2
composer install

12
docs/internals-ja/core-code-style.md

@ -12,8 +12,7 @@ Yii 2 コアフレームワークコードスタイル
しかし、コアコードや公式エクステンションに対して実際に寄稿する場合には、それらを英語で書く必要があります。
1. 概要
-------
## 1. 概要
全体として、私たちは [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) 互換のスタイルを使っていますので、
[PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) に適用されることは、すべて私たちのコードスタイルにも適用されます。
@ -29,8 +28,7 @@ Yii 2 コアフレームワークコードスタイル
- プロパティ名は private である場合はアンダースコアで始まらなければならない。
- `else if` ではなく常に `elseif` を使用すること。
2. ファイル
-----------
## 2. ファイル
### 2.1. PHP タグ
@ -43,13 +41,11 @@ Yii 2 コアフレームワークコードスタイル
PHP コードは BOM 無しの UTF-8 のみを使わなければなりません。
3. クラス名
-----------
## 3. クラス名
クラス名は `StudlyCaps` で宣言されなければなりません。例えば、`Controller`、`Model`。
4. クラス
---------
## 4. クラス
ここで "クラス" という用語はあらゆるクラスとインタフェイスを指すものとします。

2
docs/internals-ja/git-workflow.md

@ -35,7 +35,7 @@ git remote add upstream git://github.com/yiisoft/yii2.git
- `composer install` を実行して、依存パッケージをインストールします ([composer をグローバルにインストール](https://getcomposer.org/doc/00-intro.md#globally) したものと仮定しています)。
> Note: `Problem 1 The requested package bower-asset/jquery could not be found in any version, there may be a typo in the package name.` というようなエラーが生ずる場合は、`composer global require "fxp/composer-asset-plugin:^1.2.0"` を実行する必要があります。
> Note: `Problem 1 The requested package bower-asset/jquery could not be found in any version, there may be a typo in the package name.` というようなエラーが生ずる場合は、`composer global require "fxp/composer-asset-plugin:^1.3.1"` を実行する必要があります。
JavaScript を扱おうとしている場合は、
- `npm install` を実行して JavaScript テストツール群とその依存ライブラリをインストールします

2
docs/internals-pl/automation.md

@ -16,6 +16,8 @@ Istnieją zadania wykonywane automatycznie podczas pracy nad Yii:
- Uaktualnianie magicznego pliku z typami Mime (`framework/helpers/mimeTypes.php`) z repozytorium Apache HTTPd.
Uruchom `./build/build mime-type`, aby uaktualnić plik.
- Korekta porządku wpisów w pliku CHANGELOG może być przeprowadzona poprzez uruchomienie `./build/build release/sort-changelog framework`.
Wszystkie powyższe komendy są uruchamiane w [procesie wydawania nowej wersji](release.md).
Mogą być też uruchomione pomiędzy wydaniami, ale nie jest to konieczne.

12
docs/internals-pl/core-code-style.md

@ -7,8 +7,7 @@ stosowania go we własnych aplikacjach. Wybierz styl, który najbardziej odpowia
Możesz pobrać gotową konfigurację dla CodeSniffera pod adresem: https://github.com/yiisoft/yii2-coding-standards
1. Omówienie
------------
## 1. Omówienie
Używamy przede wszystkim standardu kodowania
[PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md), zatem wszystko, co dotyczy
@ -26,8 +25,7 @@ kodowania.
- Nazwy właściwości klasy MUSZĄ zaczynać się podkreślnikiem, jeśli są prywatne.
- Należy używać `elseif` zamiast `else if`.
2. Pliki
--------
## 2. Pliki
### 2.1. Tagi PHP
@ -40,13 +38,11 @@ kodowania.
Kod PHP MUSI używać wyłącznie UTF-8 bez znacznika BOM.
3. Nazwy klas
-------------
## 3. Nazwy klas
Nazwy klas MUSZĄ być zadeklarowane w formacie `StudlyCaps`. Przykładowo `Controller`, `Model`.
4. Klasy
--------
## 4. Klasy
Termin "klasa" odnosi się tutaj do wszystkich klas i interfejsów.

4
docs/internals-pl/design-decisions.md

@ -25,3 +25,7 @@ powinna być najpierw zatwierdzona przez głównych deweloperów.
Dodatkowo, pomimo tego, że unsigned int podwaja jego zakres, jeśli tabela wymaga tak dużych liczb, bezpieczniej jest używać typu
bigint lub mediumint, niż polegać na unsigned.
<https://github.com/yiisoft/yii/pull/1923#issuecomment-11881967>
6. [Klasy pomocnicze vs oddzielne niestatyczne klasy](https://github.com/yiisoft/yii2/pull/12661#issuecomment-251599463)
7. **Łańcuchowanie metod setterów** powinno być unikane, jeśli w klasie znajdują się metody zwracające ważne wartości.
Łańcuchowanie może być wspierane, jeśli klasa jest typu budującego, gdzie wszystkie settery modyfikują jedynie wewnętrzne stany: https://github.com/yiisoft/yii2/issues/13026

31
docs/internals-pl/git-workflow.md

@ -22,6 +22,8 @@ Jeśli napotkasz na problemy związane z Gitem i GitHubem na systemie operacyjny
"Permission Denied (publickey)" ("Odmowa dostępu (klucz publiczny)"), musisz odpowiednio
[skonfigurować instalację Gita do pracy z GitHubem](http://help.github.com/linux-set-up-git/).
> Tip: jeśli nie jesteś biegły w używaniu Gita, polecamy doskonałą darmową książkę [Pro Git](https://git-scm.com/book/en/v2) (z polskim tłumaczeniem dla [poprzedniej edycji](https://git-scm.com/book/pl/v1).
### 2. Dodaj główne repozytorium Yii jako dodatkowy zdalny git nazwany "upstream"
Przejdź do folderu, do którego sklonowałeś Yii (zwykle "yii2") i uruchom następującą komendę:
@ -34,15 +36,24 @@ git remote add upstream git://github.com/yiisoft/yii2.git
Poniższe kroki nie są wymagane, jeśli chcesz pracować tylko nad tłumaczeniami lub dokumentacją.
- uruchom `composer update`, aby zainstalować wymagane zależności (zakładając, że masz [composera zainstalowanego globalnie](https://getcomposer.org/doc/00-intro.md#globally)).
- uruchom `composer install`, aby zainstalować wymagane zależności (zakładając, że masz [composera zainstalowanego globalnie](https://getcomposer.org/doc/00-intro.md#globally)).
> Note: Jeśli otrzymujesz błędu typu `Problem 1 The requested package bower-asset/jquery could not be found in any version, there may be a typo in the package name.` (`Problem 1 Wymagany pakiet bower-asset/jquery nie mógł być znaleziony w jakiejkolwiek wersji, być może w nazwie pakietu jest literówka.`), musisz uruchomić komendę `composer global require "fxp/composer-asset-plugin:^1.3.1"`
Jeśli zamierzasz pracować z JavaScript:
> Note: Jeśli otrzymujesz błędu typu `Problem 1 The requested package bower-asset/jquery could not be found in any version, there may be a typo in the package name.` (`Problem 1 Wymagany pakiet bower-asset/jquery nie mógł być znaleziony w jakiejkolwiek wersji, być może w nazwie pakietu jest literówka.`), musisz uruchomić komendę `composer global require "fxp/composer-asset-plugin:^1.2.0"`
- uruchom `npm install`, aby zainstalować narzędzia testerskie JavaScript i ich zależności (zakładając, że masz [zainstalowane Node.js i NPM]
(https://nodejs.org/en/download/package-manager/)).
- uruchom komendę `php build/build dev/app basic`, aby sklonować podstawowy szablon projektu aplikacji i zainstaluj dla niego zależności composera.
> Note: testy JavaScript są zależne od biblioteki [jsdom](https://github.com/tmpvar/jsdom), która wymaga Node.js 4 lub nowszego.
Zalecane jest używanie Node.js w wersji 6 lub 7.
- uruchom komendę `php build/build dev/app basic <fork>`, aby sklonować podstawowy szablon projektu aplikacji i zainstaluj dla niego zależności composera.
`<fork>` jest URL Twojego forka repozytorium, np. `git@github.com:my_nickname/yii2-app-basic.git`. Jeśli jesteś kontrybutorem głównego kodu frameworka, możesz pominąć wskazywanie forka.
Komenda ta zainstaluje normalnie pakiety composera, ale jednocześnie podlinkuje folder yii2 do
pobranego wcześniej repozytorium, dzięki czemu otrzymasz instalację jednej instacji całego kodu na raz.
Powtórz ten krok dla zaawansowanego szablonu projektu aplikacji, jeśli chcesz: `php build/build dev/app advanced`.
Powtórz ten krok dla zaawansowanego szablonu projektu aplikacji, jeśli chcesz: `php build/build dev/app advanced <fork>`.
Ta komenda służy również do aktualizacji zależności; uruchamia wewnętrznie `composer update`.
@ -56,7 +67,8 @@ Poniższe kroki są opcjonalne.
### Testy jednostkowe
Możesz uruchomić testy jednostkowe za pomocą komendy `phpunit` w głównym folderze repozytorium.
Jeśli nie posiadasz phpunit zainstalowanego globalnie, użyj zamiast tego komendy `php vendor/bin/phpunit`.
Jeśli nie posiadasz phpunit zainstalowanego globalnie, użyj zamiast tego komendy `php vendor/bin/phpunit` lub
`vendor/bin/phpunit.bat` w przypadku korzystania z systemu Windows.
Niektóre testy wymagają przygotowania i skonfigurowania dodatkowych baz danych. Możesz utworzyć plik `tests/data/config.local.php`,
aby nadpisać konfigurację ustawioną w `tests/data/config.php`.
@ -64,19 +76,22 @@ aby nadpisać konfigurację ustawioną w `tests/data/config.php`.
Możesz ograniczyć testy do grupy tych, nad którymi akurat pracujesz, np. aby uruchomić tylko testy walidatorów i redisa użyj
`phpunit --group=validators,redis`. Możesz zobaczyć listę dostępnych grup po wpisaniu `phpunit --list-groups`.
Możesz rozpocząć testy jednostkowe JavaScript, uruchamiając `npm test` w głównym folderze repozytorium.
### Rozszerzenia
Aby pracować nad rozszerzeniami, musisz sklonować ich repozytoria. Stworzyliśmy komendę, która pozwoli Ci to zrobić w prosty sposób:
```
php build/build dev/ext <nazwa-rozszerzenia>
php build/build dev/ext <nazwa-rozszerzenia> <fork>
```
Oczywiście zamiast `<nazwa-rozszerzenia>` wpisz konkretną jego nazwę, np. `redis`.
gdzie `<nazwa-rozszerzenia>` jest poprawną nazwą, np. `redis`, a `<fork>` jest URL forka rozszerzenia np. `git@github.com:my_nickname/yii2-redis.git`.
Jeśli jesteś kontrybutorem głównego kodu frameworka, możesz pominąć wskazywanie forka.
Jeśli chcesz przetestować rozszerzenie w jednym z szablonów projektów, po prostu dodaj je do pliku `composer.json` aplikacji
w zwyczajowy sposób, np. dodaj `"yiisoft/yii2-redis": "~2.0.0"` do sekcji `require` w podstawowym szablonie aplikacji.
Uruchomienie `php build/build dev/app basic` zainstaluje rozszerzenie i jego zależności i utworzy symlink do folderu
Uruchomienie `php build/build dev/app basic <fork>` zainstaluje rozszerzenie i jego zależności i utworzy symlink do folderu
`extensions/redis`, dzięki czemu możesz pracować bezpośrednio w repozytorium yii2, a nie folderze vendorowym composera.
> Note: Również w tym przypadku pamiętaj o fladze `--useHttp`, jak to opisano powyżej.

16
docs/internals-ru/core-code-style.md

@ -5,8 +5,7 @@
Пример конфигурационного файла для CodeSniffer вы можете найти здесь: https://github.com/yiisoft/yii2-coding-standards
1. Обзор
-----------
## 1. Обзор
В общем, мы используем совместимый со стандартом [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) стиль, так что все положения [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) вполне применимы к нашему стилю кодирования.
@ -21,8 +20,7 @@
- Имена свойств ДОЛЖНЫ начинаться с подчеркивания если они объявлены с использованием модификатора `private`;
- Всегда используйте `elseif` вместо `else if`.
2. Файлы
--------
## 2. Файлы
### 2.1. Теги PHP
@ -35,13 +33,11 @@
PHP код должен содержать только символы в кодировке UTF-8 без BOM.
3. Имена Классов
--------------
## 3. Имена Классов
Имена классов ДОЛЖНЫ быть определены используя `StudlyCaps`. Например, `Controller`, `Model`.
4. Классы
----------
## 4. Классы
В данном случае, под классом подразумеваются все классы и интерфейсы.
@ -473,7 +469,7 @@ public function getEventHandlers($name)
### Каталоги/пространства имен
- Используйте нижний регистр;
- используйте множественную форму для существительных, представляющих объекты (например валидаторы);
- используйте единичную форму для имен, представляющих соответствующий функционал (например web);
- используйте множественное число для существительных, представляющих объекты (например валидаторы);
- используйте единственное число для имен, представляющих соответствующий функционал (например web);
- предпочтительнее использовать однословные пространства имён;
- если одно слово использовать не удаётся, используйте camelCase стиль.

2
docs/internals-ru/git-workflow.md

@ -36,7 +36,7 @@ git remote add upstream git://github.com/yiisoft/yii2.git
- выполните `composer update` для установки зависимостей (если [composer у вас установлен глобально](https://getcomposer.org/doc/00-intro.md#globally)).
> Note: Если вы видите такие ошибки, как `Problem 1 The requested package bower-asset/jquery could not be found in
> any version, there may be a typo in the package name.`, необходимо запустить `composer global require "fxp/composer-asset-plugin:^1.2.0"`
> any version, there may be a typo in the package name.`, необходимо запустить `composer global require "fxp/composer-asset-plugin:^1.3.1"`
- выполните `php build/build dev/app basic` для клонирования базового приложения и установки его зависимостей.
Эта команда установит сторонние пакеты composer обычным образом, но создаст ссылку с репозитория yii2 на только

12
docs/internals-uk/core-code-style.md

@ -7,8 +7,7 @@
Ви можете отримати конфігурацію для CodeSniffer за посиланням: https://github.com/yiisoft/yii2-coding-standards
1. Загальні положення
---------------------
## 1. Загальні положення
В основному командою розробників використовується стиль сумісний з [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md),
тому все, що стосується
@ -25,8 +24,7 @@
- Імена приватних властивостей ПОВИННІ починатись з підкреслення.
- Завжди використовуйте `elseif` замість `else if`.
2. Файли
--------
## 2. Файли
### 2.1. Теги PHP
@ -39,13 +37,11 @@
PHP код ПОВИНЕН використовувати лише UTF-8 без BOM.
3. Імена класів
---------------
## 3. Імена класів
Імена класів ПОВИННІ оголошуватись як `StudlyCaps`. Наприклад: `Controller`, `Model`.
4. Класи
--------
## 4. Класи
Тут термін "клас" відноситься до всіх класів та інтерфейсів.

12
docs/internals/core-code-style.md

@ -7,8 +7,7 @@ what suits you better.
You can get a config for CodeSniffer here: https://github.com/yiisoft/yii2-coding-standards
1. Overview
-----------
## 1. Overview
Overall we're using [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
compatible style so everything that applies to
@ -26,8 +25,7 @@ style as well.
- Property names MUST start with an initial underscore if they are private.
- Always use `elseif` instead of `else if`.
2. Files
--------
## 2. Files
### 2.1. PHP Tags
@ -40,13 +38,11 @@ style as well.
PHP code MUST use only UTF-8 without BOM.
3. Class Names
--------------
## 3. Class Names
Class names MUST be declared in `StudlyCaps`. For example, `Controller`, `Model`.
4. Classes
----------
## 4. Classes
The term "class" refers to all classes and interfaces here.

2
docs/internals/git-workflow.md

@ -37,7 +37,7 @@ The following steps are not necessary if you want to work only on translations o
- run `composer install` to install dependencies (assuming you have [composer installed globally](https://getcomposer.org/doc/00-intro.md#globally)).
> Note: If you see errors like `Problem 1 The requested package bower-asset/jquery could not be found in any version, there may be a typo in the package name.`, you will need to run `composer global require "fxp/composer-asset-plugin:^1.2.0"`
> Note: If you see errors like `Problem 1 The requested package bower-asset/jquery could not be found in any version, there may be a typo in the package name.`, you will need to run `composer global require "fxp/composer-asset-plugin:^1.3.1"`
If you are going to work with JavaScript:

83
framework/CHANGELOG.md

@ -4,43 +4,88 @@ Yii Framework 2 Change Log
2.0.12 under development
--------------------------
- Bug #13657: Fixed `yii\helpers\StringHelper::truncateHtml()` skip extra tags at the end (sam002)
- Bug #7946 Fixed a bug when the `form` attribute was not propagated to the hidden input of the checkbox (Kolyunya)
- Bug #13087: Fixed getting active validators for safe attribute (developeruz)
- Bug #13571: Fix `yii\db\mssql\QueryBuilder::checkIntegrity` for all tables (boboldehampsink)
- Bug #4408: Add support for unicode word characters and `+` character in attribute names (sammousa, kmindi)
- Bug #7946: Fixed a bug when the `form` attribute was not propagated to the hidden input of the checkbox (Kolyunya)
- Bug #8120: Fixes LIKE special characters escaping for Cubrid/MSSQL/Oracle/SQLite in `yii\db\QueryBuilder` (sergeymakinen)
- Bug #10346: Fixed "DOMException: Invalid Character Error" in `yii\web\XmlResponseFormatter::buildXml()` (sasha-ch)
- Bug #10372: Fixed console controller including complex typed arguments in help (sammousa)
- Bug #11230: Include `defaultRoles` in `yii\rbac\DbManager->getRolesByUser()` results (developeruz)
- Enh #13243: Added support for unicode attribute names in `yii\widgets\DetailView` (arogachev)
- Bug #11404: `yii\base\Model::loadMultiple()` returns true even if `yii\base\Model::load()` returns false (zvook)
- Bug #11719: Fixed `yii\db\Connection::$enableQueryCache` caused infinite loop when the same connection was used for `yii\caching\DbCache` (michaelarnauts)
- Bug #12715: Exception `SAVEPOINT LEVEL1 does not exist` instead of deadlock exception (Vovan-VE)
- Bug #13086, #13656: Fixed bug with optional parameters at the beginning of pattern in `yii\web\UrlRule` (rob006)
- Bug #13087: Fixed getting active validators for safe attribute (developeruz, klimov-paul)
- Bug #13306: Wildcard in `reloadableScripts` in `yii.js` allows 0 characters (arogachev)
- Bug #13340: Fixed `yii\db\Connection::useMaster()` - Exception within callback completely disables slaves (Vovan-VE)
- Bug #13340: Fixed `yii\db\Connection::useMaster()` - exception within callback completely disables slaves (Vovan-VE)
- Bug #13343: Fixed `yii\i18n\Formatter::asTime()` to process time-only values without time zone conversion (bizley)
- Bug #13418: Fixed `QueryBuilder::batchInsert()` if $rows is `\Generator` (lav45)
- Bug #13362: Fixed return value of `yii\caching\MemCache::setValues()` (masterklavi)
- Bug #13379: Fixed `applyFilter()` function in `yii.gridView.js` to work correctly when params in `filterUrl` are indexed (SilverFire, arogachev)
- Bug #13418: Fixed `QueryBuilder::batchInsert()` if `$rows` is `\Generator` (lav45)
- Bug #13494: Fixed `yii\console\controllers\MessageConstroller::saveMessagesToDb()` to work on different DBMS correctly (silverfire)
- Bug #13513: Fixed RBAC migration to work correctly on Oracle DBMS (silverfire)
- Bug #13537: Fixed `yii\web\CacheSession::destroySession()` to work correctly when session is not written yet (silverfire, papalapa)
- Bug #13538: Fixed `yii\db\BaseActiveRecord::deleteAll()` changes method signature declared by `yii\db\ActiveRecordInterface::deleteAll()` (klimov-paul)
- Bug #13571: Fix `yii\db\mssql\QueryBuilder::checkIntegrity` for all tables (boboldehampsink)
- Bug #13577: `yii\db\QueryBuilder::truncateTable` should work consistent over all databases (boboldehampsink)
- Bug #13582: PK column in `yii\db\pgsql\QueryBuilder::resetSequence()` was not quoted properly (boboldehampsink)
- Bug #13592: Fixes Oracle’s `yii\db\oci\Schema::setTransactionIsolationLevel()` (sergeymakinen)
- Bug #13592: Fixes `yii\db\oci\Schema::setTransactionIsolationLevel()` in Oracle (sergeymakinen)
- Bug #13594: Fixes insufficient quoting in `yii\db\QueryBuilder::prepareInsertSelectSubQuery()` (sergeymakinen)
- Bug #8120: Fixes LIKE special characters escaping for Cubrid/MSSQL/Oracle/SQLite in `yii\db\QueryBuilder` (sergeymakinen)
- Bug #13649: Fixes issue where `['uncheck' => false]` and `['label' => false]` options for `ActiveRadio` and `ActiveCheckbox` were ignored (Alex-Code)
- Bug #13657: Fixed `yii\helpers\StringHelper::truncateHtml()` skip extra tags at the end (sam002)
- Bug #13670: Fixed alias option from console when it includes `-` or `_` in option name (pana1990)
- Bug #13671: Fixed error handler trace to work correctly with XDebug (samdark)
- Bug #13689: Fixed handling of errors in closures (mikehaertl)
- Bug #13694: `yii\widgets\Pjax` now sends `X-Pjax-Url` header with response to fix redirect (wleona3, Faryshta)
- Bug #13704: Fixed `yii\validators\UniqueValidator` to prefix attribute name with model's database table name (vladis84)
- Bug #13707: Fixed `yii\web\ErrorHandler` and `yii\web\ErrorAction` not setting correct response code to response object before rendering error view (samdark)
- Bug #13728: Fixed the bug when `yii\behaviors\SluggableBehavior` wasn't preserving immutable slug values (Kolyunya)
- Bug #13738: Fixed `getQueryParams()` method in `yii.js` to correctly parse URL with question mark and no query parameters (vladdnepr)
- Bug #13776: Fixed setting precision and scale for decimal columns in MSSQL (arturf)
- Bug #13790: Fixed error in `\yii\widgets\MaskedInput` JavaScript by raising version required (samdark)
- Bug #13807: Fixed `yii\db\QueryBuilder` to inherit subquery params when building a `INSERT INTO ... SELECT` query (sergeymakinen)
- Bug #13848: `yii\di\Instance::ensure()` wasn't throwing an exception when `$type` is specified and `$reference` object isn't instance of `$type` (c-jonua)
- Bug #13901: Fixed passing unused parameter to `formatMessage()` call in `\yii\validators\IpValidator` (Kolyunya)
- Bug #13961: Fixed `unserialize()` error during RBAC rule retrieving from PostgreSQL DBMS (vsguts)
- Bug #14012: `yii\db\pgsql\Schema::findViewNames()` was skipping materialized views (insolita)
- Bug #14033: Fixed `yii\filters\AccessRule::matchIp()` erroring in case IP is not defined under HHVM (Kolyunya)
- Bug #14052: Fixed processing parse errors on PHP 7 since these are instances of `\ParseError` (samdark)
- Enh #8641: Enhanced `yii\console\Request::resolve()` to prevent passing parameters, that begin from digits (silverfire)
- Enh #13144: Refactored `yii\db\Query::queryScalar()` (Alex-Code)
- Enh #13179: Added `yii\data\Sort::parseSortParam` allowing to customize sort param in descendant class (leandrogehlen)
- Enh #13221: Make `\yii\db\QueryTrait::limit()` and `\yii\db\QueryTrait::offset()` methods work with `\yii\db\Expression` (Ni-san)
- Enh #13226: `yii cache` command now warns about the fact that it's not able to flush APC cache from console (samdark)
- Enh #13240: Client scripts registration in `yii\widgets\ActiverForm` was moved to the separate `registerClientScript()` method (uaoleg, silverfire)
- Enh #13243: Added support for unicode attribute names in `yii\widgets\DetailView` (arogachev)
- Enh #13254: Core validators no longer require `Yii::$app` to be set (sammousa)
- Enh #13278: `yii\caching\DbQueryDependency` created allowing specification of the cache dependency via `yii\db\QueryInterface` (klimov-paul)
- Enh #13360: Added Dockerized test setup for the framework tests (schmunk42)
- Enh #13369: Added ability to render current `yii\widgets\LinkPager` page disabled (aquy)
- Enh #13376: Data provider now automatically sets an ID so there is no need to set it manually in case multiple data providers are used with pagination (SamMousa)
- Enh #13407: Added URL-safe base64 encode/decode methods to `StringHelper` (andrewnester)
- Enh #13467: `yii\data\ActiveDataProvider` no longer queries models if models count is zero (kLkA, Kolyunya)
- Enh #13523: Plural rule for pasta (developeruz)
- Enh #13550: Refactored unset call order in `yii\di\ServiceLocator::set()` (Lanrik)
- Enh #13523: Fixed pluralization and singularization for words `pasta`, `currency` (developeruz, silverfire)
- Enh #13550: Refactored `unset()` call order in `yii\di\ServiceLocator::set()` (Lanrik)
- Enh #13560: Refactored `\yii\widgets\FragmentCache::getCachedContent()`, added tests (Kolyunya)
- Enh #13576: Added support of `srcset` to `yii\helpers\Html::img()` (Kolyunya)
- Enh #13577: Implemented `yii\db\mssql\QueryBuilder::resetSequence()` (boboldehampsink)
- Enh #13582: Added tests for all `yii\db\QueryBuilder::resetSequence` implementations, fixed SQLite implementation (boboldehampsink)
- Enh #13407: Added URL-safe base64 encode/decode methods to `StringHelper` (andrewnester)
- Bug #13649: Fixes issue where `['uncheck' => false]` and `['label' => false]` options for `ActiveRadio` and `ActiveCheckbox` were ignored (Alex-Code)
- Enh #13221: Make `\yii\db\QueryTrait::limit()` and `\yii\db\QueryTrait::offset()` methods work with `\yii\db\Expression` (Ni-san)
- Enh #13144: Refactored `yii\db\Query::queryScalar()` (Alex-Code)
- Bug #13379: Fixed `applyFilter` function in `yii.gridView.js` to work correctly when params in `filterUrl` are indexed (SilverFire, arogachev)
- Enh #13582: Added tests for all `yii\db\QueryBuilder::resetSequence()` implementations, fixed SQLite implementation (boboldehampsink)
- Enh #13650: Improved `yii\base\Security::hkdf()` to take advantage of native `hash_hkdf()` implementation in PHP >= 7.1.2 (charlesportwoodii)
- Bug #13379: Fixed `applyFilter` function in `yii.gridView.js` to work correctly when params in `filterUrl` are indexed (SilverFire)
- Bug #13670: Fixed alias option from console when it includes `-` or `_` in option name (pana1990)
- Enh #13695: `yii\web\Response::setStatusCode()` method now returns the Response object itself (kyle-mccarthy)
- Enh #13698: `yii\grid\DataColumn` filter is automatically generated as dropdown list in case of `format` set to `boolean` (bizley)
- Enh #13770: Added support for `yii\widgets\Menu` item classes definition in the form of an array (Kolyunya)
- Enh #13820: Add new HTTP status code 451 (yyxx9988)
- Enh #13823: Refactored migrations template (Kolyunya)
- Enh #13837: Refactored masking of CSRF tokens (sammousa)
- Enh #13845: `mt_rand()` is used instead of `rand()` in `yii\captcha\CaptchaAction` (kalessil)
- Enh #13883: `yii\data\SqlDataProvider` now provides automatic fallback for the case when `totalCount` is not specified (SamMousa)
- Enh #13911: Significantly enhanced MSSQL schema reading performance (paulzi, WebdevMerlion)
- Enh #13945: Removed Courier New from error page fonts list since it looks bad on Linux (samdark)
- Enh #13963: Added tests for `yii\behaviors\TimestampBehavior` (vladis84)
- Enh #13976: Disabled IPv6 check on `\yii\validators\IpValidator` as it turns out it is not needed for `inet_*` methods to work (mikk150)
- Enh #13981: `yii\caching\Cache::getOrSet()` now supports both `Closure` and `callable` (silverfire)
- Enh #13994: Refactored `yii\filters\RateLimiter`. Added tests (vladis84)
- Enh #14059: Removed unused AR instantiating for calling of static methods (ElisDN)
- Enh: Added `yii\di\Instance::__set_state()` method to restore object after serialization using `var_export()` function (silvefire)
2.0.11.2 February 08, 2017

2
framework/README.md

@ -15,7 +15,7 @@ The preferred way to install the Yii framework is through [composer](http://getc
Either run
```
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer require yiisoft/yii2
```

13
framework/UPGRADE.md

@ -22,7 +22,7 @@ Before upgrading, make sure you have a global installation of the latest version
as well as a stable version of Composer:
composer self-update
composer global require "fxp/composer-asset-plugin:^1.2.0" --no-plugins
composer global require "fxp/composer-asset-plugin:^1.3.1" --no-plugins
The simple way to upgrade Yii, for example to version 2.0.10 (replace this with the version you want) will be running `composer require`:
@ -56,6 +56,15 @@ Upgrade from Yii 2.0.11
* `yii\i18n\Formatter::normalizeDatetimeValue()` returns now array with additional third boolean element
indicating whether the timestamp has date information or it is just time value.
* `yii\grid\DataColumn` filter is now automatically generated as dropdown list with localized `Yes` and `No` strings
in case of `format` being set to `boolean`.
* The signature of `yii\db\QueryBuilder::prepareInsertSelectSubQuery()` was changed. The method has got an extra optional parameter
`$params`.
* The signature of `yii\cache\Cache::getOrSet()` has been adjusted to also accept a callable and not only `Closure`.
If you extend this method, make sure to adjust your code.
Upgrade from Yii 2.0.10
-----------------------
@ -266,7 +275,7 @@ Upgrade from Yii 2.0 Beta
the composer-asset-plugin, *before* you update your project:
```
php composer.phar global require "fxp/composer-asset-plugin:~1.0.0"
php composer.phar global require "fxp/composer-asset-plugin:~1.3.1"
```
You also need to add the following code to your project's `composer.json` file:

6
framework/assets/yii.js

@ -273,8 +273,10 @@ window.yii = (function ($) {
return {};
}
var pairs = url.substring(pos + 1).split('#')[0].split('&'),
params = {};
var pairs = $.grep(url.substring(pos + 1).split('#')[0].split('&'), function (value) {
return value !== '';
});
var params = {};
for (var i = 0, len = pairs.length; i < len; i++) {
var pair = pairs[i].split('=');

2
framework/base/Behavior.php

@ -23,7 +23,7 @@ namespace yii\base;
class Behavior extends Object
{
/**
* @var Component the owner of this behavior
* @var Component|null the owner of this behavior
*/
public $owner;

2
framework/base/Controller.php

@ -212,7 +212,7 @@ class Controller extends Component implements ViewContextInterface
* where `Xyz` stands for the action ID. If found, an [[InlineAction]] representing that
* method will be created and returned.
* @param string $id the action ID.
* @return Action the newly created action instance. Null if the ID doesn't resolve into any action.
* @return Action|null the newly created action instance. Null if the ID doesn't resolve into any action.
*/
public function createAction($id)
{

4
framework/base/ErrorHandler.php

@ -38,7 +38,7 @@ abstract class ErrorHandler extends Component
*/
public $memoryReserveSize = 262144;
/**
* @var \Exception the exception that is being handled currently.
* @var \Exception|null the exception that is being handled currently.
*/
public $exception;
@ -316,7 +316,7 @@ abstract class ErrorHandler extends Component
/**
* Converts an exception into a simple string.
* @param \Exception $exception the exception being converted
* @param \Exception|\Error $exception the exception being converted
* @return string the string representation of the exception.
*/
public static function convertExceptionToString($exception)

16
framework/base/Event.php

@ -211,13 +211,15 @@ class Event extends Object
);
foreach ($classes as $class) {
if (!empty(self::$_events[$name][$class])) {
foreach (self::$_events[$name][$class] as $handler) {
$event->data = $handler[1];
call_user_func($handler[0], $event);
if ($event->handled) {
return;
}
if (empty(self::$_events[$name][$class])) {
continue;
}
foreach (self::$_events[$name][$class] as $handler) {
$event->data = $handler[1];
call_user_func($handler[0], $event);
if ($event->handled) {
return;
}
}
}

2
framework/base/Model.php

@ -849,7 +849,7 @@ class Model extends Component implements IteratorAggregate, ArrayAccess, Arrayab
public static function loadMultiple($models, $data, $formName = null)
{
if ($formName === null) {
/* @var $first Model */
/* @var $first Model|false */
$first = reset($models);
if ($first === false) {
return false;

2
framework/base/Module.php

@ -606,7 +606,7 @@ class Module extends ServiceLocator
* Note that this method does not check [[modules]] or [[controllerMap]].
*
* @param string $id the controller ID.
* @return Controller the newly created controller instance, or `null` if the controller ID is invalid.
* @return Controller|null the newly created controller instance, or `null` if the controller ID is invalid.
* @throws InvalidConfigException if the controller class and its file name do not match.
* This exception is only thrown when in debug mode.
*/

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

Loading…
Cancel
Save