3.5.3 Métodos

Para uma lista completa de métodos do controller e suas descrições visite a API CakePHP. Dê uma olhada http://api.cakephp.org/1.2/class_controller.html.

3.5.3.1 Interagindo com as views

set(string $var, mixed $value)

O método set() é a principal forma de enviar dados do seu controller para sua view. Um vez que você usou set(), a variável pode ser acessada na sua view.

<?php
    
// Primeiro você passa os dados do controller:

$this->set('cor', 'pink');

// Então, na view, você pode utilizar os dados:

Você selecionou a cor <?php echo $cor; ?> para colorizar o cake.

?>
  1. <?php
  2. // Primeiro você passa os dados do controller:
  3. $this->set('cor', 'pink');
  4. // Então, na view, você pode utilizar os dados:
  5. Você selecionou a cor <?php echo $cor; ?> para colorizar o cake.
  6. ?>

O método set() também pega um array associativo como seu primeiro parâmetro. Esse pode ser geralmente uma caminho rápido para atribuir um grupo de informações para a view. Perceba que os índices de seu array sofrerão inflection antes de serem atribuídos à view ('indice_com_underline' se torna 'indiceComUnderline', etc.):

<?php
    
$dados = array(
    'cor' => 'pink',
    'tipo' => 'açucar'’,
    'preco_base' => 23.95
);

// fazem $cor, $tipo, e $precoBase
// disponíveis na view:

$this->set($data);  

?>
  1. <?php
  2. $dados = array(
  3. 'cor' => 'pink',
  4. 'tipo' => 'açucar',
  5. 'preco_base' => 23.95
  6. );
  7. // fazem $cor, $tipo, e $precoBase
  8. // disponíveis na view:
  9. $this->set($data);
  10. ?>
render(string $action, string $layout, string $file)

O método render() é automaticamente chamado ao final de cada action do controller requisitada. Esse método executa toda a lógica da view (usando dados que você forneceu usando o método set()), insere a view dentro do layout e o serve de volta para o usuário final.

O arquivo de view padrão renderizado é determinado por convenção. Se a action buscar() do ReceitasController é requisitada, o arquivo de view /app/views/receitas/buscar.ctp será renderizado.

Ainda que o CakePHP vá automaticamente chamá-lo (a menos que você configure $this->autoRender para false) depois de cada lógica de action, você pode usá-lo para especificar um arquivo de view alternativo configurando o nome da action no controller usando $action. Você pode também especificar um arquivo alternativo um terceiro parâmetro, $file. Quando usar $file, lembre-se de utilizar um pouco das constantes globais do CakePHP (como a VIEWS).

O parâmetro $layout permite especificar o layout na qual a view é renderizada.

3.5.3.1.1 set

set(string $var, mixed $value)

O método set() é a principal forma de enviar dados do seu controller para sua view. Um vez que você usou set(), a variável pode ser acessada na sua view.

<?php
    
// Primeiro você passa os dados do controller:

$this->set('cor', 'pink');

// Então, na view, você pode utilizar os dados:

Você selecionou a cor <?php echo $cor; ?> para colorizar o cake.

?>
  1. <?php
  2. // Primeiro você passa os dados do controller:
  3. $this->set('cor', 'pink');
  4. // Então, na view, você pode utilizar os dados:
  5. Você selecionou a cor <?php echo $cor; ?> para colorizar o cake.
  6. ?>

O método set() também pega um array associativo como seu primeiro parâmetro. Esse pode ser geralmente uma caminho rápido para atribuir um grupo de informações para a view. Perceba que os índices de seu array sofrerão inflection antes de serem atribuídos à view ('indice_com_underline' se torna 'indiceComUnderline', etc.):

<?php
    
$dados = array(
    'cor' => 'pink',
    'tipo' => 'açucar'’,
    'preco_base' => 23.95
);

// fazem $cor, $tipo, e $precoBase
// disponíveis na view:

$this->set($data);  

?>
  1. <?php
  2. $dados = array(
  3. 'cor' => 'pink',
  4. 'tipo' => 'açucar',
  5. 'preco_base' => 23.95
  6. );
  7. // fazem $cor, $tipo, e $precoBase
  8. // disponíveis na view:
  9. $this->set($data);
  10. ?>

3.5.3.1.2 render

render(string $action, string $layout, string $file)

O método render() é automaticamente chamado ao final de cada action do controller requisitada. Esse método executa toda a lógica da view (usando dados que você forneceu usando o método set()), insere a view dentro do layout e o serve de volta para o usuário final.

O arquivo de view padrão renderizado é determinado por convenção. Se a action buscar() do ReceitasController é requisitada, o arquivo de view /app/views/receitas/buscar.ctp será renderizado.

Ainda que o CakePHP vá automaticamente chamá-lo (a menos que você configure $this->autoRender para false) depois de cada lógica de action, você pode usá-lo para especificar um arquivo de view alternativo configurando o nome da action no controller usando $action. Você pode também especificar um arquivo alternativo um terceiro parâmetro, $file. Quando usar $file, lembre-se de utilizar um pouco das constantes globais do CakePHP (como a VIEWS).

O parâmetro $layout permite especificar o layout na qual a view é renderizada.

3.5.3.2 Fluxo de controle

redirect(string $url, integer $status, boolean $exit)

O método de controle de fluxo que você vai usar com maior freqüência é o redirect(). Esse método pega seu primeiro parâmetro na forma de uma URL relativa CakePHP. Quando um usuário fez uma compra com sucesso, você provavelmente irá redirecioná-lo para a tela de recibo.

<?php
	
function comprar() {

    // A lógica para finalizar a compra vai aqui...

    if($sucesso) {
        $this->redirect('/compras/obrigado');
    } else {
        $this->redirect('/compras/confirmar');
    }
}

?>
  1. <?php
  2. function comprar() {
  3. // A lógica para finalizar a compra vai aqui...
  4. if($sucesso) {
  5. $this->redirect('/compras/obrigado');
  6. } else {
  7. $this->redirect('/compras/confirmar');
  8. }
  9. }
  10. ?>

O segundo parâmetro do redirect() lhe permite definir um código de status HTTP para acompanhar o redirecionamento. Você pode querer usar 301 (movido permanentemente) ou 303 (veja outro), dependendo da natureza do redirecionamento.

Esse método não chama exit() depois de redirecionar a menos que você configure o terceiro parâmetro para true.

flash(string $message, string $url, integer $pause)

Similarmente, o método flash() é usado para direcionar o usuário para uma nova página depois de uma operação. O método flash() é diferente pelo fato de mostrar uma mensagem antes de passar o usuário para uma outra URL.

O primeiro parâmetro deve guardar a mensagem a ser mostrada, e o segundo parâmetro é uma URL relativa CakePHP. CakePHP vai mostrar a mensagem na variável $message, por um tempo definido em segundos na variável $pause antes de direcionar o usuário.

Para mensagens flash dentro da página, dê uma olhada no método setFlash() do component Session.

3.5.3.2.1 redirect

redirect(string $url, integer $status, boolean $exit)

The flow control method you’ll use most often is redirect(). This method takes its first parameter in the form of a CakePHP-relative URL. When a user has successfully placed an order, you might wish to redirect them to a receipt screen.

function placeOrder() {

    //Logic for finalizing order goes here

    if($success) {
        $this->redirect(array('controller' => 'orders', 'action' => 'thanks'));
    } else {
        $this->redirect(array('controller' => 'orders', 'action' => 'confirm'));
    }
}
  1. function placeOrder() {
  2. //Logic for finalizing order goes here
  3. if($success) {
  4. $this->redirect(array('controller' => 'orders', 'action' => 'thanks'));
  5. } else {
  6. $this->redirect(array('controller' => 'orders', 'action' => 'confirm'));
  7. }
  8. }

The second parameter of redirect() allows you to define an HTTP status code to accompany the redirect. You may want to use 301 (moved permanently) or 303 (see other), depending on the nature of the redirect.

The method will issue an exit() after the redirect unless you set the third parameter to false.

3.5.3.2.2 flash

flash(string $message, string $url, integer $pause)

Similarly, the flash() method is used to direct a user to a new page after an operation. The flash() method is different in that it shows a message before passing the user on to another URL.

The first parameter should hold the message to be displayed, and the second parameter is a CakePHP-relative URL. CakePHP will display the $message for $pause seconds before forwarding the user on.

For in-page flash messages, be sure to check out SessionComponent’s setFlash() method.

3.5.3.3 Callbacks

Controllers CakePHP vem com callbacks para inserir lógica exatamente antes ou depois das actions serem rederizadas.

beforeFilter()

Essa função é executada antes de qualquer action no controller. É o lugar ideal para checar uma sessão ativa ou inspecionar permissões.

beforeRender()

Chamada após a lógica da action do controller, mas antes da view ser renderizada. Esse callback não é usado geralmente, mas pode ser necessário se você está chamando render() manualmente antes do final de uma dada action.

afterFilter()

Chamada depois de toda action do controller.

afterRender()

Chamada depois que uma action tiver sido renderizada.

3.5.3.4 Outros métodos úteis

constructClasses()

Esse método carrega os models requeridos pelo controller. Esse processo de carregamento é feito pelo CakePHP normalmente, mas o método é uma boa quando estiver acessando controllers de diferentes perspectivas. Se você precisa do CakePHP em um script de linha de comando ou outro uso de fora, constructClasses() pode ser uma boa.

referrer()

Retorna a URL referida pela requisição atual.

disableCache()

Usado para dizer ao navegador do usuário não fazer cache dos resultados na requisição atual. Isso é diferente do cache da view, coberto no capítulo anterior.

postConditions(array $data, mixed $op, string $bool, boolean $exclusive)

Use esse método para tornar um grupo de dados enviados por POST (de inputs compatíveis com o helper Html) em um grupo de condições de busca para o model. Essa função oferece um atalho rápido para criar lógica de busca. Por exemplo, um usuário administrativo pode querer ser capaz de buscar compras para saber quais itens precisam ser enviados. Você pode criar um rápido formulário baseado no model Compra. Então a action do controller pode usar os dados enviados do formulário para criar as condições de busca.

function index() {
    $o = $this->Orders->findAll($this->postConditions($this->data));
    $this->set('compras', $o);
}
  1. function index() {
  2. $o = $this->Orders->findAll($this->postConditions($this->data));
  3. $this->set('compras', $o);
  4. }

Se $this->data['Compra']['destino'] é igual a "Padaria da Cidade Velha", postConditions converte essa condição para um array compatível para uso no método NomeDoModel->findAll(). Nesse caso, array("Compra.destino" => "Padaria da Cidade Velha").

Se você quer usar um operador SQL diferente entre os termos, forneça-os usando o segundo parâmetro.


/*
Conteúdo de $this->data
array(
    'Compra' => array(
        'num_de_itens' => '4',
        'fornecedor' => 'Trigo Integral LTDA'
    )
)
*/
 
// Vamos pegar compras que tem ao menos 4 itens e contém 'Trigo Integral LTDA'
$c = $this->Compra->findAll($this->postConditions(
    $this->data,
    array('>=', 'LIKE')
));
  1. /*
  2. Conteúdo de $this->data
  3. array(
  4. 'Compra' => array(
  5. 'num_de_itens' => '4',
  6. 'fornecedor' => 'Trigo Integral LTDA'
  7. )
  8. )
  9. */
  10. // Vamos pegar compras que tem ao menos 4 itens e contém 'Trigo Integral LTDA'
  11. $c = $this->Compra->findAll($this->postConditions(
  12. $this->data,
  13. array('>=', 'LIKE')
  14. ));

O índice nas especificações de operadores é a ordem das colunas no array $this->data. Já que num_de_itens é o primeiro, o operador >= aplica-se a ele.

O terceiro parâmetro lhe permite dizer ao CakePHP que operador booleano SQL usar entre as condições de busca. Strings com 'AND', 'OR', e 'XOR' são todos valores válidos.

Finalmente, se o último parâmetro está configurado para true, e o parâmetro $op é um array, os campos não incluídos em $op não serão incluídos nas condições retornadas.

cleanUpFields(string $modelClass = null)

Esse método de conveniência concatena as várias partes de datas em $this->data antes de salvar. Se você tem inputs de data do helper Form, esse método concatena o ano, mês, dia e hora em uma string mais compatível com banco de dados.

Esse método usa o model padrão do controller (por ex.: o model Cookie para o controller CookiesController) como alvo para a concatenação, mas uma classe alternativa pode ser usada como primeiro parâmetro.

paginate()

Esse método é usado para paginar os resultados divididos pelos seus models. Você pode especificar tamanhos de páginas, condições de busca do model e mais. Detalhes sobre esse método mais a frente. Dê uma olhada no capítulo de paginação mais a frente nesse manual.

requestAction(string $url, array $options)

Essa função chama uma action de controller de qualquer lugar e retorna os dados dessa action. A $url passada é uma URL relativa ao CakePHP (/nomedocontroller/nomedaaction/parametros). Se o array $options incluir um valor de returno. AutoRender é automaticamente configurada para true para a action do controller, tendo a requestAction te levando para a view totalmente renderizada.

Nota: apesar de ser possível usar requestAction() para pegar uma view totalmente renderizada, a perda performance que você obtem passando por toda a camada da view novamente na realidade não faz valer a pena. O método requestAction() é melhor usado em conjunto com elements - como um caminho para enviar lógica de negócio para um element antes da renderização.

Primeiro, vamos ver como pegar dados da action do controller. Primeiro, nós precisamos criar a action do controller que retorna algum dado que precisamos em vários lugares através da aplicação:

// Aqui está nosso controller simples:

class UsuariosController extends AppController {
    function pegarListaDeUsuarios() {
        return $this->Usuario->findAll('Usuario.ativo = 1');
    }
}
  1. // Aqui está nosso controller simples:
  2. class UsuariosController extends AppController {
  3. function pegarListaDeUsuarios() {
  4. return $this->Usuario->findAll('Usuario.ativo = 1');
  5. }
  6. }

Imagine que nós precisamos criar uma simples tabela mostrando os usuários ativos no sistema. Ao invés de duplicar o código de geração de lista em outro controller, nós podemos pegar dados do UsuariosController->pegarListaDeUsuarios() ao invés de usar requestAction();

class ProdutosController extends AppController {
    function mostrarProdutosDoUsuario() {
        $this->set(
            'usuarios', 
            $this->requestAction('/usuarios/pegarListaDeUsuarios')
        );

        // Agora a variável $usuarios na view vai ter dados do
        // UsuariosController::pegarListaDeUsuarios().
    }
}   
  1. class ProdutosController extends AppController {
  2. function mostrarProdutosDoUsuario() {
  3. $this->set(
  4. 'usuarios',
  5. $this->requestAction('/usuarios/pegarListaDeUsuarios')
  6. );
  7. // Agora a variável $usuarios na view vai ter dados do
  8. // UsuariosController::pegarListaDeUsuarios().
  9. }
  10. }

Se você tem um element na sua aplicação que não é estático, você pode querer usar requestAction() para enviar lógica equivalente à do controller para o element a medida em que você o injeta nas suas views. Apesar de elements sempre tem acesso a qualquer variável da view que o controller passou, essa é uma forma de passar dados para o element vindos de outro controller.

Se você criou uma action do controller que fornece a lógica necessária, você pode pegar dados e passá-lo para o segundo parâmetro do método renderElement() da view usando requestAction().

<?php 
echo $this->renderElement(
    'usuarios',
    $this->requestAction('/usuarios/pegarListaDeUsuarios')
);
?>
  1. <?php
  2. echo $this->renderElement(
  3. 'usuarios',
  4. $this->requestAction('/usuarios/pegarListaDeUsuarios')
  5. );
  6. ?>

Se o array '$options' contiver um valor "return", a action do controller será renderizada dentro de um layout vazio e retornada. Dessa forma, a função requestAction() é útil também em situações Ajax onde um pequeno elemento de uma view precisa ser preenchido antes ou durante uma atualização Ajax.

3.5.3.4.1 constructClasses

This method loads the models required by the controller. This loading process is done by CakePHP normally, but this method is handy to have when accessing controllers from a different perspective. If you need CakePHP in a command-line script or some other outside use, constructClasses() may come in handy.

3.5.3.4.2 referer

Returns the referring URL for the current request.

3.5.3.4.3 disableCache

Used to tell the user’s browser not to cache the results of the current request. This is different than view caching, covered in a later chapter.

3.5.3.4.4 postConditions

postConditions(array $data, mixed $op, string $bool, boolean $exclusive)

Use this method to turn a set of POSTed model data (from HtmlHelper-compatible inputs) into a set of find conditions for a model. This function offers a quick shortcut on building search logic. For example, an administrative user may want to be able to search orders in order to know which items need to be shipped. You can use CakePHP’s Form- and HtmlHelpers to create a quick form based on the Order model. Then a controller action can use the data posted from that form to craft find conditions:

function index() {
    $o = $this->Orders->findAll($this->postConditions($this->data));
    $this->set('orders', $o);
}
  1. function index() {
  2. $o = $this->Orders->findAll($this->postConditions($this->data));
  3. $this->set('orders', $o);
  4. }

If $this->data[‘Order’][‘destination’] equals “Old Towne Bakery”, postConditions converts that condition to an array compatible for use in a Model->findAll() method. In this case, array(“Order.destination” => “Old Towne Bakery”).

If you want use a different SQL operator between terms, supply them using the second parameter.

/*
Contents of $this->data
array(
    'Order' => array(
        'num_items' => '4',
        'referrer' => 'Ye Olde'
    )
)
*/

//Let’s get orders that have at least 4 items and contain ‘Ye Olde’
$o = $this->Order->findAll($this->postConditions(
    $this->data,
    array('>=', 'LIKE')
));
  1. /*
  2. Contents of $this->data
  3. array(
  4. 'Order' => array(
  5. 'num_items' => '4',
  6. 'referrer' => 'Ye Olde'
  7. )
  8. )
  9. */
  10. //Let’s get orders that have at least 4 items and contain ‘Ye Olde’
  11. $o = $this->Order->findAll($this->postConditions(
  12. $this->data,
  13. array('>=', 'LIKE')
  14. ));

The key in specifying the operators is the order of the columns in the $this->data array. Since num_items is first, the >= operator applies to it.

The third parameter allows you to tell CakePHP what SQL boolean operator to use between the find conditions. String like ‘AND’, ‘OR’ and ‘XOR’ are all valid values.

Finally, if the last parameter is set to true, and the $op parameter is an array, fields not included in $op will not be included in the returned conditions.

3.5.3.4.5 paginate

This method is used for paginating results fetched by your models. You can specify page sizes, model find conditions and more. See the pagination section for more details on how to use paginate.

3.5.3.4.6 requestAction

requestAction(string $url, array $options)

This function calls a controller's action from any location and returns data from the action. The $url passed is a CakePHP-relative URL (/controllername/actionname/params). To pass extra data to the receiving controller action add to the $options array.

You can use requestAction() to retrieve a fully rendered view by passing 'return' in the options: requestAction($url, array('return'));

If used without caching requestAction can lead to poor performance. It is rarely appropriate to use in a controller or model.

requestAction is best used in conjunction with (cached) elements – as a way to fetch data for an element before rendering. Let's use the example of putting a "latest comments" element in the layout. First we need to create a controller function that will return the data.

// controllers/comments_controller.php
class CommentsController extends AppController {
    function latest() {
        return $this->Comment->find('all', array('order' => 'Comment.created DESC', 'limit' => 10));
    }
}
  1. // controllers/comments_controller.php
  2. class CommentsController extends AppController {
  3. function latest() {
  4. return $this->Comment->find('all', array('order' => 'Comment.created DESC', 'limit' => 10));
  5. }
  6. }

If we now create a simple element to call that function:

// views/elements/latest_comments.ctp

$comments = $this->requestAction('/comments/latest');
foreach($comments as $comment) {
    echo $comment['Comment']['title'];
}
  1. // views/elements/latest_comments.ctp
  2. $comments = $this->requestAction('/comments/latest');
  3. foreach($comments as $comment) {
  4. echo $comment['Comment']['title'];
  5. }

We can then place that element anywhere at all to get the output using:

echo $this->element('latest_comments');
  1. echo $this->element('latest_comments');

Written in this way, whenever the element is rendered, a request will be made to the controller to get the data, the data will be processed, and returned. However in accordance with the warning above it's best to make use of element caching to prevent needless processing. By modifying the call to element to look like this:

echo $this->element('latest_comments', array('cache'=>'+1 hour'));
  1. echo $this->element('latest_comments', array('cache'=>'+1 hour'));

The requestAction call will not be made while the cached element view file exists and is valid.

In addition, requestAction now takes array based cake style urls:

echo $this->requestAction(array('controller' => 'articles', 'action' => 'featured'), array('return'));
  1. echo $this->requestAction(array('controller' => 'articles', 'action' => 'featured'), array('return'));

This allows the requestAction call to bypass the usage of Router::url which can increase performance. The url based arrays are the same as the ones that HtmlHelper::link uses with one difference. If you are using named params in your url then the requestAction url array must wrap the named params in the key 'named'. This is because requestAction only merges the named args array into the Controller::params member array and does not place the named args in the key 'named'.

echo $this->requestAction('/articles/featured/limit:3');
  1. echo $this->requestAction('/articles/featured/limit:3');

This as an array in the requestAction would then be:

echo $this->requestAction(array('controller' => 'articles', 'action' => 'featured', 'named' => array('limit' => 3)));
  1. echo $this->requestAction(array('controller' => 'articles', 'action' => 'featured', 'named' => array('limit' => 3)));

Unlike other places where array urls are analogous to string urls, requestAction treats them differently.

When using an array url in conjunction with requestAction() you must specify all parameters that you will need in the requested action. This includes parameters like $this->data and $this->params['form']