Commit 443779d6 by Qiang Xue

Merge commit '81c3c48c' into console-gii

Conflicts: framework/console/controllers/HelpController.php
parents 6a9b3c77 81c3c48c
......@@ -10,7 +10,9 @@ defined('YII_ENV') or define('YII_ENV', 'test');
require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../../common/config/aliases.php');
require(__DIR__ . '/../../common/config/bootstrap.php');
require(__DIR__ . '/../config/bootstrap.php');
$config = require(__DIR__ . '/../../tests/codeception/config/backend/acceptance.php');
......
......@@ -4,7 +4,8 @@ defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../../common/config/aliases.php');
require(__DIR__ . '/../../common/config/bootstrap.php');
require(__DIR__ . '/../config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../common/config/main.php'),
......
......@@ -10,7 +10,8 @@ defined('YII_ENV') or define('YII_ENV', 'test');
require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../../common/config/aliases.php');
require(__DIR__ . '/../../common/config/bootstrap.php');
require(__DIR__ . '/../config/bootstrap.php');
$config = require(__DIR__ . '/../../tests/codeception/config/frontend/acceptance.php');
......
......@@ -4,7 +4,8 @@ defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../../common/config/aliases.php');
require(__DIR__ . '/../../common/config/bootstrap.php');
require(__DIR__ . '/../config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../common/config/main.php'),
......
......@@ -17,7 +17,8 @@ defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/common/config/aliases.php');
require(__DIR__ . '/common/config/bootstrap.php');
require(__DIR__ . '/console/config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/common/config/main.php'),
......
......@@ -4,7 +4,8 @@ defined('YII_ENV') or define('YII_ENV', 'prod');
require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../../common/config/aliases.php');
require(__DIR__ . '/../../common/config/bootstrap.php');
require(__DIR__ . '/../config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../common/config/main.php'),
......
......@@ -4,7 +4,8 @@ defined('YII_ENV') or define('YII_ENV', 'prod');
require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../../common/config/aliases.php');
require(__DIR__ . '/../../common/config/bootstrap.php');
require(__DIR__ . '/../config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../common/config/main.php'),
......
......@@ -17,7 +17,8 @@ defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/common/config/aliases.php');
require(__DIR__ . '/common/config/bootstrap.php');
require(__DIR__ . '/console/config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/common/config/main.php'),
......
......@@ -9,7 +9,8 @@ defined('YII_TEST_BACKEND_ENTRY_FILE') or define('YII_TEST_BACKEND_ENTRY_FILE',
require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
require(YII_APP_BASE_PATH . '/common/config/aliases.php');
require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
require_once(YII_APP_BASE_PATH . '/backend/config/bootstrap.php');
// set correct script paths
......
......@@ -15,9 +15,9 @@ defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', dirname(dirname(dirn
require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
require_once(YII_APP_BASE_PATH . '/common/config/aliases.php');
require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
Yii::setAlias('@tests', dirname(dirname(__DIR__)));
\ No newline at end of file
Yii::setAlias('@tests', dirname(dirname(__DIR__)));
......@@ -6,9 +6,9 @@ defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', dirname(dirname(dirn
require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
require(YII_APP_BASE_PATH . '/common/config/aliases.php');
require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
// set correct script paths
$_SERVER['SERVER_NAME'] = 'localhost';
Yii::setAlias('@tests', dirname(dirname(__DIR__)));
\ No newline at end of file
Yii::setAlias('@tests', dirname(dirname(__DIR__)));
......@@ -6,9 +6,10 @@ defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', dirname(dirname(dirn
require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
require(YII_APP_BASE_PATH . '/common/config/aliases.php');
require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
require_once(YII_APP_BASE_PATH . '/console/config/bootstrap.php');
// set correct script paths
$_SERVER['SERVER_NAME'] = 'localhost';
Yii::setAlias('@tests', dirname(dirname(__DIR__)));
\ No newline at end of file
Yii::setAlias('@tests', dirname(dirname(__DIR__)));
......@@ -9,7 +9,8 @@ defined('FRONTEND_ENTRY_FILE') or define('FRONTEND_ENTRY_FILE', YII_APP_BASE_PAT
require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
require(YII_APP_BASE_PATH . '/common/config/aliases.php');
require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
require_once(YII_APP_BASE_PATH . '/frontend/config/bootstrap.php');
// set correct script paths
......@@ -18,4 +19,4 @@ $_SERVER['SCRIPT_FILENAME'] = FRONTEND_ENTRY_FILE;
$_SERVER['SCRIPT_NAME'] = FRONTEND_ENTRY_URL;
$_SERVER['SERVER_NAME'] = 'localhost';
Yii::setAlias('@tests', dirname(dirname(__DIR__)));
\ No newline at end of file
Yii::setAlias('@tests', dirname(dirname(__DIR__)));
Guia Definitivo para Yii 2.0
============================
Esse tutorial está disponível sob os [termos da documentação do Yii](http://www.yiiframework.com/doc/terms/).
......@@ -37,11 +38,11 @@ Estrutura de uma Aplicação
* [Controllers (Controladores)](structure-controllers.md)
* [Models (Modelos)](structure-models.md)
* [Views (Visões)](structure-views.md)
* **TBD** [Filtros](structure-filters.md)
* **TBD** [Widgets](structure-widgets.md)
* **TBD** [Módulos](structure-modules.md)
* [Assets](structure-assets.md)
* **TBD** [Extensões](structure-extensions.md)
* [Módulos](structure-modules.md)
* [Filtros](structure-filters.md)
* [Widgets](structure-widgets.md)
* [Asset Bundles](structure-assets.md)
* [Extensões](structure-extensions.md)
Tratamento de Requisições
......@@ -51,14 +52,14 @@ Tratamento de Requisições
* **TBD** [Rotas](runtime-routing.md)
* **TBD** [Requisições](runtime-requests.md)
* **TBD** [Respostas](runtime-responses.md)
* **TBD** [Seções e Cookies](runtime-sessions-cookies.md)
* **TBD** [Sessões e Cookies](runtime-sessions-cookies.md)
* [Análise e Geração de URLs](runtime-url-handling.md)
* [Tratamento de Erros](runtime-handling-errors.md)
* [Gerenciamento de Logs](runtime-logging.md)
Conceitos Chaves
----------------
Conceitos Chave
---------------
* [Componentes](concept-components.md)
* [Propriedades](concept-properties.md)
......@@ -68,7 +69,7 @@ Conceitos Chaves
* [Aliases](concept-aliases.md)
* [Autoloading de Classes](concept-autoloading.md)
* [Service Locator](concept-service-locator.md)
* [Injeção de Dependência](concept-di-container.md)
* [Container de Injeção de Dependência](concept-di-container.md)
Trabalhando com Banco de Dados
......@@ -89,7 +90,7 @@ Coletando Dados de Usuários
* [Criando um Formulário](input-forms.md)
* [Validação de Dados](input-validation.md)
* **TBD** [Uploading de Arquivos](input-file-upload.md)
* **TBD** [Upload de Arquivos](input-file-upload.md)
* **TBD** [Coletando Dados de Múltiplos Modelos](input-multiple-models.md)
......@@ -101,6 +102,7 @@ Exibindo Dados
* **TBD** [Ordenação](output-sorting.md)
* [Data Providers (Provedores de Dados)](output-data-providers.md)
* [Widgets de Dados](output-data-widgets.md)
* [Trabalhando com Client Scripts](output-client-scripts.md)
* [Temas](output-theming.md)
......@@ -109,7 +111,7 @@ Segurança
* [Autenticação](security-authentication.md)
* [Autorização](security-authorization.md)
* [Trabalhando Com Senhas](security-passwords.md)
* [Trabalhando com Senhas](security-passwords.md)
* **TBD** [Auth Clients](security-auth-clients.md)
* **TBD** [Melhores Práticas](security-best-practices.md)
......@@ -125,7 +127,7 @@ Cache
Web Services com RESTful
--------------------
------------------------
* [Visão Inicial](rest-quick-start.md)
* [Recursos](rest-resources.md)
......@@ -150,9 +152,10 @@ Testes
------
* [Visão Geral](test-overview.md)
* **TBD** [Testes Unitários](test-unit.md)
* **TBD** [Testes Funcionais](test-functional.md)
* **TBD** [Testes de Aceitação](test-acceptance.md)
* [Configuração do ambiente de testes](test-endvironment-setup.md)
* [Testes Unitários](test-unit.md)
* [Testes Funcionais](test-functional.md)
* [Testes de Aceitação](test-acceptance.md)
* [Fixtures](test-fixtures.md)
......@@ -172,13 +175,14 @@ Tópicos Especiais
* [Modelo de Aplicação Avançada](tutorial-advanced-app.md)
* [Construindo uma Aplicação a Partir do Zero](tutorial-start-from-scratch.md)
* [Comandos de Console](tutorial-console.md)
* [Ferramentas de Validação](tutorial-core-validators.md)
* [Comandos do Console](tutorial-console.md)
* [Ferramentas de Validação Embutidas](tutorial-core-validators.md)
* [Internacionalização](tutorial-i18n.md)
* [Enviando E-mails](tutorial-mailing.md)
* [Ajustes no Desempenho](tutorial-performance-tuning.md)
* **TBD** [Ambiente de Hospedagem Compartilhada](tutorial-shared-hosting.md)
* [Ferramentas de Templates](tutorial-template-engines.md)
* [Ferramentas de Template](tutorial-template-engines.md)
* [Utilização com Códigos de Terceiros](tutorial-yii-integration.md)
Widgets
......@@ -192,8 +196,8 @@ Widgets
* Menu
* LinkPager
* LinkSorter
* [Bootstrap Widgets](bootstrap-widgets.md)
* **TBD** [Jquery UI Widgets](jui-widgets.md)
* [Widgets do Bootstrap](bootstrap-widgets.md)
* [Widgets do Jquery UI](jui-widgets.md)
Helpers
......
Gerando Código com Gii
========================
Essa seção irá descrever como usar o [Gii](tool-gii.md) para automaticamente gerar código que implementa algumas funcionalidades comuns de sites. Usar o Gii para gerar código é simples, trata-se apenas de uma questão de entrar com as informações corretas de acordo com as instruções mostradas nas páginas do Gii.
Através desse tutorial, você irá aprender a:
* Habilitar o Gii em sua aplicação
* Usar o Gii para gerar uma classe Active Record
* Usar o Gii para gerar código que implementa as operações CRUD para uma tabela do BD
* Customizar o código gerado pelo Gii
Começando a usar o Gii <a name="starting-gii"></a>
------------
[Gii](tool-gii.md) é fornecido com o Yii como um [módulo](structure-modules.md). Você pode habilitar o Gii ao configurá-lo na propriedade [[yii\base\Application::modules|modules]] da aplicação. Dependendo de como você criou sua aplicação, você pode já encontrar o seguinte código no arquivo de configuração `config/web.php`:
```php
$config = [ ... ];
if (YII_ENV_DEV) {
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = 'yii\gii\Module';
}
```
A configuração acima declara que quando se está em [ambiente de desenvolvimento](concept-configurations.md#environment-constants), a aplicação deve incluir um módulo chamado `gii`, da classe [[yii\gii\Module]].
Se você checar o [script inicial](structure-entry-scripts.md) `web/index.php` da sua aplicação, você encontrará a seguinte linha, que essencialmente faz com que o `YII_ENV_DEV` seja verdadeiro.
```php
defined('YII_ENV') or define('YII_ENV', 'dev');
```
Graças a essa linha, sua aplicação está em modo de desenvolvimento e estará com o Gii habilitado, pela configuração acima. Agora você pode acessar o Gii pela URL:
```
http://hostname/index.php?r=gii
```
> Observação: Se você está acessando o Gii por um endereço IP que não seja o localhost, o acesso será negado por padrão.
> Para mudar isso, adicione a lista de endereços IP permitidos à configuração:
>
```php
'gii' => [
'class' => 'yii\gii\Module',
'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.178.20'] // ajuste de acordo com suas necessidades
],
```
![Gii](images/start-gii.png)
Gerando uma classe Active Record <a name="generating-ar"></a>
---------------------------------
Para usar o Gii para gerar uma classe Active Record, selecione o "Model Generator" clicando no link na página inicial do Gii. Preencha o formulário como indicado abaixo:
* Nome da tabela: `country`
* Classe do modelo: `Country`
![Gerador de Modelo](images/start-gii-model.png)
Em seguida, clique no botão "Preview". Você verá o `models/Country.php` listado como arquivo a ser criado. Você pode clicar no nome do arquivo para pré-visualizar seu conteúdo.
Ao usar o Gii, se você já havia criado o mesmo arquivo e pretende sobrescrevê-lo, clique no botão `diff` próximo ao nome do arquivo para ver as diferenças entre o código a ser gerado e a versão já existente.
![Pré-visualização do Gerador de Modelo](images/start-gii-model-preview.png)
Quando estiver sobrescrevendo um arquivo, marque a caixa próxima a "sobrescrever" e clique no botão "Gerar". Se estiver criando um arquivo novo, apenas clique em "Gerar".
Em seguida, você verá uma página de confirmação indicando que o código foi gerado com sucesso. Se você já tinha um arquivo, também verá uma mensagem indicando que ele foi sobrescrito com o novo código.
Gerando código CRUD <a name="generating-crud"></a>
--------------------
CRUD corresponde a Create, Read, Update, and Delete (criar, ler, atualizar e apagar), representando as quatro tarefas comuns feitas com os dados na maioria dos sites. Para criar funcionalidades CRUD usando o Gii, selecione "Gerador CRUD" clicando no link na página inicial do Gii. Seguindo o exemplo "country", preencha o formulário com as seguintes informações:
* Classe do Modelo: `app\models\Country`
* Classe da Busca: `app\models\CountrySearch`
* Classe do Controller: `app\controllers\CountryController`
![Gerador de CRUD](images/start-gii-crud.png)
Em seguida, clique no botão "Preview". Você verá uma lista de arquivos a serem gerados, como mostrado abaixo.
![Pré-visualização do Gerador de CRUD](images/start-gii-crud-preview.png)
Se você criou anteriormente os arquivos `controllers/CountryController.php` e
`views/country/index.php` (na seção de banco de dados deste guia), marque a caixa "overwrite" para substitui-los. (As versões anteriores não tinham suporte completo às operações CRUD.)
Checando os resultados <a name="trying-it-out"></a>
-------------
Para ver como ficou, use seu navegador para acessar a seguinte URL:
```
http://hostname/index.php?r=country/index
```
Você verá uma tabela mostrando os países do seu banco de dados. Você pode ordená-los ou filtrá-los inserindo condições nos cabeçalhos das colunas.
Para cada país exibido na tabela, você pode visualizar detalhes, editar ou excluir.
Você também pode clicar no botão “Create Country” no topo da tabela para ter acesso a um formulário de criação de um novo país.
![Tabela de Países](images/start-gii-country-grid.png)
![Editando um País](images/start-gii-country-update.png)
Essa é uma lista de arquivos gerados pelo Gii, caso você queira investigar como essas funcionalidades são implementadas ou adaptá-las:
* Controller: `controllers/CountryController.php`
* Modelo: `models/Country.php` e `models/CountrySearch.php`
* Views: `views/country/*.php`
> Info: o Gii é projetado para ser uma ferramenta altamente adaptável e extensível. Usando-o sabiamente, você irá acelerar o desenvolvimento da sua aplicação. Para mais detalhes, por favor siga para a seção [Gii](tool-gii.md).
Resumo <a name="summary"></a>
-------
Nessa seção, você aprendeu a usar o Gii para gerar código que implementa funcionalidades CRUD para o conteúdo guardado em uma tabela do banco de dados.
Dizendo "Hello World"
=====================
Esta seção descreve como criar uma nova página de "Hello World" em sua aplicação.
Para atingir este objetivo, você criará uma [ação](structure-controllers.md#creating-actions)
(action) e uma [visão](structure-views.md) (view):
* A aplicação enviará a requisição de página para a ação
* e a ação por sua vez renderizará a view que mostra as palavras "Hello World"
para o usuário final.
Através deste tutorial, você aprenderá as seguintes três coisas:
1. Como criar uma [ação](structure-controllers.md) para responder às requisições,
2. como criar uma [visão](structure-views.md) para compor o conteúdo da resposta, e
3. como uma aplicação envia as requisições para as [ações](structure-controllers.md#creating-actions).
Criando uma Ação <a name="creating-action"></a>
----------------
Para a tarefa "Hello", você criará uma [ação](structure-controllers.md#creating-actions)
`say` que lê um parâmetro `message` da requisição e exibe essa mensagem de volta
para o usuário. Se a requisição não fornecer um parâmetro `message`, a ação
exibirá a mensagem padrão "Hello".
> Info: [Ações](structure-controllers.md#creating-actions) são os objetos aos
quais os usuários podem se referir diretamente para execução. As ações são
agrupadas em [controladores](structure-controllers.md) (controllers). O resultado
da execução de uma ação é a resposta que o usuário final receberá.
As ações devem ser declaradas em [controladores](structure-controllers.md). Por
motivo de simplicidade, você pode declarar a ação `say` na classe já existente
`SiteController`. Este controlador está definido no arquivo `controllers/SiteController.php`.
Segue aqui o início da nova ação:
```php
<?php
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
// ...código existente...
public function actionSay($message = 'Hello')
{
return $this->render('say', ['message' => $message]);
}
}
```
No código acima, a ação `say` está definida como um método chamado `actionSay`
na classe `SiteController`. O Yii usa o prefixo `action` para diferenciar métodos
de ações de métodos que não são de ações em uma classe de controlador. O nome
após o prefixo `action` é mapeado para o ID da ação.
Quando se trata de dar nome às suas ações, você deveria entender como o Yii
trata os IDs de ações. Os IDs das ações são sempre referenciados em minúsculo.
Se o ID de uma ação necessitar de múltiplas palavras, elas serão concatenadas
por hífens (por exemplo, `create-comment`). Os nomes de métodos de ações são mapeados
para os IDs das ações removendo-se os hífens dos IDs, colocando em maiúsculo a
primeira letra de cada palavra, e prefixando o resultado com `action`. Por exemplo,
o ID de ação `create-comment` corresponde ao método de ação `actionCreateComment`.
O método de ação no nosso exemplo recebe um parâmetro `$message`, cujo valor
padrão é "Hello" (exatamente da mesma forma que você define um valor padrão para
qualquer argumento de função ou método no PHP). Quando a aplicação recebe a
requisição e determina que a ação `say` é responsável por tratar a requisição,
a aplicação alimentará este parâmetro com o parâmetro de mesmo nome encontrado
na requisição. Em outras palavras, se a requisição inclui um parâmetro `message`
com o valor `"Goodbye"`, a variável `$message` na ação receberá esse valor.
Dentro do método da ação, [[yii\web\Controller::render()|render()]] é chamado
para renderizar um arquivo de [visão](structure-views.md) chamado `say`. O
parâmetro `message` também é passado para a visão de modo que ele possa ser usado
ali. O resultado da renderização é retornado pelo método da ação. Esse resultado
será recebido pela aplicação, e exibido para o usuário final no navegador (como
parte de uma págian HTML completa).
Criando uma Visão <a name="creating-view"></a>
-----------------
[Visões](structure-views.md) são scripts que você escreve para gerar o conteúdo
de uma resposta. Para a tarefa "Hello", você criará uma visão `say` que imprime o
parâmetro `message` recebido do método da ação, e passado pela ação para a visão:
```php
<?php
use yii\helpers\Html;
?>
<?= Html::encode($message) ?>
```
A visão `say` deve ser salva no arquivo `views/site/say.php`. Quando o método
[[yii\web\Controller::render()|render()]] é chamado em uma ação, ele procurará
um arquivo PHP chamado de `views/IDdoController/NomeDaView.php`.
Perceba que no código acima o parâmetro `message` é [[yii\helpers\Html::encode()|codificado como HTML]]
antes de ser impresso. Isso é necessário, já que o parâmetro vem de um usuário final,
tornando-o vulnerável a [ataques de cross-site scripting (XSS)](http://en.wikipedia.org/wiki/Cross-site_scripting)
onde coloca-se código JavaScript malicioso no parâmetro.
Naturalmente, você pode colocar mais conteúdo na visão `say`. O conteúdo pode consistir
de tags HTML, texto puro, ou até mesmo instruções de PHP. De fato a visão `say` é
apenas um script PHP que é executado pelo método [[yii\web\Controller::render()|render()]].
O conteúdo impresso pelo script da visão será retornado à aplicação como o resultado
da resposta. A aplicação, por sua vez, retornará este resultado para o usuário final.
Testando <a name="trying-it-out"></a>
--------
Após criar a ação e a visão, você pode acessar a nova página através da seguinte URL:
```
http://hostname/index.php?r=site/say&message=Hello+World
```
![Hello World](images/start-hello-world.png)
Esta URL resultará em uma página exibindo "Hello World". Esta página compartilha
o mesmo cabeçalho e rodapé das outras páginas da aplicação.
Se você omitir o parâmetro `message` na URL, você veria a página exibindo somente
"Hello". Isso é porque `message` é passado como um parâmetro para o método `actionSay()`,
e quando ele é omitido, o valor padrão `"Hello"` será usado ao invés dele.
> Info: A nova página compartilha o mesmo cabeçalho e rodapé de outras páginas
porque o método [[yii\web\Controller::render()|render()]] irá automaticamente
incluir o resultado da visão `say` em um [layout](structure-views.md#layouts)
que neste caso está localizado em `views/layouts/main.php`.
O parâmetro `r` na URL acima requer mais explicação. Ele significa [rota](runtime-routing.md),
um ID abrangente e único de uma aplicação que se refere a uma ação. O formato da rota
é `IDdoController/IDdaAction`. Quando a aplicação recebe uma requisição, ela
verificará este parâmetro, usando a parte `IDdoController` para determinar qual
classe de controlador deve ser instanciada para tratar a requisição. Então o
controlador usará a parte `IDdaAction` para determinar qual ação deverá ser
instanciada para fazer o trabalho. No caso deste exemplo, a rota `site/say` será
resolvida como a classe de controlador `SiteController` e a ação `say`. Como
resultado, o método `SiteController::actionSay()` será chamado para tratar a requisição.
> Info: Assim como as ações, os controladores também possuem IDs que os identificam
de maneira única em uma aplicação. Os IDs de controladores seguem as mesmas regras
de nomenclatura que os IDs de ações. Os nomes das classes de controlllers
derivam dos IDs de controladores removendo-se os hífens dos IDs, convertendo a
primeira letra de cada palavra em maiúscula, e adicionando o sufixo `Controller`.
Por exemplo, o ID de controlador `post-comment` corresponde ao nome de classe
de controlador `PostCommentController`.
Resumo <a name="summary"></a>
------
Nesta seção, você tocou as partes do controlador (controller) e da visão (view)
do padrão de projeto MVC. Você criou uma ação (action) como parte de um controlador
para tratar uma requisição específica. E você também criou uma visão para compor
o conteúdo da resposta. Neste exemplo simples acima, nenhum modelo (model) foi
utilizado, já que os único dado sendo exibido foi o parâmetro `message`.
Você também aprendeu sobre as rotas no Yii, que agem como a ponte entre as
requisições do usuário e as ações do controlador.
Na próxima seção, você aprenderá como criar um modelo e adicionar uma nova
página contendo um formulário HTML.
Кэширование
=======
==========
Кэширование — это простой и эффективный способ повысить производительность веб-приложения. Сохраняя относительно
статичные данные в кэше и извлекая их из кэша, когда потребуется, мы экономим время, затрачиваемое на генерацию
данных с нуля каждый раз.
Кэширование может использоваться на различных уровнях веб-приложения. На стороне сервера, на более низшем уровне мы
используем кэширование для хранения основных данных, таких как список последних статьей запрашиваемых из базы данных;
и на более высоком уровне, кэш может использоваться для хранения фрагментов или целых веб-страниц, например как результат
рендеринга последних статьей. На стороне клиента может использоваться HTTP-кэширование, чтобы сохранить содержимое
недавно посещенных страниц в кэше браузера.
Кэширование может использоваться на различных уровнях и в различных местах веб-приложения. На стороне сервера, на более
низком уровне мы используем кэширование для хранения основных данных, таких как список последних полученных из базы
данных статьей. На более высоком уровне кэш может использоваться для хранения фрагментов или целых веб-страниц. Таких,
например, как результат рендеринга последних статьей. На стороне клиента для сохранения содержимого недавно посещенных
страниц в кэше браузера может использоваться HTTP-кэширование.
Yii поддерживает все эти механизмы кэширования:
......
Кэширование страниц
============
=================
Кэширование страниц — это кэширование всего содержимого страницы на стороне сервера. Позже когда эта страница
Кэширование страниц — это кэширование всего содержимого страницы на стороне сервера. Позже, когда эта страница
будет снова запрошена, сервер вернет её из кэша вместо того что бы генерировать её заново.
Кэширование страниц осуществляется при помощи [[yii\filters\PageCache]] и [фильтра действия](structure-filters.md).
Это может быть использовано в классе контроллера как показано ниже:
Кэширование страниц осуществляется при помощи [фильтра действия](structure-filters.md) [[yii\filters\PageCache]] и
может быть использовано в классе контроллера следующим образом:
```php
public function behaviors()
......@@ -27,14 +27,14 @@ public function behaviors()
}
```
Приведенный выше код устанавливает, что кэширования страницы должно использоваться только для `index` действия; контент
этой страницы должен быть закэширован не более чем на 60 секунд и должен будет измениться на текущий язык приложения;
и эта кэшированная страница должна быть признана просроченной, если общее количество постов было изменено.
Приведённый код задействует кэширование только для действия `index`. Содержимое страницы кешируется максимум на 60 секунд
и варьируется в зависимости от текущего языка приложения. Кэшированная страница должна быть признана просроченной, если
общее количество постов изменилось.
Как вы можете видеть, кэширование страниц очень похоже на [кэширования фрагмента](caching-fragment.md). Оба этих варианта
поддерживают параметры: `duration` (продолжительность), `dependencies` (зависимости), `variations` (вариации), и `enabled`
(включения). Их главное отличие заключается в том что кэширования страницы реализована как
[фильтр действия](structure-filters.md) а кэширования фрагмента как [виджет](structure-widgets.md).
Кэширование страниц очень похоже на [кэширования фрагментов](caching-fragment.md). В обоих случаях поддерживаются параметры
`duration` (продолжительность), `dependencies` (зависимости), `variations` (вариации), и `enabled` (включен). Главное
отличие заключается в том, что кэширование страницы реализовано в виде [фильтра действия](structure-filters.md),
а кэширование фрагмента в виде [виджета](structure-widgets.md).
Вы можете использовать [кэширования фрагмента](caching-fragment.md), a также
[динамический контент](caching-fragment.md#dynamic-content) вместе с кэшированием страницы.
Вы можете использовать вместе [кэширование фрагмента](caching-fragment.md),
[динамическое содержимое](caching-fragment.md#dynamic-content) и кэширование страницы.
Компоненты
==========
=========
Компоненты - это главные строительные блоки приложений основанных на Yii. Компоненты наследуются от класса [[yii\base\Component]] или его наследников. Три главные возможности, которые компоненты предоставляют для других классов:
Компоненты — это главные строительные блоки приложений основанных на Yii. Компоненты наследуются от класса
[[yii\base\Component]] или его наследников. Три главные возможности, которые компоненты предоставляют для других классов:
* [Свойства](concept-properties.md)
* [События](concept-events.md)
* [Поведения](concept-behaviors.md),
* [Свойства](concept-properties.md).
* [События](concept-events.md).
* [Поведения](concept-behaviors.md).
Разделение и комбинирование этих возможностей делает классы Yii более простыми в настройке и использовании. *Например, пользовательские компоненты, включающие в себя [[yii\jui\DatePicker|виджет выбора даты]], могут быть использованы в [представлении](structure-view.md) для генерации интерактивных элементов выбора даты:*
Как по отдельности, так и вместе, эти возможности делают классы Yii более простыми в настройке и использовании.
Например, пользовательские компоненты, включающие в себя [[yii\jui\DatePicker|виджет выбора даты]], могут быть
использованы в [представлении](structure-view.md) для генерации интерактивных элементов выбора даты:
```php
use yii\jui\DatePicker;
......@@ -23,13 +26,20 @@ echo DatePicker::widget([
Свойства виджета легко доступны для записи потому, что его класс унаследован от класса [[yii\base\Component]].
Компоненты - очень мощный инструмент. Но в то же время они немного тяжелее обычных объектов, потому что на поддержку [событий](concept-events.md) и [поведений](concept-behaviors.md) тратится дополнительные память и процессорное время. Если ваши компоненты не нуждаются в этих двух возможностях, вам стоит унаследовать их от [[yii\base\Object]], а не от [[yii\base\Component]]. Поступив так, вы сделаете ваши компоненты такими же эффективными, как и обычные PHP объекты, но с поддержкой [свойств](concept-properties.md).
Компоненты — очень мощный инструмент. Но в то же время они немного тяжелее обычных объектов, потому что на поддержку
[событий](concept-events.md) и [поведений](concept-behaviors.md) тратится дополнительные память и процессорное время.
Если ваши компоненты не нуждаются в этих двух возможностях, вам стоит унаследовать их от [[yii\base\Object]],
а не от [[yii\base\Component]]. Поступив так, вы сделаете ваши компоненты такими же эффективными, как и обычные PHP объекты,
но с поддержкой [свойств](concept-properties.md).
При наследовании ваших классов от [[yii\base\Component]] или [[yii\base\Object]], рекомендуется следовать некоторым соглашениям:
При наследовании ваших классов от [[yii\base\Component]] или [[yii\base\Object]], рекомендуется следовать некоторым
соглашениям:
- Если вы переопределяете конструктор, то добавьте *последним* аргументом параметр `$config` и затем передайте его в конструктор предка.
- Если вы переопределяете конструктор, то добавьте *последним* аргументом параметр `$config` и затем передайте его
в конструктор предка.
- Всегда вызывайте конструктор предка *в конце* вашего переопределенного конструктора.
- Если вы переопределяете метод [[yii\base\Object::init()]], убедитесь, что вы вызываете родительскую реализацию этого метода *в начале* вашего метода `init()`.
- Если вы переопределяете метод [[yii\base\Object::init()]], убедитесь, что вы вызываете родительскую реализацию этого
метода *в начале* вашего метода `init()`.
Пример:
......@@ -45,7 +55,7 @@ class MyClass extends Object
public function __construct($param1, $param2, $config = [])
{
// ... инициализация происходит перед тем, как будет применена конфигурация.
// ... инициализация происходит перед тем, как будет применена конфигурация.
parent::__construct($config);
}
......@@ -71,21 +81,17 @@ $component = \Yii::createObject([
], [1, 2]);
```
> Информация: Способ инициализации через вызов [[Yii::createObject()]] выглядит более сложным. Но в то же время он более мощный из-за того, что он реализован на самом верху [контейнера внедрения зависимостей](concept-di-container.md).
> Информация: Способ инициализации через вызов [[Yii::createObject()]] выглядит более сложным. Но в то же время он более
мощный из-за того, что он реализован на самом верху [контейнера внедрения зависимостей](concept-di-container.md).
Жизненyый цикл объектов класса [[yii\base\Object]] содержит следующие этапы:
Жизненый цикл объектов класса [[yii\base\Object]] содержит следующие этапы:
1. Предварительная инициализация в конструкторе. Здесь вы можете установить значения свойств по умолчанию.
2. Конфигурация объекта с помощью `$config`. Во время конфигурации могут быть перезаписаны значения свойств по умолчанию, установленные в конструкторе.
3. Конфигурация после инициализации в методе [[yii\base\Object::init()|init()]]. Вы можете переопределить этот метод, для проверки готовности объекта и нормализации свойств.
2. Конфигурация объекта с помощью `$config`. Во время конфигурации могут быть перезаписаны значения свойств по умолчанию,
установленные в конструкторе.
3. Конфигурация после инициализации в методе [[yii\base\Object::init()|init()]]. Вы можете переопределить этот метод,
для проверки готовности объекта и нормализации свойств.
4. Вызов методов объекта.
*Первые три шага всегда выполняются из конструктора объекта.* Это значит, что если вы получите экземпляр объекта, он уже будет проинициализирован и готов к работе.
Первые три шага всегда выполняются из конструктора объекта. Это значит, что если вы получите экземпляр объекта, он уже
будет проинициализирован и готов к работе.
Service Locator
===============
=============
Service Locator является объектом, который знает, как обеспечить всевозможные службы (или компоненты), которые могут понадобиться в приложении.
В пределах Service Locator'а, каждый компонент имеет только один экземпляр, который уникально определяется с помощью идентификатора (ID).
Уникальный идентификатор (ID) может быть использован для извлечения компонента из Service Locator'а.
Service Locator является объектом, предоставляющим всевозможные сервисы (или компоненты), которые могут понадобиться
приложению. В Service Locator, каждый компонент представлен единственным экземпляром, имеющим уникальный ID.
Уникальный идентификатор (ID) может быть использован для получения компонента из Service Locator.
В Yii Service Locator является экземпляром класса [[yii\di\ServiceLocator]] или его дочернего класса.
Наиболее часто используемый Service Locator в Yii - это объект *приложения*, который можно получить через
`\Yii::$app`. Обеспечиваемые им службы называют *компонентами приложения*, такие, как компоненты `запрос`, `ответ`, `UrlManager`.
Вы легко можете настроить эти компоненты или даже заменить их собственными реализациями,
благодаря функциональным службам, предоставляемым Service Locator'ом.
Наиболее часто используемый Service Locator в Yii — это объект *приложения*, который можно получить через `\Yii::$app`.
Предоставляемые им службы, такие, как компоненты `request`, `response`, `urlManager`, называют *компонентами приложения*.
Благодаря Service Locator вы легко можете настроить эти компоненты или даже заменить их собственными реализациями.
Помимо объекта приложения, объект каждого модуля так же является Service Locator'ом.
Помимо объекта приложения, объект каждого модуля также является Service Locator.
Для использования Service Locator'а первым шагом является регистрация компонентов.
Компонент может быть зарегистрирован с помощью [[yii\di\ServiceLocator::set()]].
Следующий код демонстрирует различные способы регистрации компонентов:
При использовании Service Locator первым шагом является регистрация компонентов. Компонент может быть зарегистрирован
с помощью метода [[yii\di\ServiceLocator::set()]]. Следующий код демонстрирует различные способы регистрации компонентов:
```php
use yii\di\ServiceLocator;
......@@ -24,10 +22,10 @@ use yii\caching\FileCache;
$locator = new ServiceLocator;
// Зарегистрирует "cache", используя имя класса, которое может быть использовано для создания компонента.
// регистрирует "cache", используя имя класса, которое может быть использовано для создания компонента.
$locator->set('cache', 'yii\caching\ApcCache');
// Зарегистрирует "db", используя конфигурационный массив, который может быть использован для создания компонента.
// регистрирует "db", используя конфигурационный массив, который может быть использован для создания компонента.
$locator->set('db', [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=demo',
......@@ -35,41 +33,36 @@ $locator->set('db', [
'password' => '',
]);
// Зарегистрирует "search", используя анонимную функцию, которая создаёт компонент
// регистрирует "search", используя анонимную функцию, которая создаёт компонент
$locator->set('search', function () {
return new app\components\SolrService;
});
// Зарегистрирует "pageCache", используя компонент
// регистрирует "pageCache", используя компонент
$locator->set('pageCache', new FileCache);
```
После того, как компонент зарегистрирован, вы можете получить к нему доступ, используя уникальный идентификатор (ID),
одним из двух следующих способов:
После того, как компонент зарегистрирован, вы можете обращаться к нему по его ID одним из двух следующих способов:
```php
$cache = $locator->get('cache');
// или альтернативный
// или
$cache = $locator->cache;
```
Как видно выше, [[yii\di\ServiceLocator]] позволяет обратиться к компоненту, как к свойству,
при помощи идентификатора (ID) компонента.
При обращении к компоненту впервые, [[yii\di\ServiceLocator]] будет использовать информацию о регистрации компонента,
что бы создать новый экземпляр компонента и вернёт его.
В дальнейшем при обращении к компоненту снова, Service Locator вернёт тот же экземпляр.
Как видно выше, [[yii\di\ServiceLocator]] позволяет обратиться к компоненту как к свойству используя его ID.
При первом обращении к компоненту, [[yii\di\ServiceLocator]] создаст новый экземпляр компонента на основе регистрационной
информации и вернёт его. При повторном обращении к компоненту Service Locator вернёт тот же экземпляр.
Что бы проверить, был ли идентификатор (ID) компонента уже зарегистрирован, можно использовать [[yii\di\ServiceLocator::has()]].
Если вы вызовете [[yii\di\ServiceLocator::get()]] с недопустимым идентификатором (ID), тогда будет выброшено исключение.
Чтобы проверить, был ли идентификатор компонента уже зарегистрирован, можно использовать [[yii\di\ServiceLocator::has()]].
Если вы вызовете [[yii\di\ServiceLocator::get()]] с несуществующим ID, будет выброшено исключение.
Поскольку Service Locator`ы зачастую создаются с [конфигурациями](concept-configurations.md),
записываемое свойство с именем [[yii\di\ServiceLocator::setComponents()|components]] предоставляется так,
что Вы можете его настроить и зарегистрировать несколько компонентов одновременно.
Следующий код демонстрирует конфигурационный массив,
который может использоваться для настройки приложения и регистрации компонентов "db", "cache" и "search" :
Поскольку Service Locator часто используется с [конфигурациями](concept-configurations.md), в нём имеется доступное
для записи свойство [[yii\di\ServiceLocator::setComponents()|components]]. Это позволяет настроить и зарегистрировать
сразу несколько компонентов. Следующий код демонстрирует конфигурационный массив, который может использоваться одновременно
для настройки приложения и регистрации компонентов "db", "cache" и "search":
```php
return [
......
......@@ -17,6 +17,8 @@ Yii – это универсальный фреймворк и может бы
Сравнение Yii с другими фреймворками
------------------------------------
Если вы уже знакомы с другими фреймворками, вам наверняка будет интересно сравнить их с Yii.
- Как и многие другие PHP фреймворки, для организации кода Yii использует модель MVC (Model-View-Controller).
- Yii придерживается философии простого и элегантного кода не пытаясь усложнять дизайн только ради следования каким-либо
шаблонам проектирования.
......@@ -27,7 +29,7 @@ Yii – это универсальный фреймворк и может бы
- Одна из главных целей Yii – производительность.
Yii — не проект одного человека. Он поддерживается и развивается [сильной командой][] и большим сообществом разработчиков,
которые ей помогают. Разработчики фреймворка следят за тенденциями веб разработки и развитием других проектов. Наиболее
которые ей помогают. Авторы фреймворка следят за тенденциями веб разработки и развитием других проектов. Наиболее
подходящие возможности и лучшие практики регулярно внедряются в фреймворк в виде простых и элегантных интерфейсов.
[сильной командой]: http://www.yiiframework.com/about/
......@@ -37,7 +39,7 @@ Yii — не проект одного человека. Он поддержив
На данный момент существует две основные ветки Yii: 1.1 и 2.0. Ветка 1.1 является предыдущим поколением и находится
в состоянии поддержки. Версия 2.0 – это полностью переписанный Yii, использующий последние технологии и протоколы, такие
как Composer, PSR, пространства имен, типажи (traits) и многое другое. 2.0 — последнее поколение фреймворка. На этой версии
как Composer, PSR, пространства имен, трейты и многое другое. 2.0 — текущее поколение фреймворка. На этой версии
будут сосредоточены основные усилия несколько следующих лет. Данное руководство именно о версии 2.0.
......@@ -47,6 +49,6 @@ Yii — не проект одного человека. Он поддержив
Yii 2.0 требует PHP 5.4.0 и выше. Чтобы узнать требования для отдельных возможностей вы можете запустить скрипт проверки
требований, который поставляется с каждым релизом фреймворка.
Для разработки на Yii потребуется общее понимание ООП так как фреймворк полностью следует этой парадигме. Также следует
Для разработки на Yii потребуется общее понимание ООП так как фреймворк полностью следует этой парадигме. Также стоит
изучить такие современные возможности PHP как [пространства имён](http://www.php.net/manual/ru/language.namespaces.php)
и [типажи](http://www.php.net/manual/ru/language.oop5.traits.php).
и [трейты](http://www.php.net/manual/ru/language.oop5.traits.php).
......@@ -28,15 +28,16 @@ Yii поддерживает все выше перечисленные мето
1. У компонента приложения `user` установите свойство [[yii\web\User::enableSession|enableSession]] равным false.
2. Укажите, какие методы аутентификации вы планируете использовать, настроив поведение `authenticator`
в ваших классах REST-контроллеров.
3. Реализуйте метод [[yii\web\IdentityInterface::findIdentityByAccessToken()]] *в вашем [[yii\web\User::identityClass|классе UserIdentity]]*.
3. Реализуйте метод [[yii\web\IdentityInterface::findIdentityByAccessToken()]] в вашем [[yii\web\User::identityClass|классе UserIdentity]].
Шаг 1 не обязателен, но рекомендуется его все-таки выполнить, так как RESTful API не должны сохранять информацию о состоянии клиента. Когда свойство [[yii\web\User::enableSession|enableSession]]
установлено в false, состояние аутентификации пользователя НЕ БУДЕТ постоянно
сохраняться между запросами с использованием сессий. Вместо этого аутентификация будет выполняться для каждого запроса, что достигается шагами 2 и 3.
Шаг 1 не обязателен, но рекомендуется его всё-таки выполнить, так как RESTful API не должен сохранять информацию о
состоянии клиента. Когда свойство [[yii\web\User::enableSession|enableSession]] установлено в false, состояние
аутентификации пользователя НЕ БУДЕТ сохраняться между запросами с использованием сессий. Вместо этого аутентификация
будет выполняться для каждого запроса, что достигается шагами 2 и 3.
> Подсказка: если вы разрабатываете RESTful API в пределах приложения, вы можете настроить свойство
[[yii\web\User::enableSession|enableSession]] компонента приложения `user` в конфигурации приложения. Если вы разрабатываете
RESTful API как модуль, можете добавить следующую строчку в метод `init()` модуля:
[[yii\web\User::enableSession|enableSession]] компонента приложения `user` в конфигурации приложения. Если вы
разрабатываете RESTful API как модуль, можете добавить следующую строчку в метод `init()` модуля:
> ```php
public function init()
{
......@@ -60,7 +61,7 @@ public function behaviors()
}
```
Если вы хотите включить поддержку всех трех описанных выше методов аутентификации, можете использовать `CompositeAuth`:
Если вы хотите включить поддержку всех трёх описанных выше методов аутентификации, можете использовать `CompositeAuth`:
```php
use yii\filters\auth\CompositeAuth;
......@@ -107,7 +108,7 @@ class User extends ActiveRecord implements IdentityInterface
будет пытаться аутентифицировать пользователя в своем методе `beforeAction()`.
Если аутентификация прошла успешно, контроллер выполнит другие проверки (ограничение частоты запросов, авторизация)
и затем выполнит действие. *Информация о подлинности аутентифицированного пользователя может быть получена из объекта `Yii::$app->user->identity`*.
и затем выполнит действие. Информация об аутентифицированном пользователе может быть получена из объекта `Yii::$app->user->identity`.
Если аутентификация прошла неудачно, будет возвращен ответ с HTTP-кодом состояния 401 вместе с другими необходимыми заголовками
(такими, как заголовок `WWW-Authenticate` для HTTP Basic Auth).
......@@ -115,9 +116,9 @@ class User extends ActiveRecord implements IdentityInterface
## Авторизация <a name="authorization"></a>
После аутентификации пользователя вы, вероятно, захотите проверить, есть ли у него или у нее разрешение на выполнение запрошенного
После аутентификации пользователя вы, вероятно, захотите проверить, есть ли у него или у неё разрешение на выполнение запрошенного
действия с запрошенным ресурсом. Этот процесс называется *авторизацией* и подробно описан
в разделе [Авторизация](security-authorization.md).
в разделе «[Авторизация](security-authorization.md)».
Если ваши контроллеры унаследованы от [[yii\rest\ActiveController]], вы можете переопределить
метод [[yii\rest\Controller::checkAccess()|checkAccess()]] для выполнения авторизации. Этот метод будет вызываться
......
......@@ -12,7 +12,7 @@
от [[yii\rest\ActiveController]], что позволит вам создать полноценные RESTful API, написав минимум кода.
[[yii\rest\Controller]] и [[yii\rest\ActiveController]] имеют следующие возможности, некоторые из которых
будут подробно описаны в следующих нескольких разделах:
будут подробно описаны в следующих разделах:
* Проверка HTTP-метода;
* [Согласование содержимого и форматирование данных](rest-response-formatting.md);
......@@ -21,7 +21,7 @@
[[yii\rest\ActiveController]], кроме того, предоставляет следующие возможности:
* Набор наиболее употребительных действий: `index`, `view`, `create`, `update`, `delete`, `options`;
* Набор наиболее часто используемых действий: `index`, `view`, `create`, `update`, `delete` и `options`;
* Авторизация пользователя для запрашиваемых действия и ресурса.
......@@ -33,7 +33,7 @@
Создание нового действия похоже на создание действия для Web-приложения. Единственное отличие в том,
что в RESTful-действиях вместо рендера результата в представлении с помощью вызова метода `render()`
вы просто возвращает данные. Выполнение преобразования исходных данных в запрошенный формат ложится на
вы просто возвращаете данные. Выполнение преобразования исходных данных в запрошенный формат ложится на
[[yii\rest\Controller::serializer|сериализатор]] и [[yii\web\Response|объект ответа]].
Например:
......@@ -59,8 +59,9 @@ public function actionView($id)
в разделе [Ограничение частоты запросов](rest-rate-limiting.md).
Эти именованные фильтры объявлены в методе [[yii\rest\Controller::behaviors()|behaviors()]].
Вы можете переопределить этот метод для настройки отдельных фильтров, отключения каких-то из них или для добавления ваших собственных фильтров.
Например, если вы хотите использовать только базовую HTTP-аутентификацию, вы можете написать такой код:
Вы можете переопределить этот метод для настройки отдельных фильтров, отключения каких-либо из них или для добавления
ваших собственных фильтров. Например, если вы хотите использовать только базовую HTTP-аутентификацию, вы можете
написать такой код:
```php
use yii\filters\auth\HttpBasicAuth;
......@@ -123,8 +124,8 @@ public function prepareDataProvider()
### Выполнение контроля доступа <a name="performing-access-check"></a>
При предоставлении ресурсов через RESTful API часто бывает нужно проверять, имеет ли текущий пользователь разрешение
на доступ к запрошенному ресурсу (или ресурсам) и манипуляцию им (ими). Для [[yii\rest\ActiveController]] эта задача может быть решена
переопределением метода [[yii\rest\ActiveController::checkAccess()|checkAccess()]] следующим образом:
на доступ к запрошенному ресурсу (или ресурсам) и манипуляцию им (или ими). Для [[yii\rest\ActiveController]] эта задача
может быть решена переопределением метода [[yii\rest\ActiveController::checkAccess()|checkAccess()]] следующим образом:
```php
/**
......@@ -134,7 +135,7 @@ public function prepareDataProvider()
* право выполнения указанного действия над указанной моделью данных.
* Если у пользователя нет доступа, следует выбросить исключение [[ForbiddenHttpException]].
*
* @param string $action ID действия, которое надо выполнить
* @param string $action ID действия, которое надо выполнить
* @param \yii\base\Model $model модель, к которой нужно получить доступ. Если null, это означает, что модель, к которой нужно получить доступ, отсутствует.
* @param array $params дополнительные параметры
* @throws ForbiddenHttpException если у пользователя нет доступа
......@@ -146,7 +147,7 @@ public function checkAccess($action, $model = null, $params = [])
}
```
Метод `checkAccess()` будет вызван действиями по умолчанию контроллера [[yii\rest\ActiveController]]. Если вы создаете
Метод `checkAccess()` будет вызван действиями по умолчанию контроллера [[yii\rest\ActiveController]]. Если вы создаёте
новые действия и хотите в них выполнять контроль доступа, вы должны вызвать этот метод явно в своих новых действиях.
> Подсказка: вы можете реализовать метод `checkAccess()` с помощью ["Контроля доступа на основе ролей" (RBAC)](security-authorization.md).
Обработка ошибок
================
> Раздел в разработке.
Обработка ошибок в Yii происходит несколько иначе, чем в обычном PHP. Во-первых, все нефатальные ошибки в Yii преобразуются в *исключения*:
```php
use yii\base\ErrorException;
use Yii;
try {
10/0;
} catch (ErrorException $e) {
Yii::warning("Попытка деления на ноль.");
}
// можно продолжать выполнение
```
Как это видно из примера, вы можете обрабатывать ошибки, используя конструкцию `try`-`catch`.
Во-вторых, даже фатальные ошибки в Yii показываются в красивом виде. Это значит, что при отладке кода, вы можете отслеживать причины фатальных
ошибок. Это позволяет быстрее находить причины возникших проблем.
Рендеринг ошибок в произвольном действии контроллера
----------------------------------------------------
Обычная страница вывода ошибок Yii не только хороша в разработке, но и приемлема для уже развернутых проектов, если `YII_DEBUG` выключена в начальном загрузочном скрипте `index.php`. Но иногда хочется изменить внешний вид страницы с ошибками, чтобы лучше приспособить ее под свой проект.
Самый легкий способ создать свою страницу для отображения ошибок - использовать свое действие (action) для рендеринга сообщений об ошибке.
Сначала нужно дать приложению понять, что вы хотите использовать свое действие для обработки ошибок. Для этого нужно сконфигурировать компонент `errorHandler` в конфигурационном файле приложения:
```php
// ...
'components' => [
// ...
'errorHandler' => [
'errorAction' => 'site/error',
],
]
```
С вышеуказанной конфигурацией, если происходит ошибка, Yii запустит действие `error` контроллера `site`. Это действие запрашивает у компонента `errorHandler`, было ли выброшено исключение, и, если да, отображает соответствующий вид, передавая ему объект исключения в качестве параметра.
```php
public function actionError()
{
$exception = \Yii::$app->errorHandler->exception;
if ($exception !== null) {
return $this->render('error', ['exception' => $exception]);
}
}
```
После создания `action` нужно создать соответствующий вид, который и будет отображать информацию об исключении. Объект исключения, передаваемый в вид, имеет
следующие свойства:
- `statusCode`: HTTP статус (например, 403, 500). Доступен только для [[yii\web\HttpException|HTTP exceptions]].
- `code`: код исключения.
- `message`: сообщение об ошибке.
- `file`: имя файла PHP скрипта, в котором произошла ошибка.
- `line`: номер строки в коде, где произошла ошибка.
- `trace`: стэк вызовов, приведших к ошибке.
Рендеринг ошибок без создания отдельного действия
-------------------------------------------------
Вместо создания отдельного действия внутри контроллера Site, вы можете просто указать Yii какой класс использовать для обработки ошибок:
```php
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
];
}
```
После задания вышеуказанной связки ошибки с классом обработчиком, создайте вид `views/site/error.php`, который будет использоваться автоматически.
Виду передаются три параметра:
- `$name`: название ошибки
- `$message`: сообщение об ошибке
- `$exception`: обрабатываемое исключение
Объект `$exception` имеет те же свойства, которые были указаны ранее.
......@@ -139,9 +139,9 @@ RESTful Web 服务
-----
* **编撰中** [概述](test-overview.md)
* **待定中** [单元测试](test-unit.md)
* **待定中** [功能测试](test-functional.md)
* **待定中** [验收测试](test-acceptance.md)
* **编撰中** [单元测试](test-unit.md)
* **编撰中** [功能测试](test-functional.md)
* **编撰中** [验收测试](test-acceptance.md)
* **编撰中** [测试夹具](test-fixtures.md)
......
......@@ -67,15 +67,15 @@ if ($data === false) {
Yii 支持一系列缓存存储器,概况如下:
* [[yii\caching\ApcCache]]: 使用 PHP [APC](http://php.net/manual/en/book.apc.php) 扩展。这个选项可以认为是集中式应用程序环境中(例如:单一服务器,没有独立的负载均衡器等)最快的缓存方案。
* [[yii\caching\DbCache]]: 使用一个数据库的表存储缓存数据。要使用这个缓存,你必须创建一个与 [[yii\caching\DbCache::cacheTable]] 对应的表。
* [[yii\caching\ApcCache]]使用 PHP [APC](http://php.net/manual/en/book.apc.php) 扩展。这个选项可以认为是集中式应用程序环境中(例如:单一服务器,没有独立的负载均衡器等)最快的缓存方案。
* [[yii\caching\DbCache]]使用一个数据库的表存储缓存数据。要使用这个缓存,你必须创建一个与 [[yii\caching\DbCache::cacheTable]] 对应的表。
* [[yii\caching\DummyCache]]: 仅作为一个缓存占位符,不实现任何真正的缓存功能。这个组件的目的是为了简化那些需要查询缓存有效性的代码。例如,在开发中如果服务器没有实际的缓存支持,用它配置一个缓存组件。一个真正的缓存服务启用后,可以再切换为使用相应的缓存组件。两种条件下你都可以使用同样的代码 `Yii::$app->cache->get($key)` 尝试从缓存中取回数据而不用担心 `Yii::$app->cache` 可能是 `null`
* [[yii\caching\FileCache]]: 使用标准文件存储缓存数据。这个特别适用于缓存大块数据,例如一个整页的内容。
* [[yii\caching\MemCache]]: 使用 PHP [memcache](http://php.net/manual/en/book.memcache.php)[memcached](http://php.net/manual/en/book.memcached.php) 扩展。这个选项被看作分布式应用环境中(例如:多台服务器,有负载均衡等)最快的缓存方案。
* [[yii\redis\Cache]]: 实现了一个基于 [Redis](http://redis.io/) 键值对存储器的缓存组件(需要 redis 2.6.12 及以上版本的支持 )。
* [[yii\caching\WinCache]]: 使用 PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)[另可参考](http://php.net/manual/en/book.wincache.php))扩展.
* [[yii\caching\XCache]]: 使用 PHP [XCache](http://xcache.lighttpd.net/)扩展。
* [[yii\caching\ZendDataCache]]: 使用 [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) 作为底层缓存媒介。
* [[yii\caching\FileCache]]使用标准文件存储缓存数据。这个特别适用于缓存大块数据,例如一个整页的内容。
* [[yii\caching\MemCache]]使用 PHP [memcache](http://php.net/manual/en/book.memcache.php)[memcached](http://php.net/manual/en/book.memcached.php) 扩展。这个选项被看作分布式应用环境中(例如:多台服务器,有负载均衡等)最快的缓存方案。
* [[yii\redis\Cache]]实现了一个基于 [Redis](http://redis.io/) 键值对存储器的缓存组件(需要 redis 2.6.12 及以上版本的支持 )。
* [[yii\caching\WinCache]]使用 PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)[另可参考](http://php.net/manual/en/book.wincache.php))扩展.
* [[yii\caching\XCache]]使用 PHP [XCache](http://xcache.lighttpd.net/)扩展。
* [[yii\caching\ZendDataCache]]使用 [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) 作为底层缓存媒介。
> Tip: 你可以在同一个应用程序中使用不同的缓存存储器。一个常见的策略是使用基于内存的缓存存储器存储小而常用的数据(例如:统计数据),使用基于文件或数据库的缓存存储器存储大而不太常用的数据(例如:网页内容)。
......@@ -85,15 +85,15 @@ Yii 支持一系列缓存存储器,概况如下:
所有缓存组件都有同样的基类 [[yii\caching\Cache]] ,因此都支持如下 API:
* [[yii\caching\Cache::get()|get()]]: 通过一个指定的键(key)从缓存中取回一项数据。如果该项数据不存在于缓存中或者已经过期/失效,则返回值 false。
* [[yii\caching\Cache::set()|set()]]: 将一项数据指定一个键,存放到缓存中。
* [[yii\caching\Cache::add()|add()]]: 如果缓存中未找到该键,则将指定数据存放到缓存中。
* [[yii\caching\Cache::mget()|mget()]]: 通过指定的多个键从缓存中取回多项数据。
* [[yii\caching\Cache::mset()|mset()]]: 将多项数据存储到缓存中,每项数据对应一个键。
* [[yii\caching\Cache::madd()|madd()]]: 将多项数据存储到缓存中,每项数据对应一个键。如果某个键已经存在于缓存中,则该项数据会被跳过。
* [[yii\caching\Cache::exists()|exists()]]: 返回一个值,指明某个键是否存在于缓存中。
* [[yii\caching\Cache::delete()|delete()]]: 通过一个键,删除缓存中对应的值。
* [[yii\caching\Cache::flush()|flush()]]: 删除缓存中的所有数据。
* [[yii\caching\Cache::get()|get()]]通过一个指定的键(key)从缓存中取回一项数据。如果该项数据不存在于缓存中或者已经过期/失效,则返回值 false。
* [[yii\caching\Cache::set()|set()]]将一项数据指定一个键,存放到缓存中。
* [[yii\caching\Cache::add()|add()]]如果缓存中未找到该键,则将指定数据存放到缓存中。
* [[yii\caching\Cache::mget()|mget()]]通过指定的多个键从缓存中取回多项数据。
* [[yii\caching\Cache::mset()|mset()]]将多项数据存储到缓存中,每项数据对应一个键。
* [[yii\caching\Cache::madd()|madd()]]将多项数据存储到缓存中,每项数据对应一个键。如果某个键已经存在于缓存中,则该项数据会被跳过。
* [[yii\caching\Cache::exists()|exists()]]返回一个值,指明某个键是否存在于缓存中。
* [[yii\caching\Cache::delete()|delete()]]通过一个键,删除缓存中对应的值。
* [[yii\caching\Cache::flush()|flush()]]删除缓存中的所有数据。
有些缓存存储器如 MemCache,APC 支持以批量模式取回缓存值,这样可以节省取回缓存数据的开支。 [[yii\caching\Cache::mget()|mget()]] 和 [[yii\caching\Cache::madd()|madd()]] API提供对该特性的支持。如果底层缓存存储器不支持该特性,Yii 也会模拟实现。
......@@ -177,12 +177,11 @@ $data = $cache->get($key);
下面是可用的缓存依赖的概况:
- [[yii\caching\ChainedDependency]]: 如果依赖链上任何一个依赖产生变化,则依赖改变。
- [[yii\caching\DbDependency]]: 如果指定 SQL 语句的查询结果发生了变化,则依赖改变。
- [[yii\caching\ExpressionDependency]]: 如果指定的 PHP 表达式执行结果发生变化,则依赖改变。
- [[yii\caching\FileDependency]]: 如果文件的最后修改时间发生变化,则依赖改变。
- [[yii\caching\TagDependency]]: 为一项缓存数据添加一个或多个标签。你可以通过调用 [[yii\caching\TagDependency::invalidate()]]
一次性将具有指定标签的缓存数据全部置为失效状态。
- [[yii\caching\ChainedDependency]]:如果依赖链上任何一个依赖产生变化,则依赖改变。
- [[yii\caching\DbDependency]]:如果指定 SQL 语句的查询结果发生了变化,则依赖改变。
- [[yii\caching\ExpressionDependency]]:如果指定的 PHP 表达式执行结果发生变化,则依赖改变。
- [[yii\caching\FileDependency]]:如果文件的最后修改时间发生变化,则依赖改变。
- [[yii\caching\GroupDependency]]:将一项缓存数据标记到一个组名,你可以通过调用 [[yii\caching\GroupDependency::invalidate()]] 一次性将相同组名的缓存全部置为失效状态。
## 查询缓存 <a name="query-caching"></a>
......
......@@ -19,7 +19,7 @@ Yii::setAlias('@bar', 'http://www.example.com');
> 注意:别名所指向的文件路径或 URL 不一定是真实存在的文件或资源。
可以通过在一个别名后面加斜杠 `/` 和一至多个路径分段生成新别名(无需调用 [[Yii::setAlias()]])。我们把通过 [[Yii::setAlias()]] 定义的别名称为**根别名**,而用他们衍生出去的别名成为**衍生别名**。例如,`@foo` 就是别名,而 `@foo/bar/file.php` 是一个衍生别名。
可以通过在一个别名后面加斜杠 `/` 和一至多个路径分段生成新别名(无需调用 [[Yii::setAlias()]])。我们把通过 [[Yii::setAlias()]] 定义的别名称为**根别名**,而用他们衍生出去的别名成为**衍生别名**。例如,`@foo` 就是别名,而 `@foo/bar/file.php` 是一个衍生别名。
你还可以用别名去定义新别名(根别名与衍生别名均可):
......@@ -86,7 +86,7 @@ $cache = new FileCache([
预定义的别名 <a name="predefined-aliases"></a>
------------------
Yii 预定义了一系列别名来简化常用路径和 URL的使用:
Yii 预定义了一系列别名来简化常用路径和 URL 的使用:
- `@yii` - `BaseYii.php` 文件所在的目录(也被称为框架安装目录)
- `@app` - 当前运行的应用 [[yii\base\Application::basePath|根路径(base path)]]
......
错误处理
==============
处理一个 RESTful API 请求时, 如果有一个用户请求错误或服务器发生意外时, 你可以简单地抛出一个异常来通知用户出错了。
如果你能找出错误的原因 (例如,所请求的资源不存在),你应该
考虑抛出一个适当的HTTP状态代码的异常 (例如, [[yii\web\NotFoundHttpException]]
意味着一个404 HTTP状态代码)。 Yii 将通过HTTP状态码和文本
发送相应的响应。 它还将包括在响应主体异常的
序列化表示形式。 例如,
```
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"type": "yii\\web\\NotFoundHttpException",
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
```
下面的列表总结了Yii的REST框架的HTTP状态代码:
* `200`: OK。一切正常。
* `201`: 响应 `POST` 请求时成功创建一个资源。`Location` header
包含的URL指向新创建的资源。
* `204`: 该请求被成功处理,响应不包含正文内容 (类似 `DELETE` 请求)。
* `304`: 资源没有被修改。可以使用缓存的版本。
* `400`: 错误的请求。可能通过用户方面的多种原因引起的,例如在请求体内有无效的JSON
数据,无效的操作参数,等等。
* `401`: 验证失败。
* `403`: 已经经过身份验证的用户不允许访问指定的 API 末端。
* `404`: 所请求的资源不存在。
* `405`: 不被允许的方法。 请检查 `Allow` header 允许的HTTP方法。
* `415`: 不支持的媒体类型。 所请求的内容类型或版本号是无效的。
* `422`: 数据验证失败 (例如,响应一个 `POST` 请求)。 请检查响应体内详细的错误消息。
* `429`: 请求过多。 由于限速请求被拒绝。
* `500`: 内部服务器错误。 这可能是由于内部程序错误引起的。
快速入门
===========
Yii 提供了一整套用来简化实现RESTful风格的Web Service服务的API。
特别是,Yii支持以下关于RESTful风格的API:
* 支持 [Active Record](db-active-record.md) 类的通用API的快速原型;
* 涉及的响应格式(在默认情况下支持JSON 和 XML);
* 支持可选输出字段的 可定制对象序列化;
* 适当的格式的数据采集和验证错误;
* 支持 [HATEOAS](http://en.wikipedia.org/wiki/HATEOAS);
* 有适当HTTP动词检查的高效的路由;
* 内置`OPTIONS``HEAD`动词的支持;
* 认证和授权;
* 数据缓存和HTTP缓存;
* 速率限制;
如下, 我们用一个例子来说明如何用最少的编码来建立一套RESTful风格的API。
假设你想通过RESTful风格的API来展示用户数据。用户数据被存储在用户DB表,
你已经创建了 [[yii\db\ActiveRecord|ActiveRecord]] 类 `app\models\User` 来访问该用户数据.
## 创建一个控制器 <a name="creating-controller"></a>
首先,创建一个控制器类 `app\controllers\UserController` 如下,
```php
namespace app\controllers;
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
}
```
控制器类扩展自 [[yii\rest\ActiveController]]。通过指定 [[yii\rest\ActiveController::modelClass|modelClass]]
作为 `app\models\User`, 控制器就能知道使用哪个模型去获取和处理数据。
## 配置URL规则 <a name="configuring-url-rules"></a>
然后,修改有关在应用程序配置的`urlManager`组件的配置:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
上面的配置主要是为`user`控制器增加一个URL规则。这样,
用户的数据就能通过美化的URL和有意义的http动词进行访问和操作。
## 尝试 <a name="trying-it-out"></a>
随着以上所做的最小的努力,你已经完成了创建用于访问用户数据
的RESTful风格的API。您所创建的API包括:
* `GET /users`: 逐页列出所有用户;
* `HEAD /users`: 显示用户列表的概要信息;
* `POST /users`: 创建一个新用户;
* `GET /users/123`: 返回用户为123的详细信息;
* `HEAD /users/123`: 显示用户 123 的概述信息;
* `PATCH /users/123` and `PUT /users/123`: 更新用户123;
* `DELETE /users/123`: 删除用户123;
* `OPTIONS /users`: 显示关于末端 `/users` 支持的动词;
* `OPTIONS /users/123`: 显示有关末端 `/users/123` 支持的动词。
> Info: Yii将在末端使用的控制器的名称自动变为复数。
你可以访问你的API用`curl`命令如下,
```
$ curl -i -H "Accept:application/json" "http://localhost/users"
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
```
试着改变可接受的内容类型为`application/xml`,你会看到结果以XML格式返回:
```
$ curl -i -H "Accept:application/xml" "http://localhost/users"
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/xml
<?xml version="1.0" encoding="UTF-8"?>
<response>
<item>
<id>1</id>
...
</item>
<item>
<id>2</id>
...
</item>
...
</response>
```
> Tip: 您还可以通过Web浏览器中输入URL `http://localhost/users` 来访问你的API。
尽管如此,你可能需要一些浏览器插件来发送特定的headers请求。
如你所见, 在headers响应, 有关于总数,页数的信息,等等。
还有一些链接,让您导航到其他页面的数据. 例如, `http://localhost/users?page=2`
会给你的用户数据的下一个页面。
使用 `fields``expand` 参数, 您也可以指定哪些字段应该包含在结果内。
例如, URL `http://localhost/users?fields=id,email` 将只返回 `id``email` 字段。
> Info: 您可能已经注意到了 `http://localhost/users` 的结果包括一些敏感字段,
> 例如 `password_hash`, `auth_key`。 你肯定不希望这些出现在你的API结果中。
> 你应该在 [Response Formatting](rest-response-formatting.md) 部分中过滤掉这些字段。
## 总结 <a name="summary"></a>
使用Yii框架的RESTful风格的API, 在控制器的操作中实现API末端, 使用
控制器来组织末端接口为一个单一的资源类型。
[[yii\base\Model]] 类扩展的资源被表示为数据模型。
如果你在使用(关系或非关系)数据库,推荐您使用 [[yii\db\ActiveRecord|ActiveRecord]]
来表示资源。
你可以使用 [[yii\rest\UrlRule]] 简化路由到你的API末端。
虽然不是必须的,为了方便维护您的WEB前端和后端,
建议您开发接口作为一个单独的应用程序。
速率限制
=============
为防止滥用,你应该考虑增加速率限制到您的API。
例如,您可以限制每个用户的API的使用是在10分钟内最多100次的API调用。
如果一个用户同一个时间段内太多的请求被接收, 将返回响应状态代码 429 (这意味着过多的请求)。
要启用速率限制, [[yii\web\User::identityClass|user identity class]] 应该实现 [[yii\filters\RateLimitInterface]].
这个接口需要实现以下三个方法:
* `getRateLimit()`: 返回允许的请求的最大数目及时间,例如,`[100, 600]` 表示在600秒内最多100次的API调用。
* `loadAllowance()`: 返回剩余的允许的请求和相应的UNIX时间戳数
当最后一次速率限制检查时。
* `saveAllowance()`: 保存允许剩余的请求数和当前的UNIX时间戳。
你可以在user表中使用两列来记录容差和时间戳信息。
`loadAllowance()``saveAllowance()` 可以通过实现对符合当前身份验证的用户
的这两列值的读和保存。为了提高性能,你也可以
考虑使用缓存或NoSQL存储这些信息。
一旦 identity 实现所需的接口, Yii 会自动使用 [[yii\filters\RateLimiter]]
[[yii\rest\Controller]] 配置一个行为过滤器来执行速率限制检查。 如果速度超出限制
该速率限制器将抛出一个 [[yii\web\TooManyRequestsHttpException]]。 你可以在你的 REST
控制器类里配置速率限制,
```php
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['rateLimiter']['enableRateLimitHeaders'] = false;
return $behaviors;
}
```
当速率限制被激活,默认情况下每个响应将包含以下HTTP头发送
目前的速率限制信息:
* `X-Rate-Limit-Limit`: 同一个时间段所允许的请求的最大数目;
* `X-Rate-Limit-Remaining`: 在当前时间段内剩余的请求的数量;
* `X-Rate-Limit-Reset`: 为了得到最大请求数所等待的秒数。
你可以禁用这些头信息通过配置 [[yii\filters\RateLimiter::enableRateLimitHeaders]] 为false,
就像在上面的代码示例所示。
响应格式
===================
当处理一个 RESTful API 请求时, 一个应用程序通常需要如下步骤
来处理响应格式:
1. 确定可能影响响应格式的各种因素, 例如媒介类型, 语言, 版本, 等等。
这个过程也被称为 [content negotiation](http://en.wikipedia.org/wiki/Content_negotiation)
2. 资源对象转换为数组, 如在 [Resources](rest-resources.md) 部分中所描述的。
通过 [[yii\rest\Serializer]] 来完成。
3. 通过内容协商步骤将数组转换成字符串。
[yii\web\ResponseFormatterInterface|response formatters]] 通过
[yii\web\Response::formatters|response]] 应用程序组件来注册完成。
## 内容协商 <a name="content-negotiation"></a>
Yii 提供了通过 [[yii\filters\ContentNegotiator]] 过滤器支持内容协商。RESTful API 基于
控制器类 [[yii\rest\Controller]] 在 `contentNegotiator` 下配备这个过滤器。
文件管理器提供了涉及的响应格式和语言。 例如, 如果一个 RESTful
API 请求中包含以下 header,
```
Accept: application/json; q=1.0, */*; q=0.1
```
将会得到JSON格式的响应,如下:
```
$ curl -i -H "Accept: application/json; q=1.0, */*; q=0.1" "http://localhost/users"
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
```
幕后,执行一个 RESTful API 控制器动作之前,[[yii\filters\ContentNegotiator]]
filter 将检查 `Accept` HTTP header 在请求时和配置 [[yii\web\Response::format|response format]]
`'json'`。 之后的动作被执行并返回得到的资源对象或集合,
[[yii\rest\Serializer]] 将结果转换成一个数组。最后,[[yii\web\JsonResponseFormatter]]
该数组将序列化为JSON字符串,并将其包括在响应主体。
默认, RESTful APIs 同时支持JSON和XML格式。为了支持新的格式,你应该
`contentNegotiator` 过滤器中配置 [[yii\filters\ContentNegotiator::formats|formats]] 属性,
类似如下 API 控制器类:
```php
use yii\web\Response;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_HTML;
return $behaviors;
}
```
`formats` 属性的keys支持 MIME 类型,而 values 必须在 [[yii\web\Response::formatters]]
中支持被响应格式名称。
## 数据序列化 <a name="data-serializing"></a>
正如我们上面所描述的,[[yii\rest\Serializer]] 负责转换资源的中间件
对象或集合到数组。它将对象 [[yii\base\ArrayableInterface]] 作为
[[yii\data\DataProviderInterface]]。 前者主要由资源对象实现, 而
后者是资源集合。
你可以通过设置 [[yii\rest\Controller::serializer]] 属性和一个配置数组。
例如,有时你可能想通过直接在响应主体内包含分页信息来
简化客户端的开发工作。这样做,按照如下规则配置 [[yii\rest\Serializer::collectionEnvelope]]
属性:
```php
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
public $serializer = [
'class' => 'yii\rest\Serializer',
'collectionEnvelope' => 'items',
];
}
```
那么你的请求可能会得到的响应如下 `http://localhost/users`:
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"items": [
{
"id": 1,
...
},
{
"id": 2,
...
},
...
],
"_links": {
"self": "http://localhost/users?page=1",
"next": "http://localhost/users?page=2",
"last": "http://localhost/users?page=50"
},
"_meta": {
"totalCount": 1000,
"pageCount": 50,
"currentPage": 1,
"perPage": 20
}
}
```
路由
=======
随着资源和控制器类准备,您可以使用URL如
`http://localhost/index.php?r=user/create`访问资源,类似于你可以用正常的Web应用程序做法。
在实践中,你通常要用美观的URL并采取有优势的HTTP动词。
例如,请求`POST /users`意味着访问`user/create`动作。
这可以很容易地通过配置`urlManager`应用程序组件来完成
如下所示:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
相比于URL管理的Web应用程序,上述主要的新东西是通过RESTful API
请求[[yii\rest\UrlRule]]。这个特殊的URL规则类将会
建立一整套子URL规则来支持路由和URL创建的指定的控制器。
例如, 上面的代码中是大致按照下面的规则:
```php
[
'PUT,PATCH users/<id>' => 'user/update',
'DELETE users/<id>' => 'user/delete',
'GET,HEAD users/<id>' => 'user/view',
'POST users' => 'user/create',
'GET,HEAD users' => 'user/index',
'users/<id>' => 'user/options',
'users' => 'user/options',
]
```
该规则支持下面的API末端:
* `GET /users`: 逐页列出所有用户;
* `HEAD /users`: 显示用户列表的概要信息;
* `POST /users`: 创建一个新用户;
* `GET /users/123`: 返回用户为123的详细信息;
* `HEAD /users/123`: 显示用户 123 的概述信息;
* `PATCH /users/123` and `PUT /users/123`: 更新用户123;
* `DELETE /users/123`: 删除用户123;
* `OPTIONS /users`: 显示关于末端 `/users` 支持的动词;
* `OPTIONS /users/123`: 显示有关末端 `/users/123` 支持的动词。
您可以通过配置 `only``except` 选项来明确列出哪些行为支持,
哪些行为禁用。例如,
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'except' => ['delete', 'create', 'update'],
],
```
您也可以通过配置 `patterns``extraPatterns` 重新定义现有的模式或添加此规则支持的新模式。
例如,通过末端 `GET /users/search` 可以支持新行为 `search`, 按照如下配置 `extraPatterns` 选项,
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'extraPatterns' => [
'GET search' => 'search',
],
```
您可能已经注意到控制器ID`user`以复数形式出现在`users`末端。
这是因为 [[yii\rest\UrlRule]] 能够为他们使用的末端全自动复数化控制器ID。
您可以通过设置 [[yii\rest\UrlRule::pluralize]] 为false 来禁用此行为,如果您想
使用一些特殊的名字您可以通过配置 [[yii\rest\UrlRule::controller]] 属性。
版本
==========
你的API应该是版本化的。不像你完全控制在客户端和服务器端Web应用程序代码, 对于API,您通常没有对API的客户端代码的控制权。
因此,应该尽可能的保持向后兼容性(BC),如果一些不能向后兼容的变化必须引入
APIs,你应该增加版本号。你可以参考[Semantic Versioning](http://semver.org/)
有关设计的API的版本号的详细信息。
关于如何实现API版本,一个常见的做法是在API的URL中嵌入版本号。
例如,`http://example.com/v1/users`代表`/users`版本1的API. 另一种API版本化的方法最近用的非常多的是把版本号放入HTTP请求头,通常是通过`Accept`头,
如下:
```
// 通过参数
Accept: application/json; version=v1
// 通过vendor的内容类型
Accept: application/vnd.company.myapp-v1+json
```
这两种方法都有优点和缺点, 而且关于他们也有很多争论。
下面我们描述在一种API版本混合了这两种方法的一个实用的策略:
* 把每个主要版本的API实现在一个单独的模块ID的主版本号 (例如 `v1`, `v2`)。
自然,API的url将包含主要的版本号。
* 在每一个主要版本 (在相应的模块),使用 `Accept` HTTP 请求头
确定小版本号编写条件代码来响应相应的次要版本.
为每个模块提供一个主要版本, 它应该包括资源类和控制器类
为特定服务版本。 更好的分离代码, 你可以保存一组通用的
基础资源和控制器类, 并用在每个子类版本模块。 在子类中,
实现具体的代码例如 `Model::fields()`
你的代码可以类似于如下的方法组织起来:
```
api/
common/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
modules/
v1/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
v2/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
```
你的应用程序配置应该这样:
```php
return [
'modules' => [
'v1' => [
'basePath' => '@app/modules/v1',
],
'v2' => [
'basePath' => '@app/modules/v2',
],
],
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user', 'v1/post']],
['class' => 'yii\rest\UrlRule', 'controller' => ['v2/user', 'v2/post']],
],
],
],
];
```
因此,`http://example.com/v1/users`将返回版本1的用户列表,而
`http://example.com/v2/users`将返回版本2的用户。
使用模块, 将不同版本的代码隔离。 通过共用基类和其他类
跨模块重用代码也是有可能的。
为了处理次要版本号, 可以利用内容协商
功能通过 [[yii\filters\ContentNegotiator|contentNegotiator]] 提供的行为。`contentNegotiator`
行为可设置 [[yii\web\Response::acceptParams]] 属性当它确定
支持哪些内容类型时。
例如, 如果一个请求通过 `Accept: application/json; version=v1`被发送,
内容交涉后,[[yii\web\Response::acceptParams]]将包含值`['version' => 'v1']`.
基于 `acceptParams` 的版本信息,你可以写条件代码
如 actions,resource classes,serializers等等。
由于次要版本需要保持向后兼容性,希望你的代码不会有
太多的版本检查。否则,有机会你可能需要创建一个新的主要版本。
......@@ -27,16 +27,16 @@ CREATE TABLE `country` (
`population` INT(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Country` VALUES ('AU','Australia',18886000);
INSERT INTO `Country` VALUES ('BR','Brazil',170115000);
INSERT INTO `Country` VALUES ('CA','Canada',1147000);
INSERT INTO `Country` VALUES ('CN','China',1277558000);
INSERT INTO `Country` VALUES ('DE','Germany',82164700);
INSERT INTO `Country` VALUES ('FR','France',59225700);
INSERT INTO `Country` VALUES ('GB','United Kingdom',59623400);
INSERT INTO `Country` VALUES ('IN','India',1013662000);
INSERT INTO `Country` VALUES ('RU','Russia',146934000);
INSERT INTO `Country` VALUES ('US','United States',278357000);
INSERT INTO `country` VALUES ('AU','Australia',18886000);
INSERT INTO `country` VALUES ('BR','Brazil',170115000);
INSERT INTO `country` VALUES ('CA','Canada',1147000);
INSERT INTO `country` VALUES ('CN','China',1277558000);
INSERT INTO `country` VALUES ('DE','Germany',82164700);
INSERT INTO `country` VALUES ('FR','France',59225700);
INSERT INTO `country` VALUES ('GB','United Kingdom',59623400);
INSERT INTO `country` VALUES ('IN','India',1013662000);
INSERT INTO `country` VALUES ('RU','Russia',146934000);
INSERT INTO `country` VALUES ('US','United States',278357000);
```
于是便有了一个名为 `yii2basic` 的数据库,在这个数据库中有一个包含三个字段的数据表 `country`,表中有十行数据。
......
运行应用
====================
安装 Yii 后,就有了一个运行中的 Yii 应用,根据配置的不同,可以通过 `http://hostname/basic/web/index.php``http://hostname/index.php` 访问。本章节将介绍应用的内建功能,如何组织代码,以及一般情况下应用如何处理请求。
安装 Yii 后,就有了一个可运行的 Yii 应用,根据配置的不同,可以通过 `http://hostname/basic/web/index.php``http://hostname/index.php` 访问。本章节将介绍应用的内建功能,如何组织代码,以及一般情况下应用如何处理请求。
> 补充:为简单起见,在整个“入门”板块都假定你已经把 `basic/web` 设为 Web 服务器根目录并配置完毕,你访问应用的地址会是 `http://lostname/index.php` 或类似的。请按需调整 URL。
......@@ -24,6 +24,7 @@
---------------------
应用中最重要的目录和文件(假设应用根目录是 `basic`):
```
basic/ 应用根目录
composer.json Composer 配置文件, 描述包信息
......
......@@ -121,7 +121,7 @@ public function rules()
```php
function foo($model, $attribute) {
// ... compute $value ...
// ... 计算 $value ...
return $value;
}
```
......
引入第三方代码
=============================
有时,你可能会需要在 Yii 应用中使用第三方的代码。又或者是你想要在第三方系统中把 Yii 作为类库引用。在下面这个板块中,我们向你展示如何实现这些目标。
## 在 Yii 中使用第三方类库 <a name="using-libs-in-yii"></a>
要想在 Yii 应用中使用第三方类库,你主要需要确保这些库中的类文件都可以被正常导入或可以被自动加载。
### 使用 Composer 包 <a name="using-composer-packages"></a>
目前很多第三方的类库都以 [Composer](https://getcomposer.org/) 包的形式发布。你只需要以下两个简单的步骤即可安装他们:
1. 修改你应用的 `composer.json` 文件,并注明需要安装哪些 Composer 包。
2. 运行 `php composer.phar install` 安装这些包。
这些Composer 包内的类库,可以通过 Composer 的自动加载器实现自动加载。不过请确保你应用的
[入口脚本](structure-entry-scripts.md)包含以下几行用于加载 Composer 自动加载器的代码:
```php
// install Composer autoloader (安装 Composer 自动加载器)
require(__DIR__ . '/../vendor/autoload.php');
// include Yii class file (加载 Yii 的类文件)
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
```
### 使用下载的类库 <a name="using-downloaded-libs"></a>
若你的类库并未发布为一个 Composer 包,你可以参考以下安装说明来安装它。在大多数情况下,你需要预先下载一个发布文件,并把它解压缩到
`BasePath/vendor` 目录,这里的 `BasePath` 代指你应用程序自身的 [base path(主目录)](structure-applications.md#basePath)
若该类库包含他自己的类自动加载器,你可以把它安装到你应用的[入口脚本](structure-entry-scripts.md)里。我们推荐你把它的安装代码置于
`Yii.php` 的导入之前,这样 Yii 的官方自动加载器可以拥有更高的优先级。
若一个类库并没有提供自动加载器,但是他的类库命名方式符合 [PSR-4](http://www.php-fig.org/psr/psr-4/) 标准,你可以使用 Yii 官方的自动加载器来自动加载这些类。你只需给他们的每个根命名空间声明一下[根路径别名](concept-aliases.md#defining-aliases)。比如,假设说你已经在目录 `vendor/foo/bar` 里安装了一个类库,且这些类库的根命名空间为 `xyz`。你可以把以下代码放入你的应用配置文件中:
```php
[
'aliases' => [
'@xyz' => '@vendor/foo/bar',
],
]
```
若以上情形都不符合,最可能是这些类库需要依赖于 PHP 的 include_path 配置,来正确定位并导入类文件。只需参考它的安装说明简单地配置一下 PHP 导入路径即可。
最悲催的情形是,该类库需要显式导入每个类文件,你可以使用以下方法按需导入相关类文件:
* 找出该库内包含哪些类。
* 在应用的[入口脚本](structure-entry-scripts.md)里的 `Yii::$classMap` 数组中列出这些类,和他们各自对应的文件路径。
举例来说,
```php
Yii::$classMap['Class1'] = 'path/to/Class1.php';
Yii::$classMap['Class2'] = 'path/to/Class2.php';
```
## 在第三方系统内使用 Yii <a name="using-yii-in-others"></a>
因为 Yii 提供了很多牛逼的功能,有时,你可能会想要使用它们中的一些功能用来支持开发或完善某些第三方的系统,比如:WordPress,Joomla,或是用其他 PHP 框架开发的应用程序。举两个例子吧,你可能会想念方便的 [[yii\helpers\ArrayHelper]] 类,或在第三方系统中使用
[Active Record](db-active-record.md) 活动记录功能。要实现这些目标,你只需两个步骤:安装 Yii,启动 Yii。
若这个第三方系统支持 Composer 管理他的依赖文件,你可以直接运行一下命令来安装 Yii:
```
php composer.phar require yiisoft/yii2-framework:*
php composer.phar install
```
不然的话,你可以[下载](http://www.yiiframework.com/download/) Yii 的发布包,并把它解压到对应系统的 `BasePath/vendor` 目录内。
之后,你需要修改该第三方应用的入口脚本,在开头位置添加 Yii 的引入代码:
```php
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
$yiiConfig = require(__DIR__ . '/../config/yii/web.php');
new yii\web\Application($yiiConfig); // 千万别在这调用 run() 方法。(笑)
```
如你所见,这段代码与典型的 Yii 应用的[入口脚本](structure-entry-scripts.md)非常相似。唯一的不同之处在于在 Yii 应用创建成功之后,并不会紧接着调用 `run()` 方法。因为,`run()` 方法的调用会接管 HTTP 请求的处理流程。(译者注:换言之,这就不是第三方系统而是 Yii 系统了,URL 规则也会跟着换成 Yii 的规则了)
与 Yii 应用中一样,你可以依据运行该第三方系统的环境,针对性地配置 Yii 应用实例。比如,为了使用[活动记录](db-active-record.md)功能,你需要先用该第三方系统的 DB 连接信息,配置 Yii 的 `db` 应用组件。
现在,你就可以使用 Yii 提供的绝大多数功能了。比如,创建 AR 类,并用它们来操作数据库。
## 配合使用 Yii 2 和 Yii 1 <a name="using-both-yii2-yii1"></a>
如果你之前使用 Yii 1,大概你也有正在运行的 Yii 1 应用吧。不必用 Yii 2 重写整个应用,你也可以通过增添对哪些
Yii 2 独占功能的支持来增强这个系统。下面我们就来详细描述一下具体的实现过程。
> 注意:Yii 2 需要 PHP 5.4+ 的版本。你需要确保你的服务器以及现有应用都可以支持 PHP 5.4。
首先,参考前文板块中给出的方法,在已有的应用中安装 Yii 2。
之后,如下修改 Yii 1 应用的入口脚步:
```php
// 导入下面会详细说明的定制 Yii 类文件。
require(__DIR__ . '/../components/Yii.php');
// Yii 2 应用的配置文件
$yii2Config = require(__DIR__ . '/../config/yii2/web.php');
new yii\web\Application($yii2Config); // Do NOT call run()
// Yii 1 应用的配置文件
$yii1Config = require(__DIR__ . '/../config/yii1/main.php');
Yii::createWebApplication($yii1Config)->run();
```
因为,Yii 1 和 Yii 2 都包含有 `Yii` 这个类,你应该创建一个定制版的 Yii 来把他们组合起来。上面的代码里包含了的这个定制版的 `Yii` 类,可以用以下代码创建出来:
```php
$yii2path = '/path/to/yii2';
require($yii2path . '/BaseYii.php'); // Yii 2.x
$yii1path = '/path/to/yii1';
require($yii1path . '/YiiBase.php'); // Yii 1.x
class Yii extends \yii\BaseYii
{
// 复制粘贴 YiiBase (1.x) 文件中的代码于此
}
Yii::$classMap = include($yii2path . '/classes.php');
// 通过 Yii 1 注册 Yii2 的类自动加载器
Yii::registerAutoloader(['Yii', 'autoload']);
```
大功告成!此时,你可以在你代码的任意位置,调用 `Yii::$app` 以访问 Yii 2 的应用实例,而用
`Yii::app()` 则会返回 Yii 1 的应用实例:
```php
echo get_class(Yii::app()); // 输出 'CWebApplication'
echo get_class(Yii::$app); // 输出 'yii\web\Application'
```
......@@ -210,7 +210,7 @@ You can also call a *public* method of the behavior similarly:
$component->foo();
```
As you can see, although `$component` does not define `prop1` and `bar()`, they can be used as if they are part
As you can see, although `$component` does not define `prop1` and `foo()`, they can be used as if they are part
of the component definition due to the attached behavior.
If two behaviors define the same property or method and they are both attached to the same component,
......
......@@ -97,6 +97,7 @@ When the `validate()` method is called, it does the following steps to perform v
2. Determine which rules should be applied by checking the current [[yii\base\Model::scenario|scenario]]
against the rules declared in [[yii\base\Model::rules()]]. These rules are the active rules.
3. Use each active rule to validate each active attribute which is associated with the rule.
The validation rules are evaluated in the order they are listed.
According to the above validation steps, an attribute will be validated if and only if it is
an active attribute declared in `scenarios()` and is associated with one or multiple active rules
......
......@@ -141,7 +141,7 @@ Data column is for displaying and sorting data. It is default column type so spe
using it.
The main setting of the data column is its format. It could be specified via `format` attribute. Its values are
corresponding to methods in `format` application component that is [[\yii\base\Formatter|Formatter]] by default:
corresponding to methods in `format` application component that is [[\yii\i18n\Formatter|Formatter]] by default:
```php
<?= GridView::widget([
......@@ -158,34 +158,12 @@ corresponding to methods in `format` application component that is [[\yii\base\F
]); ?>
```
In the above `text` corresponds to [[\yii\base\Formatter::asText()]]. The value of the column is passed as the first
argument. In the second column definition `date` corresponds to [[\yii\base\Formatter::asDate()]]. The value of the
In the above `text` corresponds to [[\yii\i18n\Formatter::asText()]]. The value of the column is passed as the first
argument. In the second column definition `date` corresponds to [[\yii\i18n\Formatter::asDate()]]. The value of the
column is, again, passed as the first argument while 'Y-m-d' is used as the second argument value.
Here's the bundled formatters list:
- [[\yii\base\Formatter::asRaw()|raw]] - the value is outputted as is.
- [[\yii\base\Formatter::asText()|text]] - the value is HTML-encoded. This format is used by default.
- [[\yii\base\Formatter::asNtext()|ntext]] - the value is formatted as an HTML-encoded plain text with newlines converted
into line breaks.
- [[\yii\base\Formatter::asParagraphs()|paragraphs]] - the value is formatted as HTML-encoded text paragraphs wrapped
into `<p>` tags.
- [[\yii\base\Formatter::asHtml()|html]] - the value is purified using [[HtmlPurifier]] to avoid XSS attacks. You can
pass additional options such as `['html', ['Attr.AllowedFrameTargets' => ['_blank']]]`.
- [[\yii\base\Formatter::asEmail()|email]] - the value is formatted as a mailto link.
- [[\yii\base\Formatter::asImage()|image]] - the value is formatted as an image tag.
- [[\yii\base\Formatter::asUrl()|url]] - the value is formatted as a hyperlink.
- [[\yii\base\Formatter::asBoolean()|boolean]] - the value is formatted as a boolean. You can set what's rendered for
true and false values by calling `Yii::$app->formatter->booleanFormat = ['No', 'Yes'];` before outputting GridView.
- [[\yii\base\Formatter::asDate()|date]] - the value is formatted as date.
- [[\yii\base\Formatter::asTime()|time]] - the value is formatted as time.
- [[\yii\base\Formatter::asDatetime()|datetime]] - the value is formatted as datetime.
- [[\yii\base\Formatter::asInteger()|integer]] - the value is formatted as an integer.
- [[\yii\base\Formatter::asDouble()|double]] - the value is formatted as a double number.
- [[\yii\base\Formatter::asNumber()|number]] - the value is formatted as a number with decimal and thousand separators.
- [[\yii\base\Formatter::asSize()|size]] - the value that is a number of bytes is formatted as a human readable size.
- [[\yii\base\Formatter::asRelativeTime()|relativeTime]] - the value is formatted as the time interval between a date
and now in human readable form.
For a list of available formatters see the [section about Data Formatting](output-formatter.md).
#### Action column
......
Data Formatter
==============
For formatting of outputs Yii provides a formatter class to make date more readable for users.
[[yii\i18n\Formatter]] is a helper class that is registered as an [application component](concept-components.md) name `formatter` by default.
It provides a set of methods for data formatting purpose such as date/time values, numbers and other commonly used formats in a localized way.
The formatter can be used in two different ways.
1. Using the formatting methods(all formatter methods prefixed with `as`) directly:
```php
echo Yii::$app->formatter->asDate('2014-01-01', 'long'); // output: January 1, 2014
echo Yii::$app->formatter->asPercent(0.125, 2); // output: 12.50%
echo Yii::$app->formatter->asEmail('cebe@example.com'); // output: <a href="mailto:cebe@example.com">cebe@example.com</a>
echo Yii::$app->formatter->asBoolean(true); // output: Yes
// it also handles display of null values:
echo Yii::$app->formatter->asDate(null); // output: (Not set)
```
2. Using the [[yii\i18n\Formatter::format()|format()]] method using the format name.
This method is used by classes like GridView and DetailView where you can specify the data format of a column in the
widget config.
```php
echo Yii::$app->formatter->format('2014-01-01', 'date'); // output: January 1, 2014
// you can also use an array to specify parameters for the format method:
// `2` is the value for the $decimals parameter of the asPercent()-method.
echo Yii::$app->formatter->format(0.125, ['percent', 2]); // output: 12.50%
```
All output of the formatter is localized when the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed.
You can configure the [[yii\i18n\Formatter::locale|locale]] property of the formatter for this. If not configured, the
application [[yii\base\Application::language|language]] is used as the locale. See the [Section on internationaization](tutorial-i18n.md) for more details.
The Formatter will then choose the correct format for dates and number according to the locale including names of month and
week days translated to the current language. Date formats are also affected by the [[yii\i18n\Formatter::timeZone|timeZone]]
which will also be taken [[yii\base\Application::timeZone|from the application]] by default.
For example the date format call will output different results for different locales:
```php
Yii::$app->formatter->locale = 'en-US';
echo Yii::$app->formatter->asDate('2014-01-01'); // output: January 1, 2014
Yii::$app->formatter->locale = 'de-DE';
echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1. Januar 2014
Yii::$app->formatter->locale = 'ru-RU';
echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1 января 2014 г.
```
> Note that formatting may differ between different versions of the ICU library compiled with PHP and also based on the fact whether the
> [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed or not. So to ensure your website works with the same output
> in all environments it is recommended to install the PHP intl extension in all environments and verify that the version of the ICU library
> is the same.
Configuring the format
----------------------
The default format of the Formatter class can be adjusted using the properties of the formatter class.
You can adjust these values application wide by configuring the `formatter` component in your [application config](concept-configurations.md#application-configurations)
an example configuration is shown in the following.
For more details about certain properties check out the [[yii\i18n\Formatter|API documentation of the Formatter class]].
```php
'components' => [
'formatter' => [
'dateFormat' => 'dd.MM.yyyy',
'decimalSeparator' => ',',
'thousandSeparator' => ' ',
'currencyCode' => 'EUR',
];
```
Formatting Dates
----------------
TDB
See http://site.icu-project.org/ for the format.
- [[\yii\i18n\Formatter::asDate()|date]] - the value is formatted as date.
- [[\yii\i18n\Formatter::asTime()|time]] - the value is formatted as time.
- [[\yii\i18n\Formatter::asDatetime()|datetime]] - the value is formatted as datetime.
- [[\yii\i18n\Formatter::asTimestamp()|timestamp]] - the value is formatted as a unix timestamp.
- [[\yii\i18n\Formatter::asRelativeTime()|relativeTime]] - the value is formatted as the time interval between a date
and now in human readable form.
Formatting Numbers
------------------
TDB
See http://site.icu-project.org/ for the format.
- [[\yii\i18n\Formatter::asInteger()|integer]] - the value is formatted as an integer.
- [[\yii\i18n\Formatter::asDecimal()|decimal]] - the value is formatted as a number with decimal and thousand separators.
- [[\yii\i18n\Formatter::asPercent()|percent]] - the value is formatted as a percent number.
- [[\yii\i18n\Formatter::asScientific()|scientific]] - the value is formatted as a number in scientific format.
- [[\yii\i18n\Formatter::asCurrency()|currency]] - the value is formatted as a currency value.
- [[\yii\i18n\Formatter::asSize()|size]] - the value that is a number of bytes is formatted as a human readable size.
- [[\yii\i18n\Formatter::asShortSize()|shortSize]] - the value that is a number of bytes is formatted as a human readable size.
Other formatters
----------------
TDB
Here's the bundled formatters list:
- [[\yii\i18n\Formatter::asRaw()|raw]] - the value is outputted as is.
- [[\yii\i18n\Formatter::asText()|text]] - the value is HTML-encoded. This format is used by default.
- [[\yii\i18n\Formatter::asNtext()|ntext]] - the value is formatted as an HTML-encoded plain text with newlines converted
into line breaks.
- [[\yii\i18n\Formatter::asParagraphs()|paragraphs]] - the value is formatted as HTML-encoded text paragraphs wrapped
into `<p>` tags.
- [[\yii\i18n\Formatter::asHtml()|html]] - the value is purified using [[HtmlPurifier]] to avoid XSS attacks. You can
pass additional options such as `['html', ['Attr.AllowedFrameTargets' => ['_blank']]]`.
- [[\yii\i18n\Formatter::asEmail()|email]] - the value is formatted as a mailto link.
- [[\yii\i18n\Formatter::asImage()|image]] - the value is formatted as an image tag.
- [[\yii\i18n\Formatter::asUrl()|url]] - the value is formatted as a hyperlink.
- [[\yii\i18n\Formatter::asBoolean()|boolean]] - the value is formatted as a boolean. You can set what's rendered for
true and false values by calling `Yii::$app->formatter->booleanFormat = ['No', 'Yes'];` before outputting GridView.
......@@ -17,7 +17,6 @@ Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"type": "yii\\web\\NotFoundHttpException",
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
......@@ -42,3 +41,55 @@ The following list summarizes the HTTP status code that are used by the Yii REST
* `422`: Data validation failed (in response to a `POST` request, for example). Please check the response body for detailed error messages.
* `429`: Too many requests. The request was rejected due to rate limiting.
* `500`: Internal server error. This could be caused by internal program errors.
## Customizing Error Response <a name="customizing-error-response"></a>
Sometimes you may want to customize the default error response format. For example, instead of relying on
using different HTTP statuses to indicate different errors, you would like to always use 200 as HTTP status
and enclose the actual HTTP status code as part of the JSON structure in the response, like shown in the following,
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"success": false,
"data": {
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
}
```
To achieve this goal, you can respond to the `beforeSend` event of the `response` component in the application configuration:
```php
return [
// ...
'components' => [
'response' => [
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if ($response->data !== null && !empty(Yii::$app->request->get['suppress_response_code'])) {
$response->data = [
'success' => $response->isSuccessful,
'data' => $response->data,
];
$response->statusCode = 200;
}
},
],
],
];
```
The above code will reformat the response (for both successful and failed responses) as explained when
`suppress_response_code` is passed as a `GET` parameter.
......@@ -232,7 +232,7 @@ Observe more carefully and you will find that the URL in the browser also change
http://hostname/index.php?r=country/index&page=2
```
Behind the scenes, [[yii\data\Pagination|Pagination]] is providing all of the ncessary functionality to paginate a data set:
Behind the scenes, [[yii\data\Pagination|Pagination]] is providing all of the necessary functionality to paginate a data set:
* Initially, [[yii\data\Pagination|Pagination]] represents the first page, which reflects the country SELECT query
with the clause `LIMIT 5 OFFSET 0`. As a result, the first five countries will be fetched and displayed.
......
......@@ -43,6 +43,16 @@ Thanks to that line, your application is in development mode, and will have alre
http://hostname/index.php?r=gii
```
> Note: If you are accessing Gii from a machine other than localhost, the access will be denied by default
> for security purpose. You can configure Gii to add the allowed IP addresses as follows,
>
```php
'gii' => [
'class' => 'yii\gii\Module',
'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.178.20'] // adjust this to your needs
],
```
![Gii](images/start-gii.png)
......
......@@ -94,7 +94,7 @@ if you do not specify its class, the default one will be used.
Please refer to the [Data Access Objects](db-dao.md) section for more details.
* [[yii\base\Application::errorHandler|errorHandler]]: handles PHP errors and exceptions.
Please refer to the [Handling Errors](tutorial-handling-errors.md) section for more details.
* [[yii\base\Formatter|formatter]]: formats data when they are displayed to end users. For example, a number
* [[yii\i18n\Formatter|formatter]]: formats data when they are displayed to end users. For example, a number
may be displayed with thousand separator, a date may be formatted in long format.
Please refer to the [Data Formatting](output-formatting.md) section for more details.
* [[yii\i18n\I18N|i18n]]: supports message translation and formatting.
......
......@@ -161,15 +161,13 @@ You may configure [[yii\base\Application::controllerMap|controller map]] in the
```php
[
'controllerMap' => [
[
// declares "account" controller using a class name
'account' => 'app\controllers\UserController',
// declares "article" controller using a configuration array
'article' => [
'class' => 'app\controllers\PostController',
'enableCsrfValidation' => false,
],
// declares "account" controller using a class name
'account' => 'app\controllers\UserController',
// declares "article" controller using a configuration array
'article' => [
'class' => 'app\controllers\PostController',
'enableCsrfValidation' => false,
],
],
]
......
......@@ -308,7 +308,7 @@ content to end users, you should try to [internationalize and localize](tutorial
- If the extension displays messages intended for end users, the messages should be wrapped into `Yii::t()`
so that they can be translated. Messages meant for developers (such as internal exception messages) do not need
to be translated.
- If the extension displays numbers, dates, etc., they should be formatted using [[yii\base\Formatter]] with
- If the extension displays numbers, dates, etc., they should be formatted using [[yii\i18n\Formatter]] with
appropriate formatting rules.
For more details, please refer to the [Internationalization](tutorial-i18n.md) section.
......
......@@ -224,6 +224,10 @@ use yii\web\Response;
];
```
> Info: In case the preferred content type and language cannot be determined from a request, the first format and
language listed in [[formats]] and [[languages]] will be used.
### [[yii\filters\HttpCache|HttpCache]] <a name="http-cache"></a>
......
......@@ -40,7 +40,7 @@ $this->title = 'Login';
Within a view, you can access `$this` which refers to the [[yii\web\View|view component]] managing
and rendering this view template.
Besides `$this`, there may be other predefined variables in a view, such as `$form` and `$model` in the above
Besides `$this`, there may be other predefined variables in a view, such as `$model` in the above
example. These variables represent the data that are *pushed* into the view by [controllers](structure-controllers.md)
or other objects whose trigger the [view rendering](#rendering-views).
......@@ -264,7 +264,7 @@ echo $this->render('report', [
```
The pull approach actively retrieves data from the [[yii\base\View|view component]] or other objects accessible
in views (e.g. `Yii::$app`). Using the above code as an example, within the view you can get the controller object
in views (e.g. `Yii::$app`). Using the code below as an example, within the view you can get the controller object
by the expression `$this->context`. And as a result, it is possible for you to access any properties or methods
of the controller in the `report` view, such as the controller ID shown in the following:
......
......@@ -90,7 +90,7 @@ Predefined path aliases
- `@webroot` - web root directory of currently running web application.
The aliases specific to the directory structure of the advanced application
(`@common`, `@frontend`, `@backend`, and `@console`) are defined in `common/config/aliases.php`.
(`@common`, `@frontend`, `@backend`, and `@console`) are defined in `common/config/bootstrap.php`.
Applications
......
......@@ -475,26 +475,7 @@ put there file for russian language as follows `views/site/ru-RU/index.php`.
> **Note**: If language is specified as `en-US` and there are no corresponding views, Yii will try views under `en`
> before using original ones.
i18n formatter
i18n Formatter
--------------
i18n formatter component is the localized version of formatter that supports formatting of date, time and numbers based
on current locale. In order to use it you need to configure formatter application component as follows:
```php
return [
// ...
'components' => [
'formatter' => [
'class' => 'yii\i18n\Formatter',
],
],
];
```
After configuring the component can be accessed as `Yii::$app->formatter`.
Note that in order to use i18n formatter you need to install and enable
[intl](http://www.php.net/manual/en/intro.intl.php) PHP extension.
In order to learn about formatter methods refer to its API documentation: [[yii\i18n\Formatter]].
See the [data formatter section](output-formatter.md) for details.
......@@ -420,6 +420,13 @@ To give one of the above mentioned links another label than the class or method
The part before the | is the method, property or class reference while the part after | is the link label.
It is also possible to link to the Guide using the following syntax:
```markdown
[link to guide](guide:file-name.md)
[link to guide](guide:file-name.md#subsection)
```
#### Comments
......
......@@ -72,6 +72,12 @@ make pdf
If all runs without errors the PDF will be `guide.pdf` in the `output` dir.
Special Markdown Syntax
-----------------------
We have a special Syntax for linking to classes in the API documentation.
See the [code style guide](https://github.com/yiisoft/yii2/blob/master/docs/internals/core-code-style.md#markdown) for details.
Creating your own templates
---------------------------
......@@ -80,4 +86,4 @@ TDB
Using the model layer
---------------------
TDB
\ No newline at end of file
TDB
......@@ -10,7 +10,6 @@ namespace yii\apidoc\commands;
use yii\apidoc\components\BaseController;
use yii\apidoc\models\Context;
use yii\apidoc\renderers\ApiRenderer;
use yii\apidoc\renderers\BaseRenderer;
use yii\helpers\ArrayHelper;
use yii\helpers\Console;
use yii\helpers\FileHelper;
......@@ -48,18 +47,15 @@ class ApiController extends BaseController
// setup reference to guide
if ($this->guide !== null) {
$guideUrl = $this->guide;
$referenceFile = $guideUrl . '/' . BaseRenderer::GUIDE_PREFIX . 'references.txt';
$renderer->guideUrl = $guideUrl = $this->guide;
} else {
$guideUrl = './';
$referenceFile = $targetDir . '/' . BaseRenderer::GUIDE_PREFIX . 'references.txt';
$renderer->guideUrl = $targetDir;
}
if (file_exists($referenceFile)) {
if (file_exists($renderer->generateGuideUrl('README.md'))) {
$renderer->guideUrl = $guideUrl;
$renderer->guideReferences = [];
foreach (explode("\n", file_get_contents($referenceFile)) as $reference) {
$renderer->guideReferences[BaseRenderer::GUIDE_PREFIX . $reference]['url'] = $renderer->generateGuideUrl($reference);
}
} else {
$renderer->guideUrl = null;
}
// search for files to process
......
......@@ -70,13 +70,6 @@ class GuideController extends BaseController
FileHelper::copyDirectory(rtrim($source, '/\\') . '/images', $targetDir . '/images');
}
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
// generate api references.txt
$references = [];
foreach ($files as $file) {
$references[] = basename($file, '.md');
}
file_put_contents($targetDir . '/guide-references.txt', implode("\n", $references));
}
......
......@@ -89,6 +89,21 @@ class ApiMarkdown extends GithubMarkdown
}
/**
* @inheritdoc
*/
protected function parseLink($markdown)
{
list($result, $skip) = parent::parseLink($markdown);
// add special syntax for linking to the guide
$result = preg_replace_callback('/href="guide:([A-z0-9-.#]+)"/i', function($match) {
return 'href="' . static::$renderer->generateGuideUrl($match[1]) . '"';
}, $result, 1);
return [$result, $skip];
}
/**
* Converts markdown into HTML
*
* @param string $content
......
......@@ -43,7 +43,6 @@ abstract class BaseRenderer extends Component
*/
public $controller;
public $guideUrl;
public $guideReferences = [];
public function init()
......@@ -198,6 +197,12 @@ abstract class BaseRenderer extends Component
*/
public function generateGuideUrl($file)
{
return rtrim($this->guideUrl, '/') . '/' . static::GUIDE_PREFIX . basename($file, '.md') . '.html';
$hash = '';
if (($pos = strpos($file, '#')) !== false) {
$hash = substr($file, $pos);
$file = substr($file, 0, $pos);
}
return rtrim($this->guideUrl, '/') . '/' . static::GUIDE_PREFIX . basename($file, '.md') . '.html' . $hash;
}
}
......@@ -9,7 +9,6 @@ namespace yii\apidoc\templates\pdf;
use Yii;
use yii\apidoc\helpers\ApiMarkdownLaTeX;
use yii\apidoc\helpers\IndexFileAnalyzer;
use yii\helpers\Console;
/**
......
......@@ -88,7 +88,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
if ($this->_returnUrl === null) {
$this->_returnUrl = $this->defaultReturnUrl();
}
return $this->_returnUrl;
}
......@@ -202,7 +201,7 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
if ($errorNumber > 0) {
throw new Exception('Curl error requesting "' . $url . '": #' . $errorNumber . ' - ' . $errorMessage);
}
if ($responseHeaders['http_code'] != 200) {
if (strncmp($responseHeaders['http_code'], '20', 2) !== 0) {
throw new InvalidResponseException($responseHeaders, $response, 'Request failed with code: ' . $responseHeaders['http_code'] . ', message: ' . $response);
}
......@@ -232,7 +231,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
}
}
}
return $res;
}
......@@ -291,7 +289,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
throw new Exception('Unknown response type "' . $contentType . '".');
}
}
return $response;
}
......@@ -311,7 +308,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
$result[$key] = $this->convertXmlToArray($value);
}
}
return $result;
}
......@@ -333,7 +329,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
return self::CONTENT_TYPE_XML;
}
}
return self::CONTENT_TYPE_AUTO;
}
......@@ -353,7 +348,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
if (preg_match('/^<.*>$/is', $rawContent)) {
return self::CONTENT_TYPE_XML;
}
return self::CONTENT_TYPE_AUTO;
}
......@@ -367,7 +361,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
if (!array_key_exists('class', $signatureMethodConfig)) {
$signatureMethodConfig['class'] = signature\HmacSha1::className();
}
return Yii::createObject($signatureMethodConfig);
}
......@@ -381,7 +374,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
if (!array_key_exists('class', $tokenConfig)) {
$tokenConfig['class'] = OAuthToken::className();
}
return Yii::createObject($tokenConfig);
}
......@@ -399,7 +391,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
$url .= '&';
}
$url .= http_build_query($params, '', '&', PHP_QUERY_RFC3986);
return $url;
}
......@@ -426,7 +417,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
$token = $this->refreshAccessToken($token);
}
}
return $token;
}
......@@ -441,7 +431,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
$session = Yii::$app->getSession();
$key = $this->getStateKeyPrefix() . $key;
$session->set($key, $value);
return $this;
}
......@@ -455,7 +444,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
$session = Yii::$app->getSession();
$key = $this->getStateKeyPrefix() . $key;
$value = $session->get($key);
return $value;
}
......@@ -469,7 +457,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
$session = Yii::$app->getSession();
$key = $this->getStateKeyPrefix() . $key;
$session->remove($key);
return true;
}
......@@ -502,7 +489,6 @@ abstract class BaseOAuth extends BaseClient implements ClientInterface
if (!is_object($accessToken) || !$accessToken->getIsValid()) {
throw new Exception('Invalid access token.');
}
return $this->apiInternal($accessToken, $url, $method, $params, $headers);
}
......
......@@ -6,6 +6,7 @@ Yii Framework 2 authclient extension Change Log
- Bug #3633: OpenId return URL comparison advanced to prevent url encode problem (klimov-paul)
- Bug #4490: `yii\authclient\widgets\AuthChoice` does not preserve initial settings while opening popup (klimov-paul)
- Bug #5011: OAuth API Response with 20x status were not considered success (ychongsaytc)
- Enh #3416: VKontakte OAuth support added (klimov-paul)
- Enh #4076: Request HTTP headers argument added to `yii\authclient\BaseOAuth::api()` method (klimov-paul)
- Enh #4134: `yii\authclient\InvalidResponseException` added for tracking invalid remote server response (klimov-paul)
......
......@@ -8,7 +8,6 @@
namespace yii\authclient;
use yii\base\Exception;
use yii\base\NotSupportedException;
use Yii;
/**
......
......@@ -31,9 +31,9 @@ jQuery(function($) {
$container.find('a').on('click', function(e) {
e.preventDefault();
var authChoicePopup = null;
var authChoicePopup = $container.data('authChoicePopup');
if (authChoicePopup = $container.data('authChoicePopup')) {
if (authChoicePopup) {
authChoicePopup.close();
}
......@@ -49,12 +49,14 @@ jQuery(function($) {
popupOptions.height = localPopupHeight;
}
popupOptions.left = (window.screen.width - options.popup.width) / 2;
popupOptions.top = (window.screen.height - options.popup.height) / 2;
popupOptions.left = (window.screen.width - popupOptions.width) / 2;
popupOptions.top = (window.screen.height - popupOptions.height) / 2;
var popupFeatureParts = [];
for (var propName in popupOptions) {
popupFeatureParts.push(propName + '=' + popupOptions[propName]);
if (popupOptions.hasOwnProperty(propName)) {
popupFeatureParts.push(propName + '=' + popupOptions[propName]);
}
}
var popupFeature = popupFeatureParts.join(',');
......
......@@ -66,6 +66,11 @@ use yii\base\InvalidConfigException;
class ActiveForm extends \yii\widgets\ActiveForm
{
/**
* @var string the default field class name when calling [[field()]] to create a new field.
* @see fieldConfig
*/
public $fieldClass = 'yii\bootstrap\ActiveField';
/**
* @var array HTML attributes for the form tag. Default is `['role' => 'form']`.
*/
public $options = ['role' => 'form'];
......@@ -91,9 +96,6 @@ class ActiveForm extends \yii\widgets\ActiveForm
if ($this->layout !== 'default') {
Html::addCssClass($this->options, 'form-' . $this->layout);
}
if (!isset($this->fieldConfig['class'])) {
$this->fieldConfig['class'] = ActiveField::className();
}
parent::init();
}
}
......@@ -4,6 +4,7 @@
settings = settings || {};
xhr.open(settings.method || 'GET', url, true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('Accept', 'text/html');
xhr.onreadystatechange = function (state) {
if (xhr.readyState == 4) {
if (xhr.status == 200 && settings.success) {
......
......@@ -11,6 +11,10 @@ Yii Framework 2 elasticsearch extension Change Log
- Enh #4048: Added `init` event to `ActiveQuery` classes (qiangxue)
- Enh #4086: changedAttributes of afterSave Event now contain old values (dizews)
- Enh: Make error messages more readable in HTML output (cebe)
- Enh: Added support for query stats (cebe)
- Enh: Added support for query suggesters (cebe, tvdavid)
- Enh: Added support for delete by query (cebe, tvdavid)
- Chg #4451: Removed support for facets and replaced them with aggregations (cebe, tadaszelvys)
- Chg: asArray in ActiveQuery is now equal to using the normal Query. This means, that the output structure has changed and `with` is supported anymore. (cebe)
- Chg: Deletion of a record is now also considered successful if the record did not exist. (cebe)
- Chg: Requirement changes: Yii now requires elasticsearch version 1.0 or higher (cebe)
......
......@@ -8,6 +8,8 @@
namespace yii\elasticsearch;
use yii\base\Component;
use yii\base\InvalidCallException;
use yii\base\InvalidParamException;
use yii\helpers\Json;
/**
......@@ -38,15 +40,11 @@ class Command extends Component
* @var array list of arrays or json strings that become parts of a query
*/
public $queryParts;
/**
* @var array list of arrays to highlight search results on one or more fields
* @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html
*/
public $highlight;
public $options = [];
/**
* Sends a request to the _search API and returns the result
* @param array $options
* @return mixed
*/
......@@ -69,6 +67,55 @@ class Command extends Component
}
/**
* Sends a request to the delete by query
* @param array $options
* @return mixed
*/
public function deleteByQuery($options = [])
{
if (!isset($this->queryParts['query'])) {
throw new InvalidCallException('Can not call deleteByQuery when no query is given.');
}
$query = [
'query' => $this->queryParts['query'],
];
if (isset($this->queryParts['filter'])) {
$query['filter'] = $this->queryParts['filter'];
}
$query = Json::encode($query);
$url = [
$this->index !== null ? $this->index : '_all',
$this->type !== null ? $this->type : '_all',
'_query'
];
return $this->db->delete($url, array_merge($this->options, $options), $query);
}
/**
* Sends a request to the _suggest API and returns the result
* @param string|array $suggester the suggester body
* @param array $options
* @return mixed
* @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html
*/
public function suggest($suggester, $options = [])
{
if (empty($suggester)) {
$suggester = '{}';
}
if (is_array($suggester)) {
$suggester = Json::encode($suggester);
}
$url = [
$this->index !== null ? $this->index : '_all',
'_suggest'
];
return $this->db->post($url, array_merge($this->options, $options), $suggester);
}
/**
* Inserts a document into an index
* @param string $index
* @param string $type
......
......@@ -9,7 +9,6 @@ namespace yii\elasticsearch;
use yii\base\Action;
use yii\base\NotSupportedException;
use yii\debug\Panel;
use yii\helpers\ArrayHelper;
use yii\web\HttpException;
use yii\web\Response;
......
......@@ -98,19 +98,24 @@ class QueryBuilder extends \yii\base\Object
$parts['filter'] = $whereFilter;
}
if($query->highlight) {
if (!empty($query->highlight)) {
$parts['highlight'] = $query->highlight;
}
if (!empty($query->aggregations)) {
$parts['aggregations'] = $query->aggregations;
}
if (!empty($query->stats)) {
$parts['stats'] = $query->stats;
}
if (!empty($query->suggest)) {
$parts['suggest'] = $query->suggest;
}
$sort = $this->buildOrderBy($query->orderBy);
if (!empty($sort)) {
$parts['sort'] = $sort;
}
if (!empty($query->facets)) {
$parts['facets'] = $query->facets;
}
$options = [];
if ($query->timeout !== null) {
$options['timeout'] = $query->timeout;
......
......@@ -171,7 +171,7 @@ class FixtureController extends \yii\console\controllers\FixtureController
public function options($actionID)
{
return array_merge(parent::options($actionID), [
'templatePath', 'language', 'fixtureDataPath'
'templatePath', 'language', 'fixtureDataPath', 'count'
]);
}
......@@ -338,7 +338,7 @@ class FixtureController extends \yii\console\controllers\FixtureController
}
/**
* Returns array containg fixtures templates file names. You can specify what files to find
* Returns array containing fixtures templates file names. You can specify what files to find
* by the given parameter.
* @param array $templatesNames template file names to search. If empty then all files will be searched.
* @return array
......@@ -428,9 +428,9 @@ class FixtureController extends \yii\console\controllers\FixtureController
/**
* Generates fixture file by the given fixture template file.
* @param type $templateName template file name
* @param type $templatePath path where templates are stored
* @param type $fixtureDataPath fixture data path where generated file should be written
* @param string $templateName template file name
* @param string $templatePath path where templates are stored
* @param string $fixtureDataPath fixture data path where generated file should be written
*/
public function generateFixtureFile($templateName, $templatePath, $fixtureDataPath)
{
......
......@@ -9,6 +9,7 @@ Yii Framework 2 gii extension Change Log
- Bug #3265: Fixed incorrect controller class name validation (suralc)
- Bug #3693: Fixed broken Gii preview when a file is unchanged (cebe)
- Bug #4410: Fixed Gii to preserve database column order in generated _form.php (kmindi)
- Bug #4971: Fixed hardcoded table names in `viaTable` expression in model generator (stepanselyuk)
- Enh #2018: Search model is not required anymore in CRUD generator (johonunu)
- Enh #3088: The gii module will manage their own URL rules now (qiangxue)
- Enh #3222: Added `useTablePrefix` option to the model generator for Gii (horizons2)
......
......@@ -354,7 +354,7 @@ class Generator extends \yii\gii\Generator
$viaLink = $this->generateRelationLink([$table->primaryKey[0] => $fks[$table->primaryKey[0]][1]]);
$relationName = $this->generateRelationName($relations, $className0, $db->getTableSchema($table0), $table->primaryKey[1], true);
$relations[$className0][$relationName] = [
"return \$this->hasMany($className1::className(), $link)->viaTable('{$table->name}', $viaLink);",
"return \$this->hasMany($className1::className(), $link)->viaTable('{" . $this->generateTableName($table->name) . "}', $viaLink);",
$className1,
true,
];
......@@ -363,7 +363,7 @@ class Generator extends \yii\gii\Generator
$viaLink = $this->generateRelationLink([$table->primaryKey[1] => $fks[$table->primaryKey[1]][1]]);
$relationName = $this->generateRelationName($relations, $className1, $db->getTableSchema($table1), $table->primaryKey[0], true);
$relations[$className1][$relationName] = [
"return \$this->hasMany($className0::className(), $link)->viaTable('{$table->name}', $viaLink);",
"return \$this->hasMany($className0::className(), $link)->viaTable('{" . $this->generateTableName($table->name) . "}', $viaLink);",
$className0,
true,
];
......
......@@ -20,7 +20,7 @@ namespace <?= $generator->ns ?>;
use Yii;
/**
* This is the model class for table "<?= $tableName ?>".
* This is the model class for table "<?= $generator->generateTableName($tableName) ?>".
*
<?php foreach ($tableSchema->columns as $column): ?>
* @property <?= "{$column->phpType} \${$column->name}\n" ?>
......
......@@ -626,7 +626,7 @@ abstract class ActiveRecord extends BaseActiveRecord
if (isset($columns[$name])) {
if ($columns[$name]->isMva) {
$mvaValue = explode(',', $value);
$row[$name] = array_map(array($columns[$name], 'phpTypecast'), $mvaValue);
$row[$name] = array_map([$columns[$name], 'phpTypecast'], $mvaValue);
} else {
$row[$name] = $columns[$name]->phpTypecast($value);
}
......
......@@ -148,7 +148,6 @@ class Extension extends \Twig_Extension
if (isset($this->aliases[$className])) {
return $this->aliases[$className];
}
$resolvedClassName = null;
foreach ($this->namespaces as $namespace) {
$resolvedClassName = $namespace . '\\' . $className;
if (class_exists($resolvedClassName)) {
......
......@@ -264,7 +264,7 @@ class BaseYii
* will be loaded using the `@yii/bootstrap` alias which points to the directory where bootstrap extension
* files are installed and all classes from other `yii` namespaces will be loaded from the yii framework directory.
*
* Also the [guide section on autoloading][guide-concept-autoloading].
* Also the [guide section on autoloading](guide:concept-autoloading).
*
* @param string $className the fully qualified class name without a leading backslash "\"
* @throws UnknownClassException if the class does not exist in the class file
......
......@@ -48,6 +48,7 @@ Yii Framework 2 Change Log
- Bug #3681: Fixed problem with AR::findOne() when a default scope joins another table so that PK name becomes ambigous (cebe)
- Bug #3715: Fixed the bug that using a custom pager/sorter with `GridView` may generate two different pagers/sorters if the layout configures two pagers/sorters (qiangxue)
- Bug #3716: `DynamicModel::validateData()` does not call `validate()` if the `$rules` parameter is empty (qiangxue)
- Bug #3738: ActiveField custom error selector not functioning (qiangxue)
- Bug #3751: Fixed postgreSQL schema data for enum values, do not add values if there are none (makroxyz)
- Bug #3752: `QueryBuilder::batchInsert()` does not typecast input values (qiangxue)
- Bug #3756: Fix number formatting error for `\yii\base\Formatter` by converting strings to float (kartik-v)
......@@ -89,6 +90,10 @@ Yii Framework 2 Change Log
- Bug #4813: Fixed MSSQL schema that was getting incorrect info about constraints (samdark, SerjRamone, o-rey)
- Bug #4880: Return value of yii\web\Request::getPrefferedLanguage() was a normalized value instead of a valid language value from the input array (cebe)
- Bug #4920: `yii\filters\auth\CompositeAuth` should not trigger error as long as one of the methods succeeds (qiangxue)
- Bug #4938: When `yii\db\ActiveQuery` is used to build sub-queries, its WHERE clause is not correctly generated (qiangxue)
- Bug #4954: MSSQL column comments are not retrieved correctly (SerjRamone)
- Bug #4970: `joinWith()` called by a relation was ignored by `yii\db\ActiveQuery` (stepanselyuk)
- Bug #5001: `yii\rest\CreateAction`, `yii\rest\UpdateAction` and `yii\rest\DeleteAction` should throw 500 error if the model operation returns false without validation errors (qiangxue)
- Bug: Fixed inconsistent return of `\yii\console\Application::runAction()` (samdark)
- Bug: URL encoding for the route parameter added to `\yii\web\UrlManager` (klimov-paul)
- Bug: Fixed the bug that requesting protected or private action methods would cause 500 error instead of 404 (qiangxue)
......@@ -121,6 +126,7 @@ Yii Framework 2 Change Log
- Enh #3222: Added `useTablePrefix` option to the model generator for Gii (horizons2)
- Enh #3230: Added `yii\filters\AccessControl::user` to support access control with different actors (qiangxue)
- Enh #3232: Added `export()` and `exportAsString()` methods to `yii\helpers\BaseVarDumper` (klimov-paul)
- Enh #3240: Added support for assigning an anonymous function to `yii\widgets\ActiveForm::fieldConfig` (qiangxue)
- Enh #3244: Allow logging complex data such as arrays and object via the log system (cebe)
- Enh #3252: Added support for case insensitive matching using ILIKE to PostgreSQL QueryBuilder (cebe)
- Enh #3280: Support dynamically attaching anonymous behaviors (qiangxue)
......@@ -131,6 +137,7 @@ Yii Framework 2 Change Log
- Enh #3380: Allow `value` in `defaultValueValidator` to be a closure (Alex-Code)
- Enh #3384: Added callback-style transactions (leandrogehlen, Ragazzo, samdark)
- Enh #3399, #3241: Added support for MS SQL Server older than 2012 (fourteenmeister, samdark)
- Enh #3410: yii.activeForm.js now supports adding/removing fields dynamically (qiangxue)
- Enh #3459: Added logging of errors, which may occur at `yii\caching\FileCache::gc()` (klimov-paul)
- Enh #3472: Added configurable option to encode spaces in dropDownLists and listBoxes (kartik-v)
- Enh #3518: `yii\helpers\Html::encode()` now replaces invalid code sequences with "�" (DaSourcerer)
......@@ -198,6 +205,7 @@ Yii Framework 2 Change Log
- Enh #4062: Added 'caseSensitive' option to `yii\helpers\BaseFileHelper::findFiles()` (klimov-paul)
- Enh #4691: Encoding on `ActiveForm` and `ActiveField` validation errors is now configurable (Alex-Code)
- Enh #4740: Added `yii\web\Session::addFlash()` (restyler)
- Enh #4897: Added `yii\helpers\FileHelper::mimeMagicFile` (qiangxue)
- Enh: Added support for using sub-queries when building a DB query with `IN` condition (qiangxue)
- Enh: Supported adding a new response formatter without the need to reconfigure existing formatters (qiangxue)
- Enh: Added `yii\web\UrlManager::addRules()` to simplify adding new URL rules (qiangxue)
......@@ -214,12 +222,18 @@ Yii Framework 2 Change Log
- Enh: ListView now uses the widget ID in the base tag, consistent to gridview (cebe)
- Enh: Added `yii\web\Response::enableCsrfCookie` to support storing CSRF tokens in session (qiangxue)
- Chg #2287: Split `yii\db\ColumnSchema::typecast()` into two methods `phpTypecast()` and `dbTypecast()` to allow specifying PDO type explicitly (cebe)
- Chg #2359: Refactored formatter class. One class with or without intl extension and PHP format pattern as standard (Erik_r, cebe)
- `yii\base\Formatter` functionality has been merged into `yii\i18n\Formatter`
- removed the `yii\base\Formatter` class
- Chg #2380: `yii\widgets\ActiveForm` will register validation js even if there are not fields inside (qiangxue)
- Chg #2898: `yii\console\controllers\AssetController` is now using hashes instead of timestamps (samdark)
- Chg #2913: RBAC `DbManager` is now initialized via migration (samdark)
- Chg #2914: `ActiveForm::fieldConfig` will be merged recursively with the `$options` parameter in `ActiveForm::field()` (qiangxue)
- Chg #3036: Upgraded Twitter Bootstrap to 3.1.x (qiangxue)
- Chg #3175: InvalidCallException, InvalidParamException, UnknownMethodException are now extended from SPL BadMethodCallException (samdark)
- Chg #3358: Removed automatic CSRF meta tag generation by `View`. Added `Html::csrfMetaTags()` and its call to main layout files (qiangxue)
- Chg #3383: Added `$type` parameter to `IdentityInterface::findIdentityByAccessToken()` (qiangxue)
- Chg #3511: Dropped `yii.allowAction()` and modified `yii.confirm()` in `yii.js` to support callbacks (tanakahisateru)
- Chg #3531: \yii\grid\GridView now allows any character (except ":") in the attribute part of the shorthand syntax for columns (rawtaz)
- Chg #3544: Added `$key` as a parameter to the callable specified via `yii\grid\DataColumn::value` (mdmunir)
- Chg #3611: Query caching is refactored. (qiangxue)
......@@ -252,6 +266,9 @@ Yii Framework 2 Change Log
- Chg #4591: `yii\helpers\Url::to()` will no longer prefix relative URLs with the base URL (qiangxue)
- Chg #4595: `yii\widgets\LinkPager`'s `nextPageLabel`, `prevPageLabel`, `firstPageLabel`, `lastPageLabel` are now taking `false` instead of `null` for "no label" (samdark)
- Chg #4911: Changed callback signature used in `yii\base\ArrayableTrait::fields()` from `function ($field, $model) {` to `function ($model, $field) {` (samdark)
- Chg #4955: Replaced callbacks with events for `ActiveForm` (qiangxue)
- Removed `beforeValidate()`, `beforeValidateAll()`, `afterValidate()`, `afterValidateAll()`, `ajaxBeforeSend()` and `ajaxComplete()` from `ActiveForm`.
- Added `beforeValidate`, `afterValidate`, `beforeSubmit`, `ajaxBeforeSend` and `ajaxComplete` events to `yii.activeForm`.
- Chg: Replaced `clearAll()` and `clearAllAssignments()` in `yii\rbac\ManagerInterface` with `removeAll()`, `removeAllRoles()`, `removeAllPermissions()`, `removeAllRules()` and `removeAllAssignments()` (qiangxue)
- Chg: Added `$user` as the first parameter of `yii\rbac\Rule::execute()` (qiangxue)
- Chg: `yii\grid\DataColumn::getDataCellValue()` visibility is now `public` to allow accessing the value from a GridView directly (cebe)
......@@ -265,6 +282,7 @@ Yii Framework 2 Change Log
- Chg: When an ID is found to be in both `Application::controllerMap` and `Application::modules`, the former will take precedence (qiangxue)
- New #3911: Added `yii\behaviors\SluggableBehavior` that fills the specified model attribute with the transliterated and adjusted version to use in URLs (creocoder)
- New #4193: Added `yii\filters\Cors` CORS filter to allow Cross Origin Resource Sharing (pgaultier)
- New #4945: Added `yii\test\ArrayFixture` (Ragazzo)
- New: Added `yii\base\InvalidValueException` (qiangxue)
- New: Added `yii\caching\ArrayCache` (cebe)
......
......@@ -213,3 +213,50 @@ new ones save the following code as `convert.php` that should be placed in the s
* `Html::radio()`, `Html::checkbox()`, `Html::radioList()`, `Html::checkboxList()` no longer generate the container
tag around each radio/checkbox when you specify labels for them. You should manually render such container tags,
or set the `item` option for `Html::radioList()`, `Html::checkboxList()` to generate the container tags.
* The formatter class has been refactored to have only one class regardless whether PHP intl extension is installed or not.
Functionality of `yii\base\Formatter` has been merged into `yii\i18n\Formatter` and `yii\base\Formatter` has been
removed so you have to replace all usage of `yii\base\Formatter` with `yii\i18n\Formatter` in your code.
Also the API of the Formatter class has changed in many ways.
The signature of the following Methods has changed:
- `asDate`
- `asTime`
- `asDateTime`
- `asSize` has been split up into `asSize` and `asShortSize`
- `asCurrency`
- `asDecimal`
- `asPercent`
- `asScientific`
The following methods have been removed, this also means that the corresponding format which may be used by a
GridView or DetailView is not available anymore:
- `asNumber`
- `asDouble`
Also due to these changes some formatting defaults have changes so you have to check all your GridView and DetailView
configuration and make sure the formatting is displayed correctly.
The configuration for `asSize()` has changed. It now uses the configuration for the number formatting from intl
and only the base is configured using `$sizeFormatBase`.
The specification of the date and time formats is now using the ICU pattern format even if PHP intl extension is not installed.
You can prefix a date format with `php:` to use the old format of the PHP `date()`-function.
* `beforeValidate()`, `beforeValidateAll()`, `afterValidate()`, `afterValidateAll()`, `ajaxBeforeSend()` and `ajaxComplete()`
are removed from `ActiveForm`. The same functionality is now achieved via JavaScript event mechanism. For example,
if you want to do something before performing validation on the client side, you can write the following
JavaScript code:
```js
$('#myform').on('beforeValidate', function (event, messages, deferreds, attribute) {
if (attribute === undefined) {
// the event is triggered when submitting the form
} elseif (attribute.id === 'something') {
// the event is triggered before validating "something"
}
// if you want to cancel the validation, return a boolean false.
});
```
......@@ -98,23 +98,15 @@ yii = (function ($) {
* The default implementation simply displays a js confirmation dialog.
* You may override this by setting `yii.confirm`.
* @param message the confirmation message.
* @return boolean whether the user confirms with the message in the dialog
* @param ok a callback to be called when the user confirms the message
* @param cancel a callback to be called when the user cancels the confirmation
*/
confirm: function (message) {
return confirm(message);
},
/**
* Returns a value indicating whether to allow executing the action defined for the specified element.
* This method recognizes the `data-confirm` attribute of the element and uses it
* as the message in a confirmation dialog. The method will return true if this special attribute
* is not defined or if the user confirms the message.
* @param $e the jQuery representation of the element
* @return boolean whether to allow executing the action defined for the specified element.
*/
allowAction: function ($e) {
var message = $e.data('confirm');
return message === undefined || pub.confirm(message);
confirm: function (message, ok, cancel) {
if (confirm(message)) {
!ok || ok();
} else {
!cancel || cancel();
}
},
/**
......@@ -126,15 +118,14 @@ yii = (function ($) {
* For other elements, either the containing form action or the current page URL will be used
* as the form action URL.
*
* If the `data-method` attribute is not defined, the default element action will be performed.
* If the `data-method` attribute is not defined, nothing will be done.
*
* @param $e the jQuery representation of the element
* @return boolean whether to execute the default action for the element.
*/
handleAction: function ($e) {
var method = $e.data('method');
if (method === undefined) {
return true;
return;
}
var $form = $e.closest('form');
......@@ -178,8 +169,6 @@ yii = (function ($) {
if (newForm) {
$form.remove();
}
return false;
},
getQueryParams: function (url) {
......@@ -237,28 +226,27 @@ yii = (function ($) {
}
function initDataMethods() {
var $document = $(document);
// handle data-confirm and data-method for clickable elements
$document.on('click.yii', pub.clickableSelector, function (event) {
var handler = function (event) {
var $this = $(this);
if (pub.allowAction($this)) {
return pub.handleAction($this);
} else {
event.stopImmediatePropagation();
return false;
// data-confirm requires data-method
if ($this.data('method') === undefined) {
return true;
}
});
// handle data-confirm and data-method for changeable elements
$document.on('change.yii', pub.changeableSelector, function (event) {
var $this = $(this);
if (pub.allowAction($this)) {
return pub.handleAction($this);
var message = $this.data('confirm');
if (message !== undefined) {
pub.confirm(message, function () {
pub.handleAction($this);
});
} else {
event.stopImmediatePropagation();
return false;
pub.handleAction($this);
}
});
event.stopImmediatePropagation();
return false;
};
// handle data-confirm and data-method for clickable and changeable elements
$(document).on('click.yii', pub.clickableSelector, handler)
.on('change.yii', pub.changeableSelector, handler);
}
function initScriptFilter() {
......
......@@ -22,7 +22,7 @@ use Yii;
* @property \yii\db\Connection $db The database connection. This property is read-only.
* @property \yii\web\ErrorHandler|\yii\console\ErrorHandler $errorHandler The error handler application
* component. This property is read-only.
* @property \yii\base\Formatter $formatter The formatter application component. This property is read-only.
* @property \yii\i18n\Formatter $formatter The formatter application component. This property is read-only.
* @property \yii\i18n\I18N $i18n The internationalization application component. This property is read-only.
* @property \yii\log\Dispatcher $log The log dispatcher application component. This property is read-only.
* @property \yii\mail\MailerInterface $mailer The mailer application component. This property is read-only.
......@@ -87,7 +87,7 @@ abstract class Application extends Module
* This namespace will be used to load controller classes by prepending it to the controller class name.
* The default namespace is `app\controllers`.
*
* Please refer to the [guide about class autoloading][guide-concept-autoloading] for more details.
* Please refer to the [guide about class autoloading](guide:concept-autoloading.md) for more details.
*/
public $controllerNamespace = 'app\\controllers';
/**
......@@ -514,7 +514,7 @@ abstract class Application extends Module
/**
* Returns the formatter component.
* @return \yii\base\Formatter the formatter application component.
* @return \yii\i18n\Formatter the formatter application component.
*/
public function getFormatter()
{
......@@ -612,7 +612,7 @@ abstract class Application extends Module
return [
'log' => ['class' => 'yii\log\Dispatcher'],
'view' => ['class' => 'yii\web\View'],
'formatter' => ['class' => 'yii\base\Formatter'],
'formatter' => ['class' => 'yii\i18n\Formatter'],
'i18n' => ['class' => 'yii\i18n\I18N'],
'mailer' => ['class' => 'yii\swiftmailer\Mailer'],
'urlManager' => ['class' => 'yii\web\UrlManager'],
......
......@@ -63,7 +63,7 @@ trait ArrayableTrait
* information. For example, depending on the privilege of the current application user,
* you may return different sets of visible fields or filter out some fields.
*
* The default implementation of this method returns the public object member variables.
* The default implementation of this method returns the public object member variables indexed by themselves.
*
* @return array the list of field names or field definitions.
* @see toArray()
......@@ -71,7 +71,6 @@ trait ArrayableTrait
public function fields()
{
$fields = array_keys(Yii::getObjectVars($this));
return array_combine($fields, $fields);
}
......
......@@ -94,7 +94,7 @@ class Module extends ServiceLocator
* For example, if the namespace of this module is "foo\bar", then the default
* controller namespace would be "foo\bar\controllers".
*
* See also the [guide section on autoloading][guide-concept-autoloading] to learn more about
* See also the [guide section on autoloading](guide:concept-autoloading) to learn more about
* defining namespaces and how classes are loaded.
*/
public $controllerNamespace;
......
......@@ -28,7 +28,6 @@ return [
'yii\base\Event' => YII2_PATH . '/base/Event.php',
'yii\base\Exception' => YII2_PATH . '/base/Exception.php',
'yii\base\ExitException' => YII2_PATH . '/base/ExitException.php',
'yii\base\Formatter' => YII2_PATH . '/base/Formatter.php',
'yii\base\InlineAction' => YII2_PATH . '/base/InlineAction.php',
'yii\base\InvalidCallException' => YII2_PATH . '/base/InvalidCallException.php',
'yii\base\InvalidConfigException' => YII2_PATH . '/base/InvalidConfigException.php',
......
......@@ -345,6 +345,9 @@ class HelpController extends Controller
}
$doc = "$type (defaults to " . $defaultValue . ")";
} elseif (trim($type) !== '') {
if (strncmp($type, 'bool', 4) === 0) {
$type = 'boolean, 0 or 1';
}
$doc = $type;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment