quinta-feira, 29 de março de 2012

Curso de PHP Orientado a Objetos - Parte 9

Imagem meramente ilustrativa
Vamos dar início ao nono artigo do curso de PHP Orientado a Objetos. Hoje falando sobre os métodos interceptores.

Para conhecer as demais partes, clique aqui.


Ao final deste artigo, você será capaz de:
  • Entender o que são os métodos interceptores;
  • Fazer uso dos métodos __set(), __get() e __call().
Intercepções

Métodos de intercepção são métodos especiais predefinidos no PHP. Seus nomes são reservados, todos prefixados com dois caracteres "_" (underscore) no início.
Os métodos __set(), __get() e __call são alguns desses métodos. Trata-se de métodos opcionais e geralmente utilizados para executarem ações consideradas "especiais" e específicas.

__set()

O método __set() é invocado toda vez que um atributo não declarado da classe recebe a atribuição de um valor. Este método espera dois parâmetros, o primeiro contendo o nome do atributo e o segundo seu valor. 
Em resumo, toda vez que for atribuído um valor a uma propriedade do objeto, automaticamente esta atribuição passa pelo método __set().
Para facilitar o entendimento, vamos ao exemplo:


/* Vamos crair a classe Pessoa
*  com somente uma propriedade
*  chamada Idade.
*/
class Pessoa{

  private $Idade;

  /* Quando tentarmos
   * atribuir um valor
   * para a propriedade idade
   * o método __set() entre em ação
  */

  public function __set( $propriedade, $valor ){

    if( $propriedade == "Idade" ){

      if( is_integer($valor) && strlen($valor) > 1 ){

        $this->Idade = $valor;
        echo "Valor: " . $valor . " Atribuído à propriedade: " . $propriedade;

      }else{

        echo "Valor: " . $valor . "NÃO atribuído à propriedade: " . $propriedade;

      }

    }

  }

}

$leandro = new Pessoa();
$leandro->Idade = 27;

Observe que criamos o objeto normalmente (linha 36) e quando fomos atribuir 27 a propriedade idade do objeto, nosso amigo __set() interceptou, validou e só assim, permitiu ou não que o valor chegasse de fato ao atributo $idade.
Lembre-se, o __set() sempre espera dois parâmetros: $propriedade e $valor. Esses sempre devem ser verificados.
Imagine que em sua aplicação você possui a propriedade senha. Você pode utilizar o __set() para validar se a senha informada pelo usuário atende todos os requisitos necessário e só depois, a propriedade recebe o conteúdo (caso hipotético).

__get()

Análogo ao método __set(), o __get() é chamado quando um atributo da classe precisa ser retornado para o objeto. Ele espera um parâmetro, que será preenchido com o nome do atributo chamado.
Para exemplificar melhor o uso do __get(), vamos ao exemplo:


class Carro{

  public $Nome;
  private $Valor;

  const MargemLucro = 8;

  public function __construct($Nome, $Valor){
    $this->Nome = $Nome;
    $this->Valor = $Valor;
  }

  /* Quando o usuario requisitar
  *  uma propriedade, o __get()
  *  irá interceptar, verificar se a
  *  propriedade é a "Valor" e realizar
  *  o ajuste da margem de lucro
  */
  function __get($Propriedade){

    if( $Propriedade == "Valor" ){

      $valor_reajustado = $this->Valor * ( 1 + self::MargemLucro / 100 );

      return "R$ " . number_format($valor_reajustado, 3, ',', '.');

    }

  }

}

$vectra = new Carro("Vectra 2.0", 40.000);
echo $vectra->Valor;



Perceba que ao executar, quando realizamos a requisição a propriedade Valor, o método __get() faz a intercepção, ajusta o valor para a margem de lucro pré-definida além de formatar e só assim o valor e entregue.
Esta é um uso clássico do método __get().

__call()

Diferente dos métodos __set() e __get, o método __call() entra em ação quando é feita uma chamada a um método (não mais uma propriedade) que não existe. Sempre que um método não existir no objeto, automaticamente a execução será direcionada para ele que também recebe dois parâmetros, o nome e o parâmetro informados, assim ele pode decidir o que fazer nesta situação. 
Vamos ao exemplo para entender melhor:


class Carro{

  public $Nome;
  private $Valor;

  const MargemLucro = 8;

  public function __construct($Nome, $Valor){
    $this->Nome = $Nome;
    $this->Valor = $Valor;
  }

  //Este é o método que fará a intercepção

  function __call($Metodo, $Parametros){

    echo "Método executado: " . $Metodo;
    echo "Parâmetros do método:< br />";
     
    // Um array para mostrar os parametros passados

    foreach ( $Parametros as $Chave => $Parametro ){

      echo "Parâmetro {$Chave} = " . $Parametro;

    }

  }

}

$vectra = new Carro("Vectra s.0", 40.000);
// Opa!! Que método é esse?? Ah, deixa que o __call cuida
echo $vectra->DefineCaracteristicas("Preto",2.0,"4 portas");


Ao executar, será mostrado todas as características passadas pelo método DefineCaracteristicas, justamente pela intercepção realizada pelo método __call(). Mesmo não tendo este método na classe.

Existem diversos outros métodos considerados especiais, clique aqui para consultar a lista completa.

Lembre-se que estes métodos foram projetados para facilitar a vida do programador, grandes frameworks como Zend fazem uso dessa funcionalidade para atribuir de forma dinâmica nas camadas do modelo de visão. Falaremos sobre frameworks em breve.

Terminamos assim mais uma aula. 
Utilize o espaço de comentários para dúvidas, críticas, elogios ou sugestões. É sempre um prazer ler sua opinião sobre meu conteúdo.
Gostaria de agradecer novamente pelos comentários que venho recebendo.

Na próxima aula estudaremos um pouco mais sobre métodos, desta vez o __autoload(), além de conhecermos algumas funções para manipulação de objetos.

Nenhum comentário:

Postar um comentário