Jun 08 2009

MeioUpload project created at github

Category: CakePHPvbmendes @ 10:02

Juan Basso created a project hosted at github. I am unable to keep working on this behavior an he is making some updates to the code. I think github is a great tool because you can simply fork the project and make your own changes. Go check his work: http://github.com/jrbasso/MeioUpload/tree/master

Tags: , , , ,


Oct 18 2008

Unique validation rule in CakePHP 1.2

Category: CakePHP,PHPvbmendes @ 08:46

In this post I will show an example of how apply the unique validation rule in CakePHP 1.2. It’s very important to do in some cases, like saving users. You must make sure that the username is unique in your system. Lets see how it works:

var $validate = array(
    'username' => array(
        'rule' => array('isUnique'),
        'message' => 'Username already in use.'
    )
);

I wrote a custom function to validate it, but thanks to Dia now I know the built-in validation rule.

Tags: , , ,


Oct 12 2008

MeioUpload Behavior 1.0.1 released!

Category: CakePHP,PHPvbmendes @ 19:40

I am glad to show you the MeioUpload Behavior 1.0.1. An improved Upload Behavior for CakePHP 1.2. It makes file uploads as simple as defining a variable.

See the docs.

Features

  • Accepts custom directory for files to be uploaded;
  • Validates the file extension and mime-type due to the behavior configuration;
  • Validates the max file size;
  • Allow custom validation rules;
  • Allow as many thumbnails formats as you want;
  • Allow more then one field to be uploadable, with custom options per field;
  • Stores the directory, filesize, and mime-type in the database if the table has these fields;
  • Allow the use of default files and deleting files without deleting the entire record;
  • Delete files when the record is deleted or updated with a new file;
  • Also works in the $model->saveAll method.

Changelog

v1.0.1

  • Fixed a bug in the create folder method;
  • Now you can use the $validate var of the model to apply the changes to default validation rules;
  • Changed the my_array_merge function, now it’s part of the behavior, name arrayMerge;
  • Allow use of {DS}, {model} and {field} constants in directory name and fields names;
  • Fixed a bug with the replacement of the default names.

v1.0

  • Initial release

Any bugs, features suggestions, and english errors, please tell me.

Tags: , ,


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: , , , , ,