Sep 30 2008

Setar flag no lugar de excluir registro do banco com CakePHP

Category: CakePHP, PHPvbmendes @ 19:59

Uma boa prática de programação é setar uma flag indicando que um registro foi excluido, e não simplesmente excluir o registro do banco. Por exemplo, se eu tenho um produto, que está relacionado em vários pedidos, e eu simplesmente excluo o produto, todos os pedidos que referenciam ele serão inconsistentes. Se em troca de excluir o registro do produto, eu simplesmente setar uma flag no registro indicando que ele foi excluído, eu não perderei mais essa consistência. Para excluir o produto de id 5, seria algo como:

mysql_query("UPDATE produtos SET deleted = true WHERE id = 5");

E para listar os produtos, poderia ser algo como:

mysql_query("SELECT * FROM produtos WHERE NOT deleted;");

Percebam que para transferir isso para o CakePHP, basta alterar dois métodos, o index, adicionando a condição, e o delete, substituindo o $this->Produto->del() por um save. Mas o Mariano Iglesias do Cake Syrup desenvolveu um behavior que nos economiza muito trabalho. É o SoftDeletable. Com ele, a tarefa se resume a uma simples configuração no model no qual se deseja aplicar o uso da flag.

var $actsAs = array('SoftDeletable');

Para isso, basta criar o campo deleted na sua tabela e adicionar o arquivo do behavior, disponível no site citado, na pasta de behaviors do seu projeto.

O único problema que eu encontrei nesse behavior é que ao chamar a função $this->Model->del($id), o beforeDelete do behavior é acionado, atualizando o campo da flag deleted para true e retornando false, o que impede que o registro seja realmente excluído do banco. Com isso a tentativa de salvar retorna falso, indicando erroneamente que não obteve sucesso.

Tags: ,


Sep 28 2008

Validar relacionamento belongsTo no CakePHP

Category: CakePHP, PHPvbmendes @ 11:39

Uma prática que eu acho bastante interessante é verificar se realmente um registro existe no banco antes de associá-lo a outro. Por exemplo, suponha que se têm dois models:

/app/models/pessoa.php
class Pessoa extends AppModel {
    var $name = "Pessoa";
}

/app/models/aluno.php
class Aluno extends AppModel {
    var $name = "Aluno";
    var $belongsTo = array(
        'Pessoa' => array(
            'className' => 'Pessoa',
            'foreignKey' => 'pessoa_id'
        )
    );
}

Eu quero que sempre que eu adicionar um aluno, o sistema valide se a pessoa a qual eu estou associando este aluno esteja cadastrada no banco. Ou seja, quero garantir que o aluno estará vinculado a uma pessoa válida.

Para isso eu criei uma função de validação que coloquei no meu app_model.php. Veja:

function checkBelongsTo($data, $relationName){
	$field = $this->belongsTo[$relationName]['foreignKey'];
	$search[$this->{$relationName}->primaryKey] = $data[$field];
	return $this->{$relationName}->find('count',array('conditions' => $search));
}

Vamos analisar o código. A primeira linha da função determina qual o campo que irá conter a foreign key, no nosso caso pessoa_id. A segunda linha gera um array de condições no formato:

Array[primaryKey => valor]

Onde primaryKey é obtido diretamente do model associado, e valor é o id do registro ao qual se quer fazer a relação. Na terceira linha é feita uma busca ao banco para saber quantos registros existem que satisfaçam essa condição, o que, obedecendo a condição de que a chave primária deve ser única, irá retornar 0 ou 1. O resultado desta consulta será o retorno da função.
Feito isso, basta adicionar a condição de validação ao model:

/app/models/aluno.php
class Aluno extends AppModel {
    var $name = "Aluno";
    var $validate = array(
        'pessoa_id' => array(
            'rule' => array('checkBelongsTo','Pessoa'),
            'message' => 'Pessoa inexistente.'
        );
    );
    var $belongsTo = array(
        'Pessoa' => array(
            'className' => 'Pessoa',
            'foreignKey' => 'pessoa_id'
        )
    );
}

Perceba que eu adicionei a regra de validação checkBelongsTo passando como parametro o nome do relacionamento entre aluno e pessoa.

Espero ter sido claro. Qualquer dúvida comente.

Tags: , ,


Sep 26 2008

Prepared Statements e CakePHP

Category: CakePHP, PHP, SQLvbmendes @ 10:17

Precisei montar uma SQL “na mão” usando o CakePHP pois ela era muito complexa. Mas me bateu a preocupação com o famoso SQL injection. Então me lembrei das minhas aulas de Programação Orientada a Objetos em que o professor falou que em java existia um método de uso de SQL chamado de prepared statement. O qual você monta a SQL colocando ‘?’ onde serão colocados parâmetros que serão passado para a SQL. Mas ele me mostrou como fazer isso em Java, então fui em busca de uma solução parecida em CakePHP e encontrei. Vou postar um exemplo simples que logicamente poderia ser feito usando a abstração de banco do cake:

$query = "SELECT nome FROM pessoa WHERE id = ? AND cpf = ?";
$values = array($this->params['named']['pessoa_id'],$this->params['named']['cpf']);
$this->Pessoa->query($query,$values);

Veja que eu passei dois parâmetros para o método query do model: o meu SQL com duas ‘?’ e um array com dois objetos que irão substituir as duas ‘?’ do SQL. Veja que a ordem de substituição é a natural, ou seja, o primeiro item do array substitui a primeira ‘?’ do SQL e assim sucessivamente.

É recomendado o uso dos prepared statements sempre que tiver que criar consultas com SQL e que precisem de parâmetros.

Tags: , , , , ,


Sep 25 2008

Mudança de template

Category: Uncategorizedfabiomcosta @ 11:57

Pessoal estamos num processo de readaptação do novo template, iremos mudar algumas coisas ainda neste template para melhorar a acessibilidade e se adequar a um blog de programadores :D.

Peço a paciência de todos!

We are currently changing our template, so be patient with any bug with the layout you find.

Thanks.


Sep 20 2008

meioMask a jQuery Plugin for masking inputs

Category: Javascript, jQueryfabiomcosta @ 21:08

I present you meioMask - a jQuery plugin for masking inputs.

Plugin page

Plugin official page

I’ve centralized all the comments at the page of the project, so i’m not allowing comments here but you are free and motivated to comment at the meioMask’s project page.

I was looking for a good masking plugin to use with jQuery or maybe Mootools but haven’t found one that can do what i wanted it to do. I mean like being cross-browser, accept paste event (very important!), have a money mask, like the bank ones…Well here are some of the meioMask’s features:

  • Accepts paste event;*
  • Haves fixed and reverse mask types ( allow number mask );
  • Input focus isn’t lost (if the input is smaller than the mask, focus will follow the caret);**
  • You can still use your hot keys and others (ex: ctrl+t, ctrl+f5, TAB …);
  • Supports metadata plugin;

* Safari on mac isn’t supported. Paste event for some reason isn’t fired on command+v (right-click paste works). On Mac Firefox it work’s ok.

** Firefox 2 and before aren’t supported.

You can see the plugin page here. It contains documentation and examples. I’ll be making a “projects” page here soon to add the plugins i made.Please tell me any bug, new feature, english errors on documentation…. anything! I’ll be glad to hear your feedback and make the fixes.Hope it helps you!

Tags: , , , , ,


Sep 12 2008

Trabalhando com JSON no CakePHP 1.2

Category: Ajax, CakePHP, Javascriptvbmendes @ 07:43

 Gostei da forma como o Juan Basso trabalha para renderizar objetos JSON através do CakePHP. Ficou bem limpa e da conta do recado. Segue o link do post falando sobre isso: http://blog.cakephp-brasil.org/2008/09/11/trabalhando-com-json-no-cakephp-12/

Tags: