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 14 2008

Pretty Truncate String Function in PHP (substr replacement)

Category: PHPvbmendes @ 15:33

In this post, I’ll show you a function to make truncate a string. I could simply use the substr function, but it’s not that good since I can break the string in the middle of a word. So I decided to write another function to do this job. It takes 4 parameters: the string you want to truncate, the length you want, the end pattern (defaults to ‘…’) and the string encoding (defaults to UTF-8). I need the encoding because substr may split in the middle of a character, if it is multi-byte, so I use the mb_substr function.

Examples

echo limit('this is just a test',10);// will print 'this is...'
echo limit('this is just a test',30);// will print 'this is just a test'
echo limit('thisIsJustABigWord',10);// will print 'thisIsJust...'

Notice that in the first case, the string will be trucated in the middle of a word(‘just’), so this word was removed also. In the second case, the string is smaller then the max size I specified, so it’s returned as it is. I the third case, the string is just a big word, bigger then the max size, so the word is breaked because this is the only solution i have.

Code

function limit($string,$length,$end='...',$encoding=null){
    if(!$encoding) $encoding = 'UTF-8';
    $string = trim($string);
    $len = mb_strlen($string,$encoding);
    if($len <= $length) return $string;
    else {
        $return = mb_substr($string,0,$length,$encoding);
        return (preg_match('/^(.<em>[^\s])\s+[^\s]</em>$/', $return, $matches) ? $matches[1] : $return).$end;
    }
}

In the code, I firstly remove the spaces in the start and end of the string, then I get the lenght of my string, if it’s lower then what I want, return the string itself, otherwise, return the truncated with the end pattern.

Hope it helps.

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