PHP

Como usar os métodos mágicos no PHP

Por em

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:

http://php.net/manual/pt_BR/language.oop5.magic.php