3.5.3.4 Outros métodos úteis
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.
Retorna a URL referida pela requisição atual.
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.
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);
}
function index() {$o = $this->Orders->findAll($this->postConditions($this->data));$this->set('compras', $o);}
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')
));
/*Conteúdo de $this->dataarray('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')));
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.
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.
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.
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');
}
}
// Aqui está nosso controller simples:class UsuariosController extends AppController {function pegarListaDeUsuarios() {return $this->Usuario->findAll('Usuario.ativo = 1');}}
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().
}
}
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().}}
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')
);
?>
<?phpecho $this->renderElement('usuarios',$this->requestAction('/usuarios/pegarListaDeUsuarios'));?>
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);
}
function index() {$o = $this->Orders->findAll($this->postConditions($this->data));$this->set('orders', $o);}
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')
));
/*Contents of $this->dataarray('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')));
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));
}
}
// controllers/comments_controller.phpclass CommentsController extends AppController {function latest() {return $this->Comment->find('all', array('order' => 'Comment.created DESC', 'limit' => 10));}}
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'];
}
// views/elements/latest_comments.ctp$comments = $this->requestAction('/comments/latest');foreach($comments as $comment) {echo $comment['Comment']['title'];}
We can then place that element anywhere at all to get the output using:
echo $this->element('latest_comments'); 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')); 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')); 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'); 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))); 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']
