Quando trabalhamos com programação orientada a objetos, normalmente temos que trabalhar com propriedades e métodos, seja para alterar um valor ou executar uma ação. Métodos mágicos em PHP são métodos que são invocados quando trabalhamos com as propriedades e métodos de um objeto (instância de uma classe).

Com eles você pode fazer interceptações ao longo da execução do script e modificar o curso da aplicação, caso necessário.

Você já viu dois métodos mágicos em aulas anteriores, __construct e __destruct, hoje você vai ver a maioria dos métodos mágicos que ainda não falamos.

Então vamos lá.

__set

O método mágico {php}__set{/php}, é invocado quando tentamos alterar uma propriedade com visibilidade {php}protected{/php} ou {php}private{/php}.

No trecho de código abaixo, vou criar duas propriedades privadas. Conforme já descrevi em outras aulas, não podemos alterar nem acessar valores privados ou protegidos fora do contexto da classe. Porém, como estou utilizando o método {php}__set{/php}, posso interceptar essa tentativa e fazer algo diferente. Veja:

<?php
class Pessoa
{
	// Propriedades privadas
	private   $nome;
	private   $idade;
	
	// __set é invocado quando tentamos alterar o valor de uma propriedade com
	// visibilidade protegida ou privada
	function __set( $propriedade, $valor ) {
		if ( $propriedade === 'idade' ) {
			if ( is_numeric( $valor ) ) {
				$this->$propriedade = $valor;
			}
		} else {
			$this->$propriedade = 'Valor não alterado';
		}
	}
	
	// Um método público para exibir os dados
	public function exibe() {
		echo $this->nome . ' ' . $this->idade . '<br>';
	}
}

// Pessoa
$pessoa = new Pessoa();

$pessoa->nome  = "Luiz";
$pessoa->idade = 22;

$pessoa->exibe(); // Valor não alterado 22
?>

No trecho de código acima, ao invés de apenas exibir um erro na tela falando que não foi possível alterar a propriedade por ela ser privada, eu altero o valor de uma delas, e mostro na tela que o valor da outra propriedade não pôde ser alterado.

O método {php}__set{/php} recebe dois parâmetros, a propriedade e o valor da mesma. Todas as vezes que você tentar manipular uma propriedade sem visibilidade fora do contexto da classe, ele será chamado e executado, caso configurado.

__get

O método {php}__get{/php} é acionado quando tentamos acessar uma propriedade {php}private{/php} ou {php}protected{/php}. Veja:

<?php
class Pessoa
{
	// Propriedades privadas
	private   $nome  = "Luiz";
	private   $idade = 22;
	
	// __get é invocado quando tentamos acessar uma propriedade protegida ou privada
	function __get( $propriedade ) {
		return 'Propriedade privada: $this->' . $propriedade . 
		' = ' . $this->$propriedade;
	}
}

// Pessoa
$pessoa = new Pessoa();

// Consigo acessar a propriedade privada por conta do método __get
echo $pessoa->nome; // Propriedade privada: $this->nome = Luiz 
?>

No exemplo acima, eu não conseguiria acessar o valor da propriedade {php}nome{/php}, porém, o método {php}__get{/php} me ajuda a exibir este valor.

__call

{php}__call{/php} é invocado quando tentamos acessar um método que não existe.

<?php
class Pessoa
{
	// __call é invocado quando tentamos acessar um método que não existe	
	function __call ( $metodo, $parametros ) {
		echo 'Método ' . $metodo . ' não existe. <br>';
		echo 'Parâmetros enviados: ';
		print_r( $parametros );
		echo '<br>';
	}
}

// Pessoa
$pessoa = new Pessoa();

// Tento acessar um método que não existe
$pessoa->casar('Rose', '16/08/2014');

/*
Retorno:

Método casar não existe.
Parâmetros enviados: Array ( [0] => Rose [1] => 16/08/2014 ) 
*/
?>

Como o método casar não existe, o método {php}__call{/php} é acionado e executado.

__isset

{php}__isset{/php} é invocado quando tentamos utilizar isset ou empty em membros {php}protected{/php} ou {php}private{/php}.

<?php
class Pessoa
{
	// Propriedades
	private $nome = 'Luiz';
	
	// __isset é invocado quando tentamos utilizar isset ou empty em métodos protegidos ou privados
    public function __isset($name) {
        return isset($this->$name) && !empty($this->$name);
    }
}

// Pessoa
$pessoa = new Pessoa();

// Utiliza isset em $pessoa->nome
if ( isset( $pessoa->nome ) ) {
	echo 'Dado existe.';
}
?>

__unset

{php}__unset{/php} é chamado quando tentamos utilizar unset em propriedades {php}protected{/php} ou {php}private{/php}.

<?php
class Pessoa
{
	// Propriedades
	private $nome = 'Luiz';
	
	// __unset é invocado quando utilizamos unset em propriedades protegidas
    public function __unset($name) {
        unset($this->$name);
    }
	
	// Exibe os valores
	public function exibir(){
		echo $this->nome;
	}
}

// Pessoa
$pessoa = new Pessoa();

// Desconfigura $nome
unset( $pessoa->nome );

// Tenta exibir: Notice: Undefined property: Pessoa::$nome
$pessoa->exibir();
?>

__toString

{php}__toString{/php} é chamado quando tentamos exibir um objeto (converter um objeto em string).

<?php
class Pessoa
{
	public function __toString() {
		return 'Isso é um objeto amigo.';
	}
}

// Pessoa
$pessoa = new Pessoa();

// Exibe: Isso é um objeto amigo
echo $pessoa;
?>

__callStatic

{php}__callStatic(){/php} é disparado quando invocamos métodos inacessíveis em um contexto estático.

<?php
class Pessoa
{
	protected static function mensagem(){
		echo 'Uma mensagem simples.';
	}
	
	//__callStatic() é disparado quando invocando métodos inacessíveis em um contexto estático. 
	public static function __callStatic( $m, $p ){
		echo 'Você não pode acessar o método: ' . $m . '<br>';
		echo 'Parâmetros enviados: ';
		print_r( $p );
	}
}

// Chama o método estático
Pessoa::mensagem();

/* Retorna
Você não pode acessar o método: mensagem
Parâmetros enviados: Array ( ) 
*/
?>

__invoke

O método {php}__invoke(){/php} é chamado quando um script tenta chamar um objeto como uma função.

<?php
class Pessoa
{
	// O método __invoke() é chamado quando um script tenta chamar um objeto como uma função. 
	public function __invoke(){
		return true;
	}
}

// Instância
$pessoa = new Pessoa;

// Tenta usar como função
if ( $pessoa() ) {
	echo 'OK';
}
?>

Concluindo

Como você pôde perceber, os métodos mágicos sempre começam com {php}__{/php}, por isso, é recomendado que você não crie seus métodos começando com esses caracteres.

Não falamos de todos os métodos mágicos existentes, porém, esses são os que mais utilizo em meus scripts. Se quiser saber mais sobre os métodos mágicos em PHP, acesse PHP: Métodos Mágicos (manual do PHP).

Não deixe de seguir todas as aulas do nosso curso gratuito de PHP e de PHP Orientado a Objetos.

Caso tenha dúvidas, não hesite em comentar.