07 outubro 2009

Como forçar a "declaração" de variáveis no PHP

Após uma discussão no GOPHP sobre declaração obrigatória de variáveis, iniciada pelo Ole Peter Smith, surgiram algumas maneiras de "driblar" essa liberdade que o PHP proporciona de não ser necessário declarar variáveis.

Todos sabemos que no PHP não é possível declarar uma variável, porém é possível inicializar uma variável com um determinado valor.
Quando tentamos utilizar uma variável que não foi inicializada, o PHP retorna um erro do tipo Notice. Como vários servidores não exibem os erros do tipo Notice, através do código abaixo é possível fazer com que esse erro seja tratado como um Fatal Error, que vai finalizar a execução do script.

A vantagem dessa alteração é aumentar o controle sobre as variáveis utilizadas no programa e evitar possíveis erros de execução.

Segue o código:

function newErrorHandler($error, $message)
{
if($error == 8)
{
trigger_error($message, E_USER_ERROR);
}

return false;
}

set_error_handler("newErrorHandler");

$novaVariavel = $variavelInexistente;



Além dessa maneira, quando trabalhamos com encapsulamento, podemos utilizar funções que testam o tipo da variável para garantir que o valor de um atributo será de um determinado tipo. Esse teste pode ser feito tanto para tipos primitivos quanto para tipos criados pelo usuário ou arrays.

class Pessoa
{
private $id;
private $nome;
private $tipo;
private $listaTelefone;

public function setId($id)
{
if(is_integer($id))
$this->id = $id;
else
throw new Exception('O atributo ID deve ser numérico.');
}

public function setNome($nome)
{
if(is_string($nome))
$this->nome = $nome;
else
throw new Exception('O atributo NOME deve ser uma string.');
}

public function setTipo($tipo)
{
if($tipo instanceof PessoaFisica)
$this->tipo = $tipo;
else
throw new Exception('O atributo TIPO deve ser um objeto da classe PessoaFisica.');
}

public function setListaTelefone($listaTelefone)
{
if(is_array($listaTelefone))
$this->listaTelefone = $listaTelefone;
else
throw new Exception('O atributo LISTA TELEFONE deve ser um array.');
}
}


Outros detalhes interessantes surgiram no decorrer desse tópico e que muitos desenvolvedores podem não saber da possibilidade, como por exemplo definir explicitamente o tipo de dados que uma função pode receber como parâmetro.

function calculaSalario(Array $empregados)
{
// código
}

Dessa maneira a função calculaSalario() somente irá aceitar uma variável que seja do tipo Array. Lembrando que não é possível utilizar tipos primitivos para essa funcionalidade, porém é possível utilizar tipos criados pelo usuário através de classes.

4 comentários:

  1. man!!! Q gambi :) rsrs

    Idéia original mas nada aplicável, tem alguns problemas mas era uma boa idéia pra aplicar num framework uh?

    Essa idéia por ex é a pra validation do PhpBURN (www.phpburn.com) ao dar save() ou mesmo find() ainda não implementado, se tiver interesse, seja bem vindo

    ResponderExcluir
  2. Já dá pra fazer isso direto no PHP:

    1 <\?php
    2
    3 function text(String $text)
    4 {
    5 echo $text;
    6 }
    7
    8 text(1); // erro
    9
    10 ?\>

    A não ser que, no caso, seja uma versão mais antiga. PHP 4 por exemplo.

    ResponderExcluir
  3. Caio, o detalhe é encerrar a aplicação para qualquer variável não iniciada, e não somente em funções. Um abraço!

    ResponderExcluir
  4. Klederson,
    Isso é verdade! é meio POG. Essa solução surgiu pois um programador PERL queria saber como fazer isso em PHP. Bom, aí está! É uma solução que, se realmente for implementada, pode ser muuuito melhorada! Um abraço!

    ResponderExcluir