CakePHP Brasil

11 setembro 2008

Trabalhando com JSON no CakePHP 1.2

Arquivado em: CakePHP, Tutoriais — Tags:, , , , , , — Juan Basso @ 10:13 pm

Com o crescimento do uso de AJAX, da maioria dos frameworks de JavaScript (jQuery, Prototype, mooTools, YUI, ExtJS, …) e de uma dúvida no Groups do Google (Action que renderize apenas o layout, sem necessidade de uma view), resolvi escrever um post falando sobre como usar JSON no CakePHP de forma automática para retorno dos dados, sem precisar gerar um arquivo de view para cada action e que não fere o MVC.
A Solução

Para solucionar o caso, achei que o melhor jeito seria criando uma classe de View nova. A classe View do CakePHP ela sempre procura um arquivo de view, além do template. Com a nova classe, seria feita a renderização ali mesmo, sem a necessidade de novos arquivos.

A classe que criei (JsonView) pode ser baixada aqui. Ela deve ser colocada na pasta views de da sua aplicação (nenhuma sub-pasta) com o nome de json.php. Ou seja, no final, você terá o caminho app/views/json.php.
Como Usar

Para usar é bem simples. No seu controller, quando você for retornar um código em JSON, basta alterar a variável $view do controller para usar a nova classe. Além disso, os dados que você quer que retorne, devem ser setados com o nome ‘json‘ no seu controller. Caso não seja, ele vai renderizar normalmente. Exemplo de uso no controller:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class UsuariosController extends AppController {
	var $uses = array('Usuario', 'Grupo');
 
	function index($json = false) {
		$this->set('usuarios', $this->Usuario->find('list'));
		if ($json) {
			$this->view = 'Json';
			$this->set('json', 'usuarios');
		}
	}
 
	function multilista($json = false) {
		$this->set('usuarios', $this->Usuario->find('list'));
		$this->set('grupos', $this->Grupo->find('list'));
		if ($json) {
			$this->view = 'Json';
			$this->set('json', array('usuarios', 'grupos'));
		}
	}
}

Neste caso, quando o parâmetro de index não for true, ele vai renderizar como se fosse uma requisição normal. Caso passe como true, ele irá renderizar como JSON. Já no método multilista, além do parâmetro para verificar se é JSON, ele passa um array de variáveis para a view JSON, assim a classe irá renderizar mais de uma variável.

Outra maneira de se fazer é definir a variável $view da classe diretamente com ‘Json’ (assim como foi feito com $uses no exemplo). Assim, sempre que você der um set na variável ‘json’, a classe da View se liga e renderiza em json, caso contrário mantém o normal.

Conclusão

Este é um método fácil e rápido de renderizar as requisições JSON, sem precisar criar um arquivo para cada requisição e sem precisar de muito código (tanto no controller, quanto na view).

O código que fiz, é compatível com PHP 4 e 5, então é possível usar com o CakePHP sem medo em qualquer versão de PHP.

Abraços e bom uso. :) Dicas são sempre bem vindas.

30 julho 2008

Usando FlexiGrid com CakePHP

Arquivado em: CakePHP, Tutoriais — Tags:, , , , , — Juan Basso @ 12:05 am

Pessoal,

Depois de escrever sobre como usar o TableSorter com CakePHP, vou escrever agora sobre o FlexiGrid. Mostrar como implementar o exemplo mais sofisticado que eles apresentam no site deles.

Primeiramente, vamos baixar os arquivos necessários:

  • jQuery: http://jquery.com (mais recente no momento é a 1.2.6)
  • FlexiGrid: http://www.webplicity.net/flexigrid/ (estou me baseando na versão 1.0b3)
  • Colocar os arquivos (jquery.js e flexigrid.js) na pasta vendors\js ou webroot\js, conforme sua preferência.

    Agora na view que vai mostrar a tabela:

    Carregar os javascripts:

    1
    
    <?php $javascript->link(array('jquery', 'flexigrid'), false); ?>

    Feito isso, incluir o seguinte código na página para exibir a tabela (PS: esse código eu copiei exatamente como está na página do Flexigrid):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    
    <style>
    	.flexigrid div.fbutton .add {
    		background: url(css/images/add.png) no-repeat center left;
    	}	
     
    	.flexigrid div.fbutton .delete {
    		background: url(css/images/close.png) no-repeat center left;
    	}	
    </style>
     
    <table id="flex1" style="display:none"></table>
     
    <script type="text/javascript">
    	$("#flex1").flexigrid({
    		url: '<?php echo Router::url(array('controller' => 'flexi', 'action' => 'index'), true); ?>',
    		dataType: 'json',
    		colModel : [
    			{display: 'ISO', name : 'iso', width : 40, sortable : true, align: 'center'},
    			{display: 'Name', name : 'name', width : 180, sortable : true, align: 'left'},
    			{display: 'Printable Name', name : 'printable_name', width : 120, sortable : true, align: 'left'},
    			{display: 'ISO3', name : 'iso3', width : 130, sortable : true, align: 'left', hide: true},
    			{display: 'Number Code', name : 'numcode', width : 80, sortable : true, align: 'right'}
    		],
    		buttons : [
    			{name: 'Add', bclass: 'add', onpress : test},
    			{name: 'Delete', bclass: 'delete', onpress : test},
    			{separator: true}
    		],
    		searchitems : [
    			{display: 'ISO', name : 'iso'},
    			{display: 'Name', name : 'name', isdefault: true}
    		],
    		sortname: "iso",
    		sortorder: "asc",
    		usepager: true,
    		title: 'Paises',
    		useRp: true,
    		rp: 15,
    		showTableToggleBtn: true,
    		width: 700,
    		height: 200,
    		pagestat: 'Mostrando {from} até {to} de {total} itens',
    		procmsg: 'Processando, aguarde...',
    		nomsg: 'Nenhum item'
    	});
     
    	function test(com,grid) {
    		if (com == 'Delete') {
    			confirm('Excluir ' + $('.trSelected',grid).length + ' itens?')
    		} else if (com == 'Add') {
    			alert('Adicionar novo item');
    		}
    	}
    </script>

    Pronto, nossa view está pronta para exibir os dados. Agora vamos para a parte dos dados:

    Vamos começar pelo controller (controllers/flexi_controller.php):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
    <?php
     
    class FlexiController extends AppController {
     
    	var $name = 'Flexi';
    	var $uses = array('Country');
     
    	function index() {
    		Configure::write('debug', 0);
    		extract($this->params['form']);
    		$this->paginate = array(
    			'limit' => $rp,
    			'page' => $page,
    			'order' => array(
    				$sortname => $sortorder
    			)
    		);
    		if ($query) {
    			$this->paginate['conditions'][$qtype . ' LIKE'] = '%' . $query . '%';
    		}
    		$this->header('Content-type: text/x-json');
    		$this->set('paises', $this->paginate('Country'));
    		$this->layout = 'ajax';
    	}
     
    }
     
    ?>

    Duas considerações: desativar o debug é para que ele não exiba erros/warnings de PHP e o tempo de carregamento no final. O layout ajax é para ele não incluir nada a mais que o que eu colocar na view.

    Bem, feito isso no controller, vamos para a view (views/flexi/index.ctp), montar nosso JSON na mão… :)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    <?php $params = $paginator->params(); ?>
    { page: <?php echo $params['page']; ?>, total: <?php echo $params['count']; ?>, rows: [
    <?php
    $registros = array();
    foreach ($paises as $pais) {
    	$registros[] = "{id: '" . $pais['Country']['iso'] . "', cell: ['" . $pais['Country']['iso'] . "', '" . $pais['Country']['name'] . "', '" . $pais['Country']['printable_name'] . "', '" . $pais['Country']['iso3'] . "', '" . $pais['Country']['numcode'] . "']}";
    }
    echo implode(',', $registros);
    ?> ] }

    Pronto, isso aí vai gerar o JSON necessário para o Flexigrid. Já dá para brincar com ordenação, troca de páginas, filtro…

    Qualquer coisa, só comentar!

    28 julho 2008

    Usando o TableSorter com CakePHP

    Arquivado em: CakePHP, Tutoriais — Tags:, , , , , , , — Juan Basso @ 9:26 pm

    Pessoal, depois de um tempo sumido devido a alguns trabalhos que me consumiram muito tempo, estou voltando…

    Hoje vou falar de uma experiência que tive com o TableSorter com CakePHP na construção de uma página, não me atendo muito a detalhes de design, mas da parte funcional. No grupos de CakePHP PT eu tinha falado que ia fazer, mas fazem quase dois meses e nada, porém agora lá vai… Bill: desculpe a demora. :)

    Primeiro, baixem o jQuery (http://jquery.com) e o plugin TableSorter (http://tablesorter.com).

    Extraia os arquivos baixados (jquery.js e jquery.tablesorter.js) em alguma vendors\js ou webroot\js. Eu particularmente prefiro deixar na pasta vendors, pois são plugins de terceiros ou que não são exclusivos da aplicação. Em contra partida, deixar na pasta webroot polpa o trabalho do servidor executar o cake para procurar, reduzindo o tempo de resposta. Aí vai do gosto de cada um. Eu prefiro perder tempo para deixar as coisas nos seus devidos lugares…

    No controller, você precisa apenas declarar que vai usar o helper Javascript:

    1
    
    var $helpers = array(..., 'Javascript');

    Feito isso, criamos uma tabela na view do que queremos mostar:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    <table border="0" id="detalhe_compra">
    	<caption><?php __('Detalhe por compra'); ?></caption>
    	<thead>
    		<tr>
    			<th><?php __('Pedido'); ?></th>
    			<th><?php __('Data'); ?></th>
    			<th><?php __('Cliente'); ?></th>
    			<th><?php __('Valor'); ?></th>
    		</tr>
    	</thead>
    	<tfoot>
    		<tr>
    			<td colspan="3">&nbsp;</td>
    			<td><?php echo $number->currency($totalPedidos); ?>
    		</tr>
    	</tfoot>
    	<tbody>
    <?php foreach ($pedidos as $pedido): ?>
    		<tr>
    			<td><?php echo $pedido['Pedido']['numero']; ?></td>
    			<td><?php echo $pedido['Pedido']['data']; ?></td>
    			<td><?php echo $pedido['Cliente']['nome']; ?></td>
    			<td><?php echo $pedido['Pedido']['valor']; ?></td>
    		</tr>
    <?php endforeach; ?>
    	</tbody>
    </table>

    Depois, ainda na mesma view, basta colocar o seguinte código para carregar os arquivos de javascript no head:

    1
    
    <?php $javascript->link(array('jquery', 'jquery.tablesorter'), false); ?>

    Em seguida, configurar o TableSorter para agir sobre a tabela:

    1
    2
    3
    4
    5
    6
    
    <?php
    $javascript->codeBlock('
    	$(document).ready(function(){
    		$("#detalhe_compra").tablesorter({decimal: ",", dateFormat: "uk"});
    	});', array('inline' => false));
    ?>

    Nas configurações da tabela, defini que os números possuem o vírgula como separador decimal e a data no formato inglês (similar ao nosso).

    Pronto, só isso já faz funcionar o TableSorter. Outras configurações, podem olhar no site do TableSorter e ver. Lá é bem documentado e tranquilo.

    Abraços e boa sorte a todos, qualquer coisa, é só comentar.

    19 maio 2008

    Usando jQuery com CakePHP

    Arquivado em: Tutoriais — Tags:, , — Juan Basso @ 8:59 pm

    Vendo o questionamento de muitas pessoas no Google Groups, vou explicar como usar o jQuery juntamente com o CakePHP.

    A primeira coisa que você tem que fazer é baixar o código do jQuery e colocá-lo na pasta vendors\js (tanto faz ser na vendors dentro de app ou fora). Depois disso, nos controllers que você for utilizar o jQuery, inclua o helper Javascript:

    1
    2
    3
    
    class SeuController extends AppController {
      var $helpers = array('Javascript');
    }

    Se você usa em todas as páginas, pode colocar isto no seu AppController.

    Feito isso, você pode usar na sua view (ou layout) o seguinte código:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    <?php
    // Incluir o jQuery ao projeto
    // Neste exemplo estou importando a jquery.tablesorter também
    // O segundo parâmetro (false) é para indicar que vai no <head> e não no local onde está sendo executado
    $javascript->link(array('jquery', 'jquery.tablesorter'), false);
     
    // Aqui vou definir alguns comandos de jQuery
    $javascript->codeBlock('
      $(document).ready(function(){
        $("#detalhe_compra").tablesorter({decimal: ",", dateFormat: "uk"});
        $("#resumo_compras").tablesorter({decimal: ",", dateFormat: "uk"});
      });', array('inline' => false));
    ?>
    Minha view normalmente...

    Com isso, você faz que o código javascript vá para o <head> do seu HTML e não fique no meio das suas views, o que é deselegante e fora do padrão W3C.

    Num próximo post explico como usar jQuery e AJAX.

    Powered by WordPress