Curso de PHP Orientado a Objetos – Parte 9
Nono artigo do curso de PHP Orientado a Objetos. Dessa vez estudaremos os métodos interceptores, também conhecidos como métodos mágicos.
Ao final deste artigo, você será capaz de: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.
- Entender o que são os métodos interceptores;
- Fazer uso dos métodos __set(), __get() e __call().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/* 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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:"; // 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.
Tipo então é assim que funciona o encapsulamento no PHP.
Tipo eu fiquei meio grilado de não tem q usar um “get” ou “set”
na frete do nome da propriedade! Acho q vou demorar um
pouco a me acostumar se for assim! E o nível do curso é
bem alto e aplaudo sua iniciativa!
Fabiano não confunda, o encapsulamento em PHP segue o mesmo padrão de outras linguagens como Java por exemplo, você deve criar suas variáveis e as que julgar necessárias crie os seus devidos métodos get and setter. Os métodos __set e __get devem ser usados para finalidades específicas.
José, após perceber que os métodos especiais são para propriedades inacessíveis (private e protected), também me veio a dúvida: por que não usar o setPropriedade e getPropriedade, ao invés dos métodos especiais com uma condição para verificar qual a propriedade?
Você comentou sobre finalidades específicas. Poderia citar uma onde utilizar métodos mágicos fosse mais adequado do que os convencionais setters e getters?
E mais uma vez, o curso é muito bom.
O curso está muito bom!!!
A proposta é muito diferente do que encontramos na maioria dos tutoriais, cursos e vídeo aulas na internet… diferente no sentido de ser mais claro, direto e recheado de exemplos.
Parabéns!!!
Bastante lúcido e esclarecedor. Grato pelo empenho!
No exemplo sobre o uso do __set(), a propriedade ‘Idade’ deveria ter sido declarada como ‘public’ ao invés de ‘private’, não!? Afinal, como propriedade privada, não podemos acessa-la diretamente usando $objeto->propriedade. Estou certo?
Esquece. Depois do meu código não funcionar, fui ao manual e li que o método especial __set() é justamente para propriedades inacessíveis que, no caso, seria realmente uma propriedade privada (private).