Os controllers (controladores) fazem parte da arquitetura MVC. 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, controllers analisarão os dados de entradas obtidos pela requisição, passarão estes dados para os models (modelos), incluirão os resultados dos models (modelos) nas views (visões) e finalmente gerarão as respostas de saída.
Os controllers são compostos por unidades básicas chamadas de 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
:
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 conforme o ID solicitado; Se o model for devidamente
carregado, a ação irá exibi-lo utilizado a view 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 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.
Os usuários finais abordarão as ações por meio de rotas. Uma rota é uma string composta pelas seguintes partes:
As rotas seguem o seguinte formato:
IDdoController/IDdoAction
ou o seguinte formato se o controller estiver em um módulo:
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.
Em aplicações Web, os controllers devem estender de yii\web\Controller
ou de suas classes filhas. De forma semelhante, em 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
:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
}
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), hífens 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 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
).
Os nomes da classes dos controllers podem ser derivadas dos IDs dos controllers de acordo com as seguintes procedimentos:
Controller
como sufixo.Segue alguns exemplos, assumindo que o namespace do controller
tenha por padrão o valor app\controllers
:
article
torna-se app\controllers\ArticleController
;post-comment
torna-se app\controllers\PostCommentController
;admin/post-comment
torna-se app\controllers\admin\PostCommentController
;adminPanels/post-comment
torna-se app\controllers\adminPanels\PostCommentController
.As classes dos controllers devem ser autoloadable.
Por esta razão, nos exemplos anteriores, o controller article
deve ser salvo
no arquivo cuja alias é @app/controllers/ArticleController.php
;
enquanto o controller admin/post-comment
deve ser salvo no @app/controllers/admin/PostCommentController.php
.
Informação: No último exemplo
admin/post-comment
, mostra como você pode colocar um controller em um subdiretório do namespace controller. Isto é útil quando você quiser organizar seus controllers em diversas categorias e não quiser usar módulos.
Você pode configurar um 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 controllers de terceiros na qual você não tem controle sobre seus nomes de classes.
Você pode configurar o mapeamento de controllers na configuração da aplicação. Por exemplo:
[
'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,
],
],
]
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, será utilizada a
rota especificada pela propriedade.
Para as aplicações Web, este valor é 'site'
, enquanto
para as aplicações console é help
. Portanto, se uma
URL for http://hostname/index.php
, o controller site
será utilizado nesta requisição.
Você pode alterar o controller padrão como a seguinte configuração da aplicação:
[
'defaultRoute' => 'main',
]
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
:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public function actionIndex()
{
return $this->render('index');
}
public function actionHelloWorld()
{
return 'Hello World';
}
}
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
e comment-post
são IDs válidos, enquanto view?
e 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 uma classe-filha. 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.
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 procedimentos:
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çãoindex
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 são definidas por classes de ações que estendem de yii\base\Action ou de uma classe-filha. 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:
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. 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
namespace app\components;
use yii\base\Action;
class HelloWorldAction extends Action
{
public function run()
{
return "Hello World";
}
}
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 que será enviado como resposta aos usuários finais.
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 redirect() retorna um objeto de resposta):
public function actionForward()
{
// redireciona o navegador do usuário para http://example.com
return $this->redirect('http://example.com');
}
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
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
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
.
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:
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 para mais detalhes.
Cada controller tem uma ação padrão especificado pela propriedade yii\base\Controller::$defaultAction. Quando uma 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:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public $defaultAction = 'home';
public function actionHome()
{
return $this->render('home');
}
}
Ao processar uma requisição, a aplicação criará um controller baseada na rota solicitada. O controller, então, se submeterá ao seguinte ciclo de vida para concluir a requisição:
beforeAction()
da aplicação, o módulo (se o controller pertencer a um módulo) e o controller.false
, o restante dos métodos subsequentes beforeAction()
serão ignoradas e a execução da ação será cancelada.beforeAction()
desencadeia a execução de um evento chamado beforeAction
na qual você pode associar a uma função (handler).afterAction()
do controller, o módulo (se o controller pertencer a um módulo) e a aplicação.afterAction()
desencadeia a execução de um evento chamado afterAction
na qual você pode associar a uma função (handler).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.
Segue algumas boas práticas em destaque. Os controllers:
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.