Commit 8a3d8c94 by Alexander Makarov

Merge pull request #6395 from davidsonalencar/master

Update guides pt-BR [skip ci]
parents 1e179a13 7b4745c4
......@@ -74,14 +74,14 @@ Conceitos Chave
Trabalhando com Banco de Dados
------------------------------
* [Data Access Objects (DAO, Objeto de Acesso a Dados)](db-dao.md) - Estabelecendo uma conexão com o Banco de Dados, consultas básicas, transações e manipulação do esquema
* [Query Builder (Construtor de Consulta)](db-query-builder.md) - Consultando o banco de dados usando uma camada de abstração simples
* [Active Record](db-active-record.md) - Sobre o Active Record ORM, recuperando e manipulando registros e definindo relacionamentos
* [Migrations (Migrações)](db-migrations.md) - Aplica controle de versão para seus banco de dados em um ambiente de desenvolvimento em equipe
* [Data Access Objects (DAO, Objeto de Acesso a Dados)](db-dao.md)? Estabelecendo uma conexão com o Banco de Dados, consultas básicas, transações e manipulação do esquema
* [Query Builder (Construtor de Consulta)](db-query-builder.md)? Consultando o banco de dados usando uma camada de abstração simples
* [Active Record](db-active-record.md): Sobre o Active Record ORM, recuperando e manipulando registros e definindo relacionamentos
* [Migrations (Migrações)](db-migrations.md): Aplica controle de versão para seus banco de dados em um ambiente de desenvolvimento em equipe
* **TBD** [Sphinx](db-sphinx.md)
* **TBD** [Redis](db-redis.md)
* **TBD** [MongoDB](db-mongodb.md)
* **TBD** [ElasticSearch](db-elastic-search.md)
* **TBD** [ElasticSearch](db-elasticsearch.md)
Coletando Dados de Usuários
......@@ -96,7 +96,7 @@ Coletando Dados de Usuários
Exibindo Dados
---------------
* [Formatando Dados](output-formatting.md)
* [Formatando Dados](output-formatter.md)
* **TBD** [Paginação](output-pagination.md)
* **TBD** [Ordenação](output-sorting.md)
* [Data Providers (Provedores de Dados)](output-data-providers.md)
......@@ -125,7 +125,7 @@ Cache
* [Cache HTTP](caching-http.md)
Web Services com RESTful
Web Services RESTful
------------------------
* [Introdução](rest-quick-start.md)
......@@ -151,7 +151,7 @@ Testes
------
* [Visão Geral](test-overview.md)
* [Configuração do ambiente de testes](test-endvironment-setup.md)
* [Configuração do ambiente de testes](test-environment-setup.md)
* [Testes Unitários](test-unit.md)
* [Testes Funcionais](test-functional.md)
* [Testes de Aceitação](test-acceptance.md)
......@@ -184,16 +184,16 @@ Widgets
* Menu: **TBD** link para a página de demonstração
* LinkPager: **TBD** link para a página de demonstração
* LinkSorter: **TBD** link para a página de demonstração
* [Widgets do Bootstrap](bootstrap-widgets.md)
* [Widgets do Jquery UI](jui-widgets.md)
* [Widgets do Bootstrap](widget-bootstrap.md)
* [Widgets do Jquery UI](widget-jui.md)
Helpers
-------
* [Visão Geral](helper-overview.md)
* **TBD** [ArrayHelper](helper-array.md)
* **TBD** [Html](helper-html.md)
* **TBD** [Url](helper-url.md)
* [ArrayHelper](helper-array.md)
* [Html](helper-html.md)
* [Url](helper-url.md)
* **TBD** [Segurança](helper-security.md)
......@@ -6,8 +6,24 @@ ou baixando um arquivo compactado. O primeiro modo é o preferido, já que permi
que você instale novas [extensões](structure-extensions.md) ou atualize o
Yii simplesmente executando um único comando.
> Note: Ao contrário do Yii 1, as instalações padrão do Yii 2 resultam em
tanto o framework quanto um esqueleto de aplicação sendo baixados e instalados.
A instalação do Yii padrão resulta no download e instalação tanto do framework
quanto de um template de aplicação.
Um template de aplicação é uma aplicação do Yii implementando algumas recursos básicos,
como a autenticação, o formulário de contato, etc.
Este código é organizado de uma forma recomendada. No entanto, ele pode servir
como ponto de partida para seus projetos.
Nesta e nas próximas seções, iremos descrever como instalar o *Template Básico de
Aplicação* do Yii e como implementar novas funcionalidades em cima deste template.
O Yii também fornece um outro template chamado de [Template Avançado de Aplicação](tutorial-advanced-app.md) que é melhor usado em uma equipe de desenvolvimento que desenvolvem
aplicações de multiplas camadas.
> Informação: O Template Básico de Aplicação é adequado para o desenvolvimento de
cerca de 90% das aplicações Web. Este template difere do Template Avançado de
Aplicação principalmente na forma de como o seu código é organizado. Se você é
novo no Yii, recomendamos fortemente em escolher o Template Básico de Aplicação
pela sua simplicidade além de ter funcionalidades o suficiente.
If you are new to Yii, we strongly recommend you stick to the Basic Application Template for its simplicity yet sufficient functionalities.
Instalando via Composer <a name="installing-via-composer"></a>
......@@ -39,15 +55,12 @@ o que permite gerenciar dependências via bower e npm package por meio do Compos
Você apenas precisa rodar este comando uma vez. O segundo comando instala o Yii
em um diretório chamado `basic`. Você pode escolher um diretório diferente se quiser.
> Nota: Durante a instalação do Yii pode acontecer que o Composer peça suas
> credenciais de login do Github por ultrapassar taxa limite (rate-limit) da API do Github.
> Isso é normal pois o Composer necessita obter muitas informações de todos os
> pacotes no Github.
> Logando no Github incrementa a taxa limite (rate-limit) da API para que o Composer
> possa continuar o seu trabalho. Para mais detalhes, por favor consulte a
> [documentação do Composer](https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens).
> Observação: Durante a instalação, o Composer pode pedir suas credenciais de login
> do Github. Isto é normal, pelo fato do Composer precisar obter a taxa limite
> (rate-limit) da API para recuperar as informações de dependência de pacotes do
> Github. Para mais detalhes, consulte a [documentação do Composer](https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens).
> Tip: Se você quiser instalar a última versão de desenvolvimento do Yii, você
> Dica: Se você quiser instalar a última versão de desenvolvimento do Yii, você
> pode usar o seguinte comando, que adiciona uma [opção de estabilidade](https://getcomposer.org/doc/04-schema.md#minimum-stability):
>
> composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic
......@@ -78,8 +91,9 @@ Outras Opções de Instalação <a name="other-installation-options"></a>
As instruções de instalação acima mostram como instalar o Yii, que também cria
uma aplicação Web básica que funciona imediatamente sem qualquer configuração ou
modificação (*out of the box*). Este método é um bom ponto de início para projetos
pequenos ou para quando você começar a aprender o Yii.
modificação (*out of the box*).
Esta abordagem é um bom ponto de partida para a maioria dos projetos, seja ele
pequeno ou grande. É especialmente adequado se você acabou de começar a aprender Yii.
No entanto, existem outras opções de instalação disponíveis:
......
Controllers (Controladores)
===========
Os controllers (controladores) fazem parte da arquitetura [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller).
São objetos de classes que estendem de [[yii\base\Controller]] e são responsáveis
pelo processamento das requisições e por gerar respostas. Em particular, após
assumir o controle de [applications](structure-applications.md), controllers
analisarão os dados de entradas obtidos pela requisição, passarão estes dados
para os [models](structure-models.md) (modelos), incluirão os resultados dos models
(modelos) nas [views](structure-views.md) (visões) e finalmente gerarão as respostas
de saída.
## Actions (Ações) <a name="actions"></a>
Os controllers são compostos por unidades básicas chamadas *ações* que podem ser
tratados pelos usuários finais a fim de realizar a sua execução.
No exemplo a seguir mostra um controller `post` com duas ações: `view` e `create`:
```php
namespace app\controllers;
use Yii;
use app\models\Post;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
class PostController extends Controller
{
public function actionView($id)
{
$model = Post::findOne($id);
if ($model === null) {
throw new NotFoundHttpException;
}
return $this->render('view', [
'model' => $model,
]);
}
public function actionCreate()
{
$model = new Post;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
}
```
Na ação `view` (definido pelo método `actionView()`), o primeiro código carrega o
[model](structure-models.md) conforme o ID solicitado; Se o model for devidamente
carregado, a ação irá exibi-lo utilizado a [view](structure-views.md) chamada de `view`.
Caso contrário, a ação lançará uma exceção.
Na ação `create` (definido pelo método `actionCreate()`), o código é parecido.
Primeiro ele tenta popular o [model](structure-models.md) usando os dados da requisição
em seguida os salva. Se ambos forem bem sucedidos, a ação redirecionará o navegador
para a ação `view` com o novo ID criado pelo model. Caso contrário, a ação exibirá
a view `create` na qual os usuário poderão fornecer os dados necessários.
## Routes (Rotas) <a name="routes"></a>
Os usuários finais abordarão as ações por meio de *rotas*. Uma rota é uma string composta
pelas seguintes partes:
* um ID do módulo: serve apenas se o controller pertencer a um [módulo](structure-modules.md) que não seja da aplicação;
* um ID do controller: uma string que identifica exclusivamente o controller dentre todos os controllers da mesma aplicação (ou do mesmo módulo, caso o controller pertença a um módulo);
* um ID da ação: uma string que identifica exclusivamente uma ação dentre todas as ações de um mesmo controller.
As rotas seguem o seguinte formato:
```
IDdoController/IDdoAction
```
ou o seguinte formato se o controller estiver em um módulo:
```php
IDdoModule/IDdoController/IDdoAction
```
Portanto, se um usuário fizer uma requisição com a URL `http://hostname/index.php?r=site/index`,
a ação `index` do controller `site` será executada. Para mais detalhes sobre como
as ações são resolvidas pelas rotas, por favor consulte a seção [Roteamento e Criação de URL](runtime-routing.md).
## Criando Controllers <a name="creating-controllers"></a>
Em [[yii\web\Application|aplicações Web]], os controllers devem estender de [[yii\web\Controller]]
ou de suas classes filhas. De forma semelhante, em [[yii\console\Application|aplicaçoes console]],
os controllers devem estender de [[yii\console\Controller]] ou de suas classes filhos. O código a seguir define um controller `site`:
```php
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
}
```
### IDs dos Controllers <a name="controller-ids"></a>
Normalmente, um controller é projetado para tratar as requisições relativos a
um determinado tipo de recurso. Por esta razão, os IDs dos controllers geralmente
são substantivos que referenciam-se ao tipo de recurso que será tratado.
Por exemplo, você pode usar o `article` como o ID do um controller para tratar
dados de artigos.
Por padrão, os IDs dos controllers devem conter apenas esses caracteres:
letras inglesas em caixa baixa, números, underscores (underline), traços e barras.
Por exemplo, `article` e `post-comment` são ambos IDs de controllers válidos,
enquanto `article?`, `PostComment`, `admin\post` não são.
Um ID de controller também pode conter um prefixo para o subdiretório. Por exemplo,
`admin/article` representa um controller `article` em um subdiretório `admin` sob
o [[yii\base\Application::controllerNamespace|namespace do controller]]
Os caracteres válidos para os prefixos de subdiretórios incluem: letras inglesas
em caixa alto ou caixa baixa, números, underscores (underline) e barras, onde as
barras são usadas para separar os níveis dos subdiretórios (por exemplo, `panels/admin`).
### Nomenclatura da Classe do Controller <a name="controller-class-naming"></a>
Os nomes da classes dos controllers podem ser derivadas dos IDs dos controllers
de acordo com as seguintes regras:
* Colocar em caixa alta a primeira letra de cada palavra separadas por traço.
Observe que se o ID do controller possuir barras, a regra é aplicada apenas na
parte após a última barra no ID.
* Remover os traços e substituir todas as barras por barras invertidas.
* Adicionar `Controller` como sufixo.
* E preceder ao [[yii\base\Application::controllerNamespace|namespace controller]].
Segue alguns exemplos, assumindo que o [[yii\base\Application::controllerNamespace|namespace do controller]]
tenha por padrão o valor `app\controllers`:
* `article` deriva-se de `app\controllers\ArticleController`;
* `post-comment` deriva-se de `app\controllers\PostCommentController`;
* `admin/post-comment` deriva-se de `app\controllers\admin\PostCommentController`;
* `adminPanels/post-comment` deriva-se de `app\controllers\adminPanels\PostCommentController`.
As classes dos controllers devem ser [autoloadable](concept-autoloading.md).
Por esta razão, nos exemplos anteriores, o controller `article` deve ser salvo
no arquivo cuja [alias](concept-aliases.md) é `@app/controllers/ArticleController.php`;
enquanto o controller `admin/post2-comment` deve ser salvo no `@app/controllers/admin/Post2CommentController.php`.
> Informação: No último exemplo `admin/post2-comment`, mostra como você pode colocar
um controller em um subdiretório do [[yii\base\Application::controllerNamespace|namespace controller]]. Isto é útil quando você quiser organizar seus controllers em diversas
categorias e não quiser usar [módulos](structure-modules.md).
### Mapeando Controllers <a name="controller-map"></a>
Você pode configurar um [[yii\base\Application::controllerMap|mapeamento de controllers]] para superar as barreiras impostas pelos IDs de controllers e pelos nomes de classes
descritos acima. Isto é útil principalmente quando quiser esconder alguns controllers
de terceiros na qual você não tem controle sobre seus nomes de classes.
Você pode configurar o [[yii\base\Application::controllerMap|mapeamento de controllers]]
na [configuração da aplicação](structure-applications.md#application-configurations) como o seguinte exemplo:
```php
[
'controllerMap' => [
// declara o controller "account" usando um nome de classe
'account' => 'app\controllers\UserController',
// declara o controller "article" usando uma configuração em array
'article' => [
'class' => 'app\controllers\PostController',
'enableCsrfValidation' => false,
],
],
]
```
### Controller Padrão <a name="default-controller"></a>
Cada aplicação tem um controller padrão que é especificado pela propriedade [[yii\base\Application::defaultRoute]].
Quando uma requisição não especificar uma [rota](#id-da-rota), será utilizada a
rota especificada pela propriedade.
Para as [[yii\web\Application|aplicações Web]], este valor é `'site'`, enquanto
para as [[yii\console\Application|aplicações console]] é `help`. Portanto, se uma
URL `http://hostname/index.php` for usada, significa que o controller `site` será
usado nesta requisição.
Você pode alterar o controller padrão como a seguinte [configuração da aplicação](structure-applications.md#application-configurations):
```php
[
'defaultRoute' => 'main',
]
```
## Criando Ações <a name="creating-actions"></a>
Criar ações pode ser tão simples como a definição dos chamados *métodos de ação*
em uma classe controller. Um método de ação é um método *público* cujo nome inicia
com a palavra `action`. O valor de retorno representa os dados de resposta a serem
enviados aos usuário finais. O código a seguir define duas ações, `index` e `hello-world`:
```php
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public function actionIndex()
{
return $this->render('index');
}
public function actionHelloWorld()
{
return 'Hello World';
}
}
```
### IDs das Ações <a name="action-ids"></a>
Uma ação muitas vezes é projetada para realizar uma manipulação em particular sobre
um recurso. Por esta razão, os IDs das ações geralmente são verbos, tais como `view`, `update`, etc.
Por padrão, os IDs das ações devem conter apenas esses caracteres: letras inglesas
em caixa baixa, números, underscores (underline) e traços. Os traços em um ID da
ação são usados para separar palavras. Por exemplo, `view`, `update2`, `comment-post`
todos são IDs válidos, enquanto `view?`, `Update` não são.
Você pode criar ações de duas maneiras: ações inline (em sequência) e
ações standalone (autônomas). Uma ação inline é definida pelo método
de uma classe controller, enquanto uma ação standalone é uma classe que estende de
[[yii\base\Action]] ou de suas classes filhas. As ações inline exigem menos esforço
para serem criadas e muitas vezes as preferidas quando não se tem a intenção de
reutilizar estas ações. Ações standalone, por outro lado, são criados principalmente
para serem utilizados em diferentes controllers ou para serem distribuídos como
[extensions](structure-extensions.md).
### Ações Inline <a name="inline-actions"></a>
As ações inline referem-se a os chamados métodos de ação, que foram descritos anteriormente.
Os nomes dos métodos de ações são derivadas dos IDs das ações de acordo com os
seguintes critérios:
* Colocar em caixa alta a primeira letra de cada palavra do ID da ação;
* Remover os traços;
* Adicionar o prefixo `action`.
Por exemplo, `index` torna-se `actionIndex` e `hello-world` torna-se `actionHelloWorld`.
> Observação: Os nomes dos métodos de ações são *case-sensitive*. Se você tiver
um método chamado `ActionIndex`, não será considerado como um método de ação e
como resultado, o pedido para a ação `index` lançará uma exceção. Observe também
que os métodos de ações devem ser públicas. Um método privado ou protegido NÃO
será definido como ação inline.
As ações inline normalmente são as mais utilizadas pois demandam pouco esforço
para serem criadas. No entanto, se você deseja reutilizar algumas ações em diferentes
lugares ou se deseja distribuir uma ação, deve considerar defini-la como uma *ação standalone*.
### Ações Standalone <a name="standalone-actions"></a>
Ações standalone são definidas por classes de ações que estendem de [[yii\base\Action]]
ou de suas classes filhas.
Por example, nas versões do Yii, existe a [[yii\web\ViewAction]] e a [[yii\web\ErrorAction]], ambas são ações standalone.
Para usar uma ação standalone, você deve *mapear as ações* sobrescrevendo o método
[[yii\base\Controller::actions()]] em suas classes controllers como o seguinte:
```php
public function actions()
{
return [
// declara a ação "error" usando um nome de classe
'error' => 'yii\web\ErrorAction',
// declara a ação "view" usando uma configuração em array
'view' => [
'class' => 'yii\web\ViewAction',
'viewPrefix' => '',
],
];
}
```
Como pode ver, o método `actions()` deve retornar um array cujas chaves são os IDs
das ações e os valores correspondentes ao nome da classe da ação ou [configurações](concept-configurations.md). Ao contrário das ações inline, os IDs das ações standalone
podem conter caracteres arbitrários desde que sejam mapeados no método `actions()`.
Para criar uma classe de ação standalone, você deve estender de [[yii\base\Action]] ou de duas classes filhas e implementar um método público chamado `run()`. A regra para o método `run()`
é semelhante ao de um método de ação. Por exemplo,
```php
<?php
namespace app\components;
use yii\base\Action;
class HelloWorldAction extends Action
{
public function run()
{
return "Hello World";
}
}
```
### Resultados da Ação <a name="action-results"></a>
O valor de retorno do método de ação ou do método `run()` de uma ação standalone
são importantes. Eles representam o resultado da ação correspondente.
O valor de retorno pode ser um objeto de [resposta](runtime-responses.md) que
que enviará como resposta aos usuários finais.
* Para [[yii\web\Application|aplicações Web]], o valor de retorno também poder
ser algum dado arbitrário que será atribuído à propriedade [[yii\web\Response::data]]
e ainda ser convertido em uma string para representar o corpo da resposta.
* Para [[yii\console\Application|aplicações console]], o valor de retorno também
poder ser um inteiro representando o [[yii\console\Response::exitStatus|exit status]]
(status de saída) da execução do comando.
Nos exemplos acima, todos os resultados são strings que serão tratados como o
corpo das respostas para serem enviados aos usuários finais. No exemplo a seguir,
mostra como uma ação pode redirecionar o navegador do usuário para uma nova URL
retornando um objeto de resposta (o método [[yii\web\Controller::redirect()|redirect()]]
retorna um objeto de resposta):
```php
public function actionForward()
{
// redireciona o navegador do usuário para http://example.com
return $this->redirect('http://example.com');
}
```
### Parâmetros da Ação <a name="action-parameters"></a>
Os métodos de ações para as ações inline e os métodos `run()` para as ações
standalone podem receber parâmetros, chamados *parâmetros da ação*.
Seus valores são obtidos a partir das requisições. Para
[[yii\web\Application|aplicações Web]], o valor de cada parâmetro da ação são
obtidos pelo `$_GET` usando o nome do parâmetro como chave; para
[[yii\console\Application|aplicações console]], eles correspondem aos argumentos
da linha de comando.
No exemplo a seguir, a ação `view` (uma ação inline) possui dois parâmetros declarados:
`$id` e `$version`.
```php
namespace app\controllers;
use yii\web\Controller;
class PostController extends Controller
{
public function actionView($id, $version = null)
{
// ...
}
}
```
A seguir, os parâmetros da ação serão populados em diferentes requisições:
* `http://hostname/index.php?r=post/view&id=123`: o parâmetro `$id` receberá
o valor `'123'`, enquanto o `$version` continuará com o valor nulo porque não
existe o parâmetro `version` na URL.
* `http://hostname/index.php?r=post/view&id=123&version=2`: os parâmetros `$id`
e `$version` serão receberão os valores `'123'` e `'2'`, respectivamente.
* `http://hostname/index.php?r=post/view`: uma exceção [[yii\web\BadRequestHttpException]]
será lançada porque o parâmetro obrigatório `$id` não foi informado na requisição.
* `http://hostname/index.php?r=post/view&id[]=123`: uma exceção [[yii\web\BadRequestHttpException]]
será lançada porque o parâmetro `$id` foi informado com um valor array `['123']`
na qual não era esperado.
Se você quiser que um parâmetro da ação aceite valores arrays, deverá declara-lo
explicitamente com `array`, como mostro a seguir:
```php
public function actionView(array $id, $version = null)
{
// ...
}
```
Agora, se a requisição for `http://hostname/index.php?r=post/view&id[]=123`, o
parâmetro `$id` receberá o valor `['123']`. Se a requisição for
`http://hostname/index.php?r=post/view&id=123`, o parâmetro `$id` ainda receberá
um array como valor pois o valor escalar `'123'` será convertido automaticamente
em um array.
Os exemplo acima mostram, principalmente, como os parâmetros da ação trabalham em
aplicações Web. Para aplicações console, por favor, consulte a seção
[Comandos de Console](tutorial-console.md) para mais detalhes.
### Default Action <a name="default-action"></a>
Cada controller tem uma ação padrão especificado pela propriedade
[[yii\base\Controller::defaultAction]].
Quando uma [rota](#id-da-rota) contém apenas o ID do controller, implica que a
ação padrão do controller seja solicitada.
Por padrão, a ação padrão é definida como `index`. Se quiser alterar o valor padrão,
simplesmente sobrescreva esta propriedade na classe controller, como o seguinte:
```php
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public $defaultAction = 'home';
public function actionHome()
{
return $this->render('home');
}
}
```
## Ciclo de Vida do Controller <a name="controller-lifecycle"></a>
Ao processar uma requisição, a [aplicação](structure-applications.md) criará
um controller baseada na [rota](#routes) solicitada. O controller, então, se submeterá
ao seguinte ciclo de vida para concluir a requisição:
1. O método [[yii\base\Controller::init()]] é chamado após o controller ser criado e configurado.
2. O controller cria um objeto da ação baseada no ID da ação solicitada:
* Se o ID da ação não for especificado, o [[yii\base\Controller::defaultAction|ID da ação padrão]] será utilizada.
* Se o ID da ação for encontrada no [[yii\base\Controller::actions()|mapeamento das ações]], uma ação standalone será criada;
* Se o ID da ação for encontrada para corresponder a um método de ação, uma ação inline será criada;
* Caso contrário, uma exceção [[yii\base\InvalidRouteException]] será lançada.
3. De forma sequencial, o controller chama o método `beforeAction()` da aplicação, o módulo (se o controller pertencer a um módulo) e o controller.
* Se uma das chamadas retornar false, o restante dos métodos `beforeAction()` serão ignoradas e a execução da ação será cancelada.
* Por padrão, cada método `beforeAction()` desencadeia a execução de um evento chamado `beforeAction` na qual você pode associar a uma função (handler).
4. O controller executa a ação:
* Os parâmetros da ação serão analizados e populados a partir dos dados obtidos pela requisição;
5. De forma sequencial, o controller chama o método `afterAction()` do controller, o módulo (se o controller pertencer a um módulo) e a aplicação.
* Por padrão, cada método `afterAction()` desencadeia a execução de um evento chamado `afterAction` na qual você pode associar a uma função (handler).
6. A aplicação obterá o resultado da ação e irá associá-lo na [resposta](runtime-responses.md).
## Best Practices <a name="best-practices"></a>
Em uma aplicação bem projetada, frequentemente os controllers são bem pequenos na
qual cada ação possui poucas linhas de códigos.
Se o controller for um pouco complicado, geralmente indica que terá que refaze-lo
e passar algum código para outro classe.
Em resumo, os controllers:
* podem acessar os dados de uma [requisição](runtime-requests.md);
* podem chamar os métodos dos [models](structure-models.md) e outros componentes
de serviço com dados da requisição;
* podem usar as [views](structure-views.md) para compor as respostas;
* NÃO devem processar os dados da requisição - isto deve ser feito pelos [models](structure-models.md);
* devem evitar inserir códigos HTML ou outro código de apresentação - é melhor
que sejam feitos nas [views](structure-views.md).
Models (Modelos)
================
Os models (modelos) fazem parte da arquitetura [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller).
Eles representam os dados, as regras e a lógica de negócio.
Você pode criar uma classe model estendendo de [[yii\base\Model]] ou de seus filhos.
A classe base [[yii\base\Model]] suporta muitos recursos úteis:
* [Atributos](#attributes): representa os dados de negócio e podem ser acessados
normalmente como uma propriedade de objeto ou como um elemento de array;
* [Labels dos atributos](#attribute-labels): especifica os labels de exibição dos
atributos;
* [Atribuição em massa](#massive-assignment): suporta popular vários atributos em
uma única etapa;
* [Regras de validação](#validation-rules): garante que os dados de entrada sejam
baseadas nas regras de validação que foram declaradas;
* [Data Exporting](#data-exporting): permite que os dados de model a serem exportados
em array possuam formatos personalizados.
A classe `Model` também é a classe base para models mais avançados, como o [Active Record](db-active-record.md).
Por favor, consulte a documentação relevante para mais detalhes sobre estes models mais avançados.
> Informação: Você não é obrigado basear suas classe model em [[yii\base\Model]].
> No entanto, por existir muitos componentes do Yii construídos para suportar o
> [[yii\base\Model]], normalmente é a classe base preferível para um model.
## Atributos <a name="attributes"></a>
Os models representam dados de negócio por meio de *atributos*. Cada atributo é
uma propriedade publicamente acessível de um model. O método [[yii\base\Model::attributes()]]
especifica quais atributos de uma classe model possuirá.
Você pode acessar um atributo como fosse uma propriedade normal de um objeto:
```php
$model = new \app\models\ContactForm;
// "name" é um atributo de ContactForm
$model->name = 'example';
echo $model->name;
```
Você também pode acessar os atributos como elementos de um array, graças ao suporte
de [ArrayAccess](http://php.net/manual/en/class.arrayaccess.php) e
[ArrayIterator](http://php.net/manual/en/class.arrayiterator.php) pelo
[[yii\base\Model]]:
```php
$model = new \app\models\ContactForm;
// acessando atributos como elementos de array
$model['name'] = 'example';
echo $model['name'];
// iterando sobre os atributos
foreach ($model as $name => $value) {
echo "$name: $value\n";
}
```
### Definindo Atributos <a name="defining-attributes"></a>
Por padrão, se a classe model estender diretamente de [[yii\base\Model]], todas
as suas variáveis públicas e não estáticas serão atributos. Por exemplo, a classe
model `ContactForm` a seguir possui quatro atributos: `name`, `email`, `subject`
e `body`. O model `ContactForm` é usado para representar os dados de entrada obtidos
a partir de um formulário HTML.
```php
namespace app\models;
use yii\base\Model;
class ContactForm extends Model
{
public $name;
public $email;
public $subject;
public $body;
}
```
Você pode sobrescrever o método [[yii\base\Model::attributes()]] para definir
atributos de uma forma diferente. Este método deve retornar os nomes dos atributos
em um model. Por exemplo, o [[yii\db\ActiveRecord]] faz com que o método retorne
os nomes das colunas da tabela do banco de dados como nomes de atributos.
Observe que também poderá sobrescrever os métodos mágicos tais como `__get()` e
`__set()`, para que os atributos poderem ser acessados como propriedades normais
de objetos.
### Labels dos Atributos <a name="attribute-labels"></a>
Ao exibir valores ou obter dados de entrada dos atributos, muitas vezes é necessário
exibir alguns labels associados aos atributos. Por exemplo, dado um atributo chamado
`firstName`, você pode querer exibir um label `First Name` que é mais amigável
quando exibido aos usuários finais como em formulários e mensagens de erro.
Você pode obter o label de um atributo chamando o método [[yii\base\Model::getAttributeLabel()]].
Por exemplo,
```php
$model = new \app\models\ContactForm;
// displays "Name"
echo $model->getAttributeLabel('name');
```
Por padrão, os labels dos atributos automaticamente serão gerados com os nomes dos
atributos. Isto é feito pelo método [[yii\base\Model::generateAttributeLabel()]].
Ele transforma os nomes camel-case das variáveis em várias palavras, colocando em
caixa alta a primeira letra de cada palavra. Por exemplo, `username` torna-se
`Username`, enquanto `firstName` torna-se `First Name`.
Se você não quiser usar esta geração automática do labels, poderá sobrescrever o
método [[yii\base\Model::attributeLabels()]] declarando explicitamente os labels
dos atributos. Por exemplo,
```php
namespace app\models;
use yii\base\Model;
class ContactForm extends Model
{
public $name;
public $email;
public $subject;
public $body;
public function attributeLabels()
{
return [
'name' => 'Your name',
'email' => 'Your email address',
'subject' => 'Subject',
'body' => 'Content',
];
}
}
```
Para aplicações que suportam vários idiomas, você pode querer traduzir os labels
dos atributos. Isto também é feito no método [[yii\base\Model::attributeLabels()|attributeLabels()]],
conforme o exemplo a seguir:
```php
public function attributeLabels()
{
return [
'name' => \Yii::t('app', 'Your name'),
'email' => \Yii::t('app', 'Your email address'),
'subject' => \Yii::t('app', 'Subject'),
'body' => \Yii::t('app', 'Content'),
];
}
```
Você pode até definir condicionalmente os labels dos atributos. Por exemplo, baseado
no [cenário](#scenarios) que o model estiver utilizando, você pode retornar diferentes
labels para o mesmo atributo.
> Informação: Estritamente falando, os labels dos atributos fazem parte das
[views](structure-views.md) (visões). Mas ao declarar os labels em models (modelos),
frequentemente tornam-se mais convenientes e podem resultar um código mais limpo
e reutilizável.
## Cenários <a name="scenarios"></a>
Um model (modelo) pode ser usado em diferentes *cenários*. Por exemplo, um model
`User` pode ser usado para obter dados de entrada de login, mas também pode ser
usado com a finalidade de registrar o usuário. Em diferentes cenários, um model
pode usar diferentes regras e lógicas de negócio. Por exemplo, um atributo `email`
pode ser obrigatório durante o cadastro do usuário, mas não durante ao login.
Um model (modelo) usa a propriedade [[yii\base\Model::scenario]] para identificar
o cenário que está sendo usado.
Por padrão, um model (modelo) suporta apenas um único cenário chamado `default`.
O código a seguir mostra duas formas de definir o cenário de um model (modelo):
```php
// o cenário é definido pela propriedade
$model = new User;
$model->scenario = 'login';
// o cenário é definido por meio de configuração
$model = new User(['scenario' => 'login']);
```
Por padrão, os cenários suportados por um model (modelo) são determinados pelas
[regras de validação](#validation-rules) declaradas no próprio model (modelo).
No entanto, você pode personalizar este comportamento sobrescrevendo o método
[[yii\base\Model::scenarios()]], conforme o exemplo a seguir:
```php
namespace app\models;
use yii\db\ActiveRecord;
class User extends ActiveRecord
{
public function scenarios()
{
return [
'login' => ['username', 'password'],
'register' => ['username', 'email', 'password'],
];
}
}
```
> Informação: Nos exemplos anteriores, as classes model (model) são estendidas de
[[yii\db\ActiveRecord]] por usarem diversos cenários para auxiliarem as classes
[Active Record](db-active-record.md) classes.
O método `scenarios()` retorna um array cujas chaves são os nomes dos cenários e
os valores que correspondem aos *active attributes* (atributo ativo). Um atributo
ativo podem ser [atribuídos em massa](#massive-assignment) e é sujeito a
[validação](#validation-rules). No exemplo anterior, os atributos `username` e
`password` são ativos no cenário `login`; enquanto no cenário `register`, além
dos atribitos `username` e `password`, o atributo `email` passará a ser ativo.
A implementação padrão do método `scenarios()` retornará todos os cenários encontrados
nas regras de validação declaradas no método [[yii\base\Model::rules()]]. Ao
sobrescrever o método `scenarios()`, se quiser introduzir novos cenários, além
dos cenários padrão, poderá escrever um código conforme o exemplo a seguir:
```php
namespace app\models;
use yii\db\ActiveRecord;
class User extends ActiveRecord
{
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['login'] = ['username', 'password'];
$scenarios['register'] = ['username', 'email', 'password'];
return $scenarios;
}
}
```
O recurso de cenários são usados principalmente para [validação](#validation-rules)
e para [atribuição em massa](#massive-assignment).
Você pode, no entanto, usá-lo para outros fins. Por exemplo, você pode declarar
diferentes [labels para os atributos](#attribute-labels) baseados no cenário atual.
## Regras de Validação <a name="validation-rules"></a>
Quando os dados para um model (modelo) são recebidos de usuários finais, devem ser
validados para garantir que satisfazem as regras (*regras de validação*, também
conhecidos como *regras de negócio*). Por exemplo, considerando um model (modelo)
`ContactForm`, você pode querer garantir que todos os atributos não sejam vazios e
que o atributo `email` contenha um e-mail válido.
Se o valor de algum atributo não satisfizer a regra de negócio correspondente,
mensagens apropriadas de erros serão exibidas para ajudar o usuário a corrigi-los.
Você pode chamar o método [[yii\base\Model::validate()]] para validar os dados
recebidos. O método usará as regras de validação declaradas em [[yii\base\Model::rules()]]
para validar todos os atributos relevantes. Se nenhum erro for encontrado, o método
retornará true. Caso contrário, o método irá manter os erros na propriedade
[[yii\base\Model::errors]] e retornará false. Por exemplo,
```php
$model = new \app\models\ContactForm;
// os atributos do model serão populados pelos dados fornecidos pelo usuário
$model->attributes = \Yii::$app->request->post('ContactForm');
if ($model->validate()) {
// todos os dados estão válidos
} else {
// a validação falhou: $errors é um array contendo as mensagens de erro
$errors = $model->errors;
}
```
Para declarar as regras de validação em um model (modelo), sobrescreva o método
[[yii\base\Model::rules()]] retornando as regras que os atributos do model (modelo)
devem satisfazer. O exemplo a seguir mostra as regras de validação sendo declaradas
no model (modelo) `ContactForm`:
```php
public function rules()
{
return [
// os atributos name, email, subject e body são obrigatórios
[['name', 'email', 'subject', 'body'], 'required'],
// o atributo email deve ter um e-mail válido
['email', 'email'],
];
}
```
Uma regra pode ser usada para validar um ou vários atributos e, um atributo pode
ser validado por uma ou várias regras.
Por favor, consulte a seção [Validação de Dados](input-validation.md) para mais
detalhes sobre como declarar regras de validação.
Às vezes, você pode querer que uma regra se aplique apenas em determinados
[cenários](#scenarios). Para fazer isso, você pode especificar a propriedade
`on` de uma regra, como o seguinte:
```php
public function rules()
{
return [
// os atributos username, email e password são obrigatórios no cenario "register"
[['username', 'email', 'password'], 'required', 'on' => 'register'],
// os atributos username e password são obrigatórios no cenario "login"
[['username', 'password'], 'required', 'on' => 'login'],
];
}
```
Se você não especificar a propriedade `on`, a regra será aplicada em todos os
cenários. Uma regra é chamada de *active rule* (regra ativa), se ela puder ser
aplicada no [[yii\base\Model::scenario|cenário]] atual.
Um atributo será validado, se e somente se, for um atributo ativo declarado no
método `scenarios()` e estiver associado a uma ou várias regras declaradas no método `rules()`.
## Atribuição em Massa <a name="massive-assignment"></a>
Atribuição em massa é a forma conveniente para popular um model (modelo) com os
dados de entrada do usuário usando uma única linha de código.
Ele popula os atributos de um model (modelo) atribuindo os dados de entrada diretamente
na propriedade [[yii\base\Model::$attributes]]. Os dois códigos a seguir são
equivalentes, ambos tentam atribuir os dados do formulário enviados pelos usuários
finais para os atributos do model (modelo) `ContactForm`. Evidentemente, a
primeira forma, que utiliza a atribuição em massa, é a mais limpa e o menos
propenso a erros do que a segunda forma:
```php
$model = new \app\models\ContactForm;
$model->attributes = \Yii::$app->request->post('ContactForm');
```
```php
$model = new \app\models\ContactForm;
$data = \Yii::$app->request->post('ContactForm', []);
$model->name = isset($data['name']) ? $data['name'] : null;
$model->email = isset($data['email']) ? $data['email'] : null;
$model->subject = isset($data['subject']) ? $data['subject'] : null;
$model->body = isset($data['body']) ? $data['body'] : null;
```
### Atributos Seguros <a name="safe-attributes"></a>
A atribuição em massa só se aplica aos chamados *safe attributes* (atributos seguros),
que são os atributos listados no [[yii\base\Model::scenarios()]] para o
[[yii\base\Model::scenario|cenário]] atual de um model (modelo).
Por exemplo, se o model (modelo) `User` declarar o cenário como o código a seguir,
quando o cenário atual for `login`, apenas os atributos `username` e `password`
podem ser atribuídos em massa. Todos os outros atributos permanecerão inalterados.
```php
public function scenarios()
{
return [
'login' => ['username', 'password'],
'register' => ['username', 'email', 'password'],
];
}
```
> Informação: A razão da atribuição em massa só se aplicar para os atributos seguros
é para que você tenha o controle de quais atributos podem ser modificados pelos
dados dos usuário finais. Por exemplo, se o model (modelo) tiver um atributo
`permission` que determina a permissão atribuída ao usuário, você gostará que
apenas os administradores possam modificar este atributo através de uma interface backend.
Como a implementação do método [[yii\base\Model::scenarios()]] retornará todos os
cenários e atributos encontrados em [[yii\base\Model::rules()]], se não quiser
sobrescrever este método, isto significa que um atributo é seguro desde que esteja
mencionado em uma regra de validação ativa.
Por esta razão, uma alias especial de validação chamada `safe`, será fornecida
para que você possa declarar um atributo seguro, sem ser validado. Por exemplo,
a declaração da regra a seguir faz com que tanto o atributo `title` quanto o
`description` sejam seguros.
```php
public function rules()
{
return [
[['title', 'description'], 'safe'],
];
}
```
### Atributos não Seguros <a name="unsafe-attributes"></a>
Como descrito anteriormente, o método [[yii\base\Model::scenarios()]] serve para
dois propósitos: determinar quais atributos devem ser validados e quais atributos
são seguros. Em alguns casos raros, você pode quer validar um atributo sem marca-lo
como seguro. Para fazer isto, acrescente um ponto de exclamação `!` como prefixo
do nome do atributo ao declarar no método `scenarios()`, como o que foi feito no
atributo `secret` no exemplo a seguir:
```php
public function scenarios()
{
return [
'login' => ['username', 'password', '!secret'],
];
}
```
Quando o model (modelo) estiver no cenário `login`, todos os três atributos serão
validados. No entanto, apenas os atributos `username` e `password` poderão ser
atribuídos em massa. Para atribuir um valor de entrada no atributo `secret`, terá
que fazer isto explicitamente da seguinte forma:
```php
$model->secret = $secret;
```
## Exportação de Dados <a name="data-exporting"></a>
Muitas vezes os models (modelos) precisam ser exportados em diferentes tipos de
formatos. Por exemplo, você pode querer converter um conjunto de models (modelos)
no formato JSON ou Excel. O processo de exportação pode ser divido em duas etapas independentes.
Na primeira etapa, os models (modelos) serão convertidos em arrays; na segunda
etapa, os arrays serão convertidos em um determinado formato. Se concentre apenas
na primeira etapa, uma vez que a segunda etapa pode ser alcançada por formatadores
de dados genéricos, tais como o [[yii\web\JsonResponseFormatter]].
A maneira mais simples de converter um model (modelo) em um array consiste no uso
da propriedade [[yii\base\Model::$attributes]].
Por exemplo,
```php
$post = \app\models\Post::findOne(100);
$array = $post->attributes;
```
Por padrão, a propriedade [[yii\base\Model::$attributes]] retornará os valores de
todos os atributos declarados no método [[yii\base\Model::attributes()]].
Uma maneira mais flexível e poderosa de converter um model (modelo) em um array é
através do método [[yii\base\Model::toArray()]]. O seu comportamento padrão é o
mesmo do [[yii\base\Model::$attributes]]. No entanto, ele permite que você escolha
quais itens de dados, chamados de *fields* (campos), devem ser mostrados no array
resultante e como eles devem vir formatados.
Na verdade, é a maneira padrão de exportação de models (modelos) no desenvolvimento
de Web services RESTful, como descrito na seção [Formatando Respostas](rest-response-formatting.md).
### Campos <a name="fields"></a>
Um campo é simplesmente um elemento nomeado no array obtido pela chamada do método
[[yii\base\Model::toArray()]] de um model (modelo).
Por padrão, os nomes dos campos são iguais aos nomes dos atributos. No entanto,
você pode alterar este comportamento sobrescrevendo os métodos
[[yii\base\Model::fields()|fields()]] e/ou [[yii\base\Model::extraFields()|extraFields()]].
Ambos os métodos devem retornar uma lista dos campos definidos. Os campos definidos
pelo método `fields()` são os campos padrão, o que significa que o `toArray()`
retornará estes campos por padrão. O método `extraFields()` define, de forma adicional,
os campos disponíveis que também podem ser retornados pelo `toArray()`, contanto
que sejam especificados através do parâmetro `$expand`. Por exemplo, o código a
seguir retornará todos os campos definidos em `fields()` incluindo os campos
`prettyName` e `fullAddress`, a menos que estejam definidos no `extraFields()`.
```php
$array = $model->toArray([], ['prettyName', 'fullAddress']);
```
Você poderá sobrescrever o método `fields()` para adicionar, remover, renomear ou
redefinir os campos. O valor de retorno do `fields()` deve ser um array. As chaves
do array não os nomes dos campos e os valores correspondem ao nome do atributo
definido, na qual, podem ser tanto os nomes de propriedades/atributos quanto funções
anônimas que retornam o valor dos campos correspondentes. Em um caso especial,
quando o nome do campo for igual ao nome do atributo definido, você poderá omitir
a chave do array. Por exemplo,
```php
// usar uma lista explicita de todos os campos lhe garante que qualquer mudança
// em sua tabela do banco de dados ou atributos do model (modelo) não altere os
// nomes de seus campos (para manter compatibilidade com versões anterior da API).
public function fields()
{
return [
// o nome do campos é igual ao nome do atributo
'id',
// o nome do campo é "email", o nome do atributo correspondente é "email_address"
'email' => 'email_address',
// o nome do campo é "name", o seu valor é definido por uma função call-back do PHP
'name' => function () {
return $this->first_name . ' ' . $this->last_name;
},
];
}
// filtra alguns campos, é bem usado quando você quiser herdar a implementação
// da classe pai e remover alguns campos delicados.
public function fields()
{
$fields = parent::fields();
// remove os campos que contém informações delicadas
unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);
return $fields;
}
```
> Atenção: Como, por padrão, todos os atributos de um model (modelo) serão
>incluídos no array exportado, você deve examinar seus dados para ter certeza
>que não possuem informações delicadas. Se existir, deverá sobrescrever o método
>`fields()` para remove-los. No exemplo anterior, nós decidimos remover os
>campos `auth_key`, `password_hash` e `password_reset_token`.
## Boas Práticas <a name="best-practices"></a>
A representação dos dados, regras e lógicas de negócios estão centralizados nos
models (modelos). Muitas vezes precisam ser reutilizadas em lugares diferentes.
Em um aplicativo bem projetado, models (modelos) geralmente são muitos maiores
que os [controllers](structure-controllers.md)
Em resumo, os models (modelos):
* podem conter atributos para representar os dados de negócio;
* podem conter regras de validação para garantir a validade e integridade dos dados;
* podem conter métodos para implementar lógicas de negócio;
* NÃO devem acessar diretamente as requisições, sessões ou quaisquer dados do
ambiente do usuário. Os models (modelos) devem receber estes dados a partir dos
[controllers (controladores)](structure-controllers.md);
* devem evitar inserir HTML ou outros códigos de apresentação – isto deve ser
feito nas [views (visões)](structure-views.md);
* devem evitar ter muitos [cenários](#scenarios) em um único model (modelo).
Você deve considerar em utilizar com mais frequência a última recomendação acima
quando desenvolver sistemas grandes e complexos.
Nestes sistemas, os models (modelos) podem ser bem grandes, pois são usados em
muitos lugares e podendo, assim, conter muitas regras e lógicas de negócio.
Nestes casos, a manutenção do código de um model (modelo) pode se transformar
em um pesadelo, na qual uma simples mudança no código pode afetar vários lugares
diferentes. Para desenvolver um model (modelo) manutenível, você pode seguir a
seguinte estratégia:
* Definir um conjunto de classes model (modelo) base que são compartilhados por
diferentes [aplicações](structure-applications.md) ou [módulos](structure-modules.md).
Estas classes model (modelo) base deve contem um conjunto mínimo de regras e lógicas
de negocio que são comuns entre os locais que as utilizem.
* Em cada [aplicação](structure-applications.md) ou [módulo](structure-modules.md)
que usa um model (modelo), deve definir uma classe model (modelo) concreta que
estenderá a classe model (modelo) base que a corresponde. A classe model (modelo)
concreta irá conter apenas as regras e lógicas que são específicas de uma aplicação
ou módulo.
Por exemplo, no [Modelo de Aplicação Avançada](tutorial-advanced-app.md), você
pode definir uma classe model (modelo) base `common\models\Post`. Em seguida,
para a aplicação front-end, você define uma classe model (modelo) concreta
`frontend\models\Post` que estende de `common\models\Post`. E de forma similar
para a aplicação back-end, você define a `backend\models\Post`. Com essa estratégia,
você garantirá que o `frontend\models\Post` terá apenas códigos específicos da
aplicação front-end e, se você fizer qualquer mudança nele, não precisará se
preocupar se esta mudança causará erros na aplicação back-end.
......@@ -54,7 +54,7 @@ build translation "../docs/guide" "../docs/guide-pt-BR" > report-guide-pt-BR.htm
Antes de iniciar seus trabalhos de tradução certifique-se que o arquivo em qual
irá trabalhar esteja disponível para ser traduzido. Para isso, acesse a
[planilha no Google Docs](https://docs.google.com/spreadsheets/d/17JOpAjkJz2YZCjD6gWaUx32wskGRB-2CdFbed111iys/edit?usp=sharing).
[planilha no Google Docs](https://docs.google.com/spreadsheets/d/1pAMe-qsKK0poEsQwGI2HLFmj4afKSkEUd_1qegU5YqQ).
Regras e Observações
......@@ -74,19 +74,27 @@ Regras e Observações
- action — ação
- application system - sistema
- application template — template de aplicação
- controller — controller (controlador)
- eager loading — eager loading (carregamento na inicialização)
- lazy loading — lazy loading (carregamento retardado)
- model — model (modelo)
- query builder — query builder (construtor de consulta)
- view — view (visão)
- note — observação
- info — informação
- tip — dica
- warning - atenção
- attribute label - label do atributo
- inline action — ação inline
- standalone action — ação standalone
### Termos Sem Tradução
- active record
- alias
- cache
- CamelCase
- CamelCase, camel-case
- core
- framework
- hash
......@@ -94,4 +102,6 @@ Regras e Observações
- id
- runtime
- widget
- backend
- frontend
- web service
\ No newline at end of file
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