PHP
Como usar os métodos mágicos no PHP
Algo muito interessante que o PHP 5 trouxe ao imergir na orientação a objetos, foram os métodos mágicos. Os métodos mágicos, são métodos previamente definidos de uma classe que tem funcionalidades específicas, estes métodos são precedidos por __, portanto, evite criar métodos em suas classes usando esta notação, a não ser que seja algo bem específico. Vou mostrar abaixo a funcionalidade de alguns deles:
1 – __construct
É o nosso tão famoso construtor. Ele é chamado quando instanciamos uma classe, ou seja, quando escrevemos new.
class Cliente{ private $nome; public function __construct($nome){ $this->nome = $nome; } } $cliente = new Cliente("Meu cliente");
2 – __destruct
O método contrário do construtor, ou seja, é chamado quando uma instância for destruída. Esta destruição pode ser quando explicitamente o(s) objeto(s) são removidos da execução ou no encerramento de uma execução de um script. Por exemplo: Em uma requisição HTTP, o destrutor seria chamado ao servidor devolver a resposta da requisição.
class Cliente{ private $nome; public function __construct($nome){ $this->nome = $nome; } public function __destruct(){ echo "Minha variável nome: {$this->nome} sendo destruída."; } } $cliente = new Cliente("Meu cliente");
3 – __toString
Por padrão se fizermos assim:
$cliente = Cliente("Meu cliente"); echo $cliente; //causará um erro
Isto causará um erro, porque o PHP não conseguirá converter a classe em uma string. Mas se declararmos o método mágico e o retorno da função for uma string, será mostrado na tela este valor. Se o retorno não for uma string também será lançado um erro.
class Cliente{ private $nome; public function __construct($nome){ $this->nome = $nome; } public function __toString(){ return $this->nome; } } $cliente = new Cliente("Meu cliente"); echo $cliente; //imprimirá Meu cliente
4 – __call e __callStatic
Estes dois métodos mágicos permitem realizar uma sobrecarga nos objetos criados permitindo a criação de métodos dinâmicos. Portanto é possível chamar métodos habituais ou estáticos (usando o __callStatic) sem que eles realmente existam em suas classes. Este recurso é muito interessante, porque podemos realizar ações incríveis dentro de uma classe. Estas duas funções recebem como parâmetros a variável $name, que é o nome do método chamado e a variável $arguments, que é um array com os parâmetros passados.
class String{ public function __call($name, $arguments){ if (strpos($name,'upper') !== false) { return strtoupper($arguments[0]); } } public static function __callStatic($name, $arguments){ if (strpos($name,'upper') !== false) { return strtoupper($arguments[0]); } } } $string = new String(); echo $string->upper("minha string"); //MINHA STRING echo String::upper("minha string"); //MINHA STRING
Veja que criei um método fictício upper que pode ser chamado tanto de um objeto instanciado quanto diretamente da classe via estático. O método pega o primeiro argumento e o retorna em maiúsculo.
5 – __invoke
Parece ser semelhante a um construtor, mas, a diferença que é somente uma invocação, portanto, o objeto precisa ser instanciado previamente. É como se o objeto pudesse ser chamado inúmeras vezes como um método.
class String{ public function __invoke($s){ return strtoupper($s); } } $string = new String(); echo $string("minha string"); //MINHA STRING
6 – __get e __set
Semelhante ao __call porém com foco nos atributos da classe. É possível pegar dados ou atribuir dados sem que realmente os atributos existam na classe ou sejam permitidos o acesso direto. Se for atribuído para um atributo inexistente o __set é chamado, se for pego algum atributo inexistente o __get será chamado. A função __set recebe dois parâmetros: $name é o nome do atributo chamado e $value é o valor que se quer atribuir, já o __get só recebe o $name de igual significado ao __set.
class Cliente{ private $nome; public function __set($name, $value){ if (strpos($name,'nome') !== false) { $this->nome = $value; } } public function __get($name){ if (strpos($name,'nome') !== false) { return $this->nome; } } } $cliente = new Cliente(); $cliente->nome="Meu cliente"; echo $cliente->nome;
Veja que o atributo $nome na classe Cliente é privado, isto faz com que não seja acessível diretamente, mas com o código adicionado permitimos isto.
8 – __clone
A clonagem de objetos permite a cópia das propriedades de um objeto para outro e o método __clone é chamado quando o objeto é clonado, neste método você pode fazer alguma mudança nas propriedades do clone.
class Cliente{ private $nome; public function __set($name, $value){ if (strpos($name,'nome') !== false) { $this->nome = $value; } } public function __get($name){ if (strpos($name,'nome') !== false) { return $this->nome; } } public function __clone(){ $this->nome .=" Sobrenome"; } } $cliente = new Cliente(); $cliente->nome="Meu cliente"; echo $cliente->nome; $clienteNovo = clone $cliente; echo "Novo cliente: ".$clienteNovo->nome; //Meu cliente Sobrenome
Veja que em todo cliente clonado será concatenado o valor “Sobrenome” ao nome.
Referências: