10 – Detalhes sobre Controllers
Já experimentou acreditar em você? Tente! Você não faz ideia do que é capaz.
Os controllers correspondem ao ‘C’ no padrão MVC. Após o roteamento ter sido aplicado e o controller correto encontrado, a ação do controller é chamada. Seu controller deve lidar com a interpretação dos dados de uma requisição, certificando-se que os models corretos são chamados e a resposta ou view esperada seja exibida. Os controllers podem ser vistos como intermediários entre a camada Model e View. Você vai querer manter seus controllers magros e seus Models gordos. Isso lhe ajudará a reutilizar seu código e testá-los mais facilmente.
Mais comumente, controllers são usados para gerenciar a lógica de um único model. Por exemplo, se você está construindo um site para uma padaria online, você pode ter um RecipesController e um IngredientsController gerenciando suas receitas e seus ingredientes. No CakePHP, controllers são nomeados de acordo com o model que manipulam. É também absolutamente possível ter controllers que usam mais de um model.
Os controllers da sua aplicação são classes que estendem a classe CakePHP AppController, a qual por sua vez estende a classe Controller do CakePHP. A classe AppController pode ser definida em /app/Controller/AppController.php e deve conter métodos que são compartilhados entre todos os seus controllers.
Os controllers fornecem uma série de métodos que são chamados de ações. Ações são métodos em um controller que manipulam requisições. Por padrão, todos os métodos públicos em um controller são ações e acessíveis por urls.
Os atributos e métodos criados em AppController vão estar disponíveis para todos os controllers da sua aplicação. Este é o lugar ideal para criar códigos que são comuns para todos os seus controllers. Componentes (que você vai aprender mais tarde) são a melhor alternativa para códigos que são usados por muitos (mas não obrigatoriamente em todos) controllers.
Enquanto regras normais de herança de classes orientadas à objetos são aplicadas, o CakePHP também faz um pequeno trabalho extra quando se trata de atributos especiais do controller. A lista de componentes (components) e helpers usados no controller são tratados diferentemente. Nestes casos, as cadeias de valores do AppController são mescladas com os valores de seus controllers filhos. Os valores dos controllers filhos sempre sobrescreveram os do AppController.
O CakePHP mescla as seguintes variáveis do AppController em controllers da sua aplicação:
$components
$helpers
$uses
Lembre-se de adicionar os helpers Html e Form padrões se você incluiu o atributo $helpers em seu AppController.
Também lembre de fazer as chamadas de callbacks do AppController nos controllers filhos para obter melhores resultados:
function beforeFilter() {
parent::beforeFilter();
}
No CakePHP nós gostamos de manter os nossos actions do controller enxutos, e colocar a maior parte da lógica de negócio de nossa aplicação nos modelos.
Exemplo de Controller Comentado
<?php
// O comando abaixo faz o include da classe AppController que encontra-se na pasta app/Controller
App::uses('AppController', 'Controller');
// Observe que o controller PostsController extende a classe AppController
class PostsController extends AppController {
A propriedade recursive define qual a profundidade que o CakePHP deve ir para procurar modelos associados de dados via métodos find() e read().
Imagine uma aplicação com Groups e cada Group contém muitos Users que por sua vez, cada User tem muitos Articles. Você pode setar $recursive para vários valores baseado no total de dados que você deseja de volta de uma chamada $this->Group->find():
-1 Cake busca somente dados de Group, sem joins.
0 Cake busca dados de Group e seu domínio
1 Cake busca um Group, seu domínio e seus Users associados
2 Cake busca um Group, seu domínio, seus Users associados e os Articles assoaiados aos Users
Não defina $recursive mais do que você precisa. Quando você tem dados buscados pelo CakePHP você não vai deixar sua aplicação lenta desnecessariamente. Observe também que o nível recursivo padrão é 1.
*/
$this->Post->recursive = 0;
/*
O método set() tem como objetivo enviar informações para a View.
Com a linha abaixo a view index.ctp poderá chamar o array $posts, que contém todos os posts paginados.
*/
$this->set('posts', $this->paginate());
}
/**
* view method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function view($id = null) {
// Verifica com o model Post, se existe o $id recebido
if (!$this->Post->exists($id)) {
throw new NotFoundException(__('Invalid post'));
}
// Opções para filtrar o model Post que tem o $id como chave primária
$options = array('conditions' => array('Post.' . $this->Post->primaryKey => $id));
// Passa para a view a variável $post com o primeiro Post encontrado
$this->set('post', $this->Post->find('first', $options));
}
public function add() {
// Verifica se a requisição é do tipo POST
if ($this->request->is('post')) {
// Cake PHP recomenda chamar a função create() para re-inicializar um model antes de salvar
// um novo registro. Criar - create(). Salvar/Atualizar - save().
$this->Post->create();
// O método save() salva o registro e também valida
if ($this->Post->save($this->request->data)) {
// setFlash mostra uma mensagem
$this->Session->setFlash(__('The post has been saved'));
// redirect redireciona para o action index. Também existem outros parâmetros
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The post could not be saved. Please, try again.'));
}
}
}
public function edit($id = null) {
// Verifica se existe o $id no model Post
if (!$this->Post->exists($id)) {
throw new NotFoundException(__('Invalid post'));
}
//echo 'CONTROLLER - Enviando para o Model';
//exit;
// Verifica se houve requisição do tipo POST ou PUT
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->Post->save($this->request->data)) {
//echo 'CONTROLLER - Vindo do Model';
//exit;
$this->Session->setFlash(__('The post has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The post could not be saved. Please, try again.'));
}
} else {
$options = array('conditions' => array('Post.' . $this->Post->primaryKey => $id));
$this->request->data = $this->Post->find('first', $options);
}
}
public function delete($id = null) {
// Guarda em $this->Post->id o $id passado via parâmetro
$this->Post->id = $id;
if (!$this->Post->exists()) {
throw new NotFoundException(__('Invalid post'));
}
// CakeRequest::onlyAllow($methods) - adicionado no Cake 2.3. Substituiu o método
// requireDelete() das versões anteriores.
$this->request->onlyAllow('post', 'delete');
// Exclui o registro
if ($this->Post->delete()) {
$this->Session->setFlash(__('Post deleted'));
$this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Post was not deleted'));
$this->redirect(array('action' => 'index'));
}
}
Permitir que registros sejam deletados usando requisições GET é perigoso, pois rastreadores na web podem acidentalmente deletar todo o seu conteúdo.
Mais detalhes
Comments fornecido por CComment