Em primeiro lugar, acabei escrevendo um texto um tanto extenso, queria simplificar as coisas mas não é tão simples. Em segundo lugar, programadores com experiências diferentes tem opniões diferentes, logo, acima de tudo, você deve deixar a sua experiência e o seu trabalho dizer se é bom ou ruim para o desenvolvimento dos seus projetos. Então, vamos lá.   Desde o momento que colocaram os métodos mágicos, eu fiz uso de quase todos para teste (alguns métodos vieram depois), mas em desenvolvimento, nunca usei mais que quatro (__construct, __destruct, __clone, __toString) e uma única exceção foi o uso de __invoke para um wrapper de Closures, no qual, era feita a chamada da closure através do __invoke.

Métodos como __sleep e __wakeUp são facilmente substituídos pela interface Serializable, que, ao meu ver, é uma melhor prática de uso, uma vez que uma interface define o comportamento de uma classe.

Os métodos __unset, __isset, __set_state eu nunca utilizei, então não vou poder lhe informar com precisão usos práticos.

Os métodos mágicos como __set, __get, __call e __callStatic eu vejo como poder dar uma maior flexibilidade a um objeto e/ou tornar objetos realmente dinâmicos (como atributos variados). Aqui no fórum você deve encontrar alguns exemplos de transferência de dados entre controller e view utilizando métodos mágicos.

A vantagem básica é o dinamismo e o não "entupimento" de métodos em uma classe. As desvantagens estão na garantia dos atributos/métodos (por ex: você vai precisar saber como tal atributo foi incluído, como nome e/ou tipo) e as validações. Não estou dizendo que não há, mas é mais trabalhoso.

Só que, não somente o que o método pode fazer ou não que define se ele é bom ou ruim, também depende do escopo de uso e a forma que está sendo usado.

Há também o detalhe que, se você estiver programando sozinho, não será um problema o uso pois você, e somente você, definiu nomes e atributos. Mas, em uma equipe de desenvolvimento, você trabalhando na View, e o seu amigo desenvolvendo a parte de Model e Controller, lhe passa uma lista de usuário: $list = new StdClass(); $list->userList = array('Fulano' , 'Ciclano' , 'Beltrano');
E você deseja trabalhar com esses dados na view: $usuarioList = $list->usuarioList; $count = $usuario->count(); while($usuarioList->valid()) { $usuario = $usuarioList->current(); echo $usuario; $usuario->next(); } Mesmo você conhecendo os objetos que está trabalhando (StdClass é uma classe standard do PHP que implementa os métodos __set e __get). Não há garantias de que você receberá o atributo correto, com nome correto e do tipo correto.

No primeiro código, eu estou utilizando um simples array, no segundo, estou esperando receber uma classe do tipo ArrayIterator. Os dados vieram do back-end para o front-end.   O front solicitou uma lista com o nome dos usuários, e foi realmente passada uma lista com os nomes dos usuários. Mas na forma que o front esperava ou da forma que o back imaginou?   Se, em algum momento, você precisar pedir para o programador back-end como ele está passando os dados para você, isso é ruim do ponto de vista da Orientação à Objetos (e veja que não estamos falando de usar algum tip de debug para verificar os dados, tal qual var_dump).   Mas também, devemos falar das vantagens, e algumas formas de uso, por exemplo: class DataTraversable implements IteratorAggregate { private $data = array(); public function __set($name , $value) { $this->data[$name] = $value; } public function __get($name) { if (array_key_exists($name , $this->data)) { return $this->data[$name]; } $trace = debug_backtrace(); throw new RuntimeException( sprintf( 'Undefined property via __get(): %s in %s on line %s', $name, $trace[0]['file'], $trace[0]['line'] ) ); } public function getIterator() { return new ArrayIterator($this->data); } } Basicamente, é uma classe com "dados transponíveis". Eu posso definir e pegar dados utilizando os métodos mágicos __set e __get. Além disso, eu utilizo a interface IteratorAggregate, que, dessa forma, posso utilizar a classe em uma estrutura de controle(foreach, por exemplo).   Vamos a execução: $dataTraversable = new DataTraversable(); $dataTraversable->nome = 'Gabriel'; $dataTraversable->sobrenome = 'Heming'; $dataTraversable->linguagemProgramacao = 'PHP'; foreach($dataTraversable AS $key => $data) { echo $key.' -> '.$data.'<br />'; } E como Saída:   No exemplo acima, é perfeitamente vista a vantagem do uso dos métodos mágicos. Pois você poderá inserir atributos dinâmicos, sem necessidade de validação, recuperar um valor em específico (ou tratar através de uma exception quando o valor não existir) e, além de tudo, iterar sobre os atributos. Só não podemos deixar de lado, que a garantia de iterar sobre o objeto é feita pela Interaface e não pelo uso dos métodos mágicos.   Como conclusão, e acima de qualquer exemplo ou "mantra", quem deve decidir o que é bom ou ruim para com o seu trabalho, é somente você. Se lhe facilitar o trabalho e você só ganhar com isso, parabéns, use-o. Mas se isso começar a dar mais problemas que solução e, principalmente, a manutenção se tornar muito custosa, você terá um sério problema. Lembrando que a OO, além de abstrair e tornar a programação mais próxima do mundo real, tem como objetivo, quando bem empregado, reusabilidade e, consequentemente, reduzir custos de manutenção.   Lembrando como eu comentei lá no início, experiências e projetos diferentes, tendem a ter perpectivas e opniões diferentes.   Esse artigo pode explanar alguns pontos também: http://imasters.com.br/artigo/21865/php/phpog-uma-questao-de-design/