Boa Noite
Estou começando a estudar PHP OOP e me deparei com o metodo magico __set e __get.
Eu entendi que com esses metodos, eu posso criar um atributo em tempo de execucao, ou seja, não preciso declara-lo.
Isso não quebra regras de OOP. ?
Esse método é muito utilizado pelos programas PHP ? Ou somente em situações especiais ?
Atualmente programa em Delphi, mas conheço um pouco de C# e Java. Nunca vi nada parecido, mas nestas linguagens a tipagem é forte
e estatica e nao como o PHP com tipagem fraca e dinamica..
Não gostaria de ficar usando algo que não seja muito padrão entre a comunidade de programadores PHP .
Grato
Tone
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/