Se você trabalha com PHP Orientado à Objetos e gosta de manter seus dados encapsulados de uma forma “elegante”, você inevitavelmente acaba escrevendo métodos de set e get para os atributos privados da sua classe. Porém, a versão 5 do PHP conta com uma funcionalidade que pouquíssima gente utiliza (talvez porque a maioria dos programadores PHP não sabem programar) que são as Properties.
O que são Properties?
Uma property permite que você associe rotinas de acesso à um atributo da sua classe. Você consegue definir que sempre que houver uma atribuição sobre um determinado atributo do seu objeto, seja executado o método X ou então, sempre que esse valor for requisitado seja executado o método Y. O que acontece na realidade é que você define os métodos e regras de set e get para os seus atributos e faz com que eles sempre sejam executados de forma transparente pela sua classe, e assim você consegue utilizar normalmente seus atributos.
Veja um exemplo bem simples do conceito sendo aplicado:
<?php
class People {
private $name;
function __set($property, $value) {
switch ($property) {
case 'Name': $this->name = ucwords(strtolower($value)); break;
}
}
function __get($property) {
switch ($property) {
case 'Name': return "Meu nome é {$this->name}."; break;
}
}
}
$p = new People();
$p->Name = 'ARTHUR FURLAN';
echo $p->Name;
?>
Resultado:
Meu nome é Arthur Furlan.
Repare que apesar de ter defindo o valor ‘ARTHUR FURLAN’ para o atributo, a string armazenada é ‘Arthur Furlan’. Como a atribuição ocorre dentro dos métodos __set() e __get(), você poderia ter uma infinidade de linhas, chamadas de funções e métodos tratando o valor passado antes de defini-lo no seu atributo.
Extendendo o conceito
Como você pôde ver, as rotinas de acesso do seus atributos são independentes. Você pode definir somente o método get e manter o set privado à classe, ou definir um método de set e manter o get privado (apesar de eu ainda não ter achado uma aplicação útil para esse caso =D). Isso é bastante útil, principalmente quando se está trabalhando com registros do banco de dados, pois o valor do campo ‘Id’ de um registro raramente é alterado. Então, nesse caso, seria interessante definirmos para ele, somente uma property de get e deixarmos que todas as suas atribuições sejam feitas internamente à classe.
<?php
class People {
private $id;
private $firstName;
private $lastName;
private $age;
function __set($attribute, $value) {
switch ($attribute) {
case 'FirstName': $this->firstName = ucwords(strtolower($value)); break;
case 'LastName' : $this->lastName = ucwords(strtolower($value)); break;
case 'Age' : $this->age = (int) $value; break;
}
}
function __get($attribute) {
switch ($attribute) {
case 'Id' : return $this->id;
case 'FirstName': return $this->firstName;
case 'LastName' : return $this->lastName;
case 'Age' : return $this->age;
}
}
}
$p = new People();
$p->FirstName = 'Arthur';
$p->LastName = 'Furlan';
$p->Age = 21;
echo "{$p->FirstName} {$p->LastName} ({$p->Age})";
?>
Observações
1. Repare que é possível atribuir valores à atributos que não existem fisicamente no seu objeto, desde que você crie uma property para tratar esse caso, assim como foi utilizado na classe acima.
2 Apesar de definir um atributo como privado e não criar método de get para ele, o programador poderá descobrir o valor do seu atributo através dos comandos print_r() ou var_dump(). Então, esse tipo de prática só não basta para manter um dado do objeto em sigilo.



6 Comments
Legal. Abandonei o php na versão 4.2 qnd resolvi programar somente OO e migrei para Java, e hj tb brinco com Ruby On Rails. Agora, vendo os grandes saltos de melhorias injetados no PHP 5 dá até vontade de voltar a brincar com o php…
Muito legal esse esquema de Property, precisa ser mais divulgado.
Parabéns pelo artigo.
Abraços.
“talvez porque a maioria dos programadores PHP não sabem programar”
Deprimente.
Pelo visto você acha que está no grupo dos que sabe. Pergunta: “elegante” é declarar variáveis com um nome e acessá-las com outro? Se ‘id’ é igual a ‘Id’, não tem sentido a linguagem ser case-sensitive no que diz respeito as variáveis.
Quando você declara uma variável como privada, __set passa a funcionar sem a necessidade da gambiarra da letra maiúscula.
“Apesar de definir um atributo como privado e não criar método de get para ele, o programador poderá descobrir o valor do seu atributo através dos comandos print_r() ou var_dump(). Então, esse tipo de prática só não basta para manter um dado do objeto em sigilo”
Permita-me perguntar se você estava babando enquanto escrevia esse comentário. Estava? Se você não quer que um var_dump mostre o conteúdo de sua variável, retire o metodo __get, oras. Você abre a porta para o retorno da variável a ainda quer que o valor esteja inacessível?
Agora minha dúvida final: se (no inglês) uma classe contém methods e properties, por que cargas d’água “uma property permite que você associe rotinas de acesso à um atributo da sua classe”? Oras, se property é propriedade, o que você está criando são métodos de acesso.
Quanto ao comentário do Mário (”Muito legal esse esquema de Property, precisa ser mais divulgado.”):
Vide manual. Está lá a pelo menos dois anos.
“Use the manual, Luke”.
@Fernando:
> Pelo visto você acha que está no grupo dos que sabe.
Uma coisa não tem necessariamente a ver com a outra! Eu acredito que o PHP seja a linguagem com o maior número de adeptos no nosso país, isso faz com que inevitavelmente existam pessoas que não possuam conhecimento necessária para trabalharem profissionalmente com a tecnologia (o que é normal, diga-se de passagem). Porém no PHP, diferentemente das outras linguagens, a maior parte dessas pessoas estão empregadas (ok, isso não é normal)! Não vou entrar nos méritos de porque isso acontece ou porque deixa de acontecer, mas isso é fato (concordamos nesse ponto pelo menos!?) e está se tornando cada vez mais comum. Porém esse é um outro assunto, muito mais longo do que o tratado nesse post.
> Pergunta: “elegante” é declarar variáveis com um nome e acessá-las com outro? Se ‘id’ é igual a ‘Id’, não tem sentido a linguagem ser case-sensitive no que diz respeito as variáveis.
Você precisa aprender à abstrair os conceitos por detrás dos exemplos… Mas vamos começar comentando que uma property não é uma variável física, ela está mais para um ponteiro do que para uma variável propriamente dita. Além disso, declarar uma variável com letra minúscula e acessá-la com letra maiúscula é apenas um padrão que eu costumo adotar, porém existem n outros padrões sobre o assunto. Alguns deles sugerem colocar ‘_’ na frente das variáveis, outro sugerem ‘m_’ e por ae vai… Acredite, definitivamente o conceito exposto neste post não é “declare seus atributos com letras minúscula e suas propriedades com letras maiúsculas”.
> Se você não quer que um var_dump mostre o conteúdo de sua variável, retire o metodo __get, oras. Você abre a porta para o retorno da variável a ainda quer que o valor esteja inacessível?
Na realidade, esse comentário foi só para alertar as pessoas que no PHP é possível ver o valor de uma variável privada com as funções print_r() ou var_dump(), e que o uso dessa técnica não previne isso. Teste você mesmo:
> Agora minha dúvida final: se (no inglês) uma classe contém methods e properties, por que cargas d’água “uma property permite que você associe rotinas de acesso à um atributo da sua classe”? Oras, se property é propriedade, o que você está criando são métodos de acesso.
Relembrando o ponto citado anteriormente sobre abstrair conceitos de exemplos… O que uma property faz é associar uma variável à um método/rotina/whatever, nada mais do que isso.
> Vide manual. Está lá a pelo menos dois anos.
Sim. Todas as funcionalidades da linguagem estão lá.
http://br.php.net/manual/pt_BR/language.oop5.overloading.php
Não ligue para o que alguns ignorantes possam vir a dizer. Não que eu esteja dizendo que o Fernando é ignorante, mas você sabe como é… a internet está cheia deles!
Seu artigo é excelente! O dia que as pessoas entenderem os verdadeiros benefícios da programação OO, o nível das aplicações web irá crescer muito.
Parabéns!
Acho que Fernando não sabe programar…
Qualquer pessoa que sabe o mínimo de programação, tem certeza de que a propriedade foi criada para simplificar a forma de acesso e poder ter validação e tratamento da informação da propriedade.
Programei muito tempo em delphi, o php tem suas peculiaridades…
Outra coisa que Fernando não entendeu é que $p->FirstName é diferente de $p->firstName, o primeiro é Propriedade e o segundo Atributo, não é que se possa acessar com case-insensitive como ele disse… é que realmente são coisas completamente diferentes…
se $p->firstName fosse publica poderiamos acessá-lo e não haveria nenhum tipo de tratamento completamente diferente ocorre em $p->FirstName que vc pode atribuir methodos de read e write para tratar e validar os dados.
Deixo aqui que fico feliz pelo php evoluir, mas gostaria que as propertys fossem mais parecida com as do delphi, é mais clara a escrita.
Do mais o php é o exemplo de como o simples é funcional e rápido!!!
Abraços e parabéns
Tenho que concordar com o Fernando em algumas coisas que disse. Quando alguém generaliza (como em “talvez porque a maioria dos programadores PHP não sabem programar”), acaba passando um certo ar de superioridade. Se não foi sua intenção, é melhor pensar um pouco mais antes de escrever.
Anos atrás, ensinava-se que um objeto possuia campos, atributos ou propriedades. Todos os nomes revelavam a mesma coisa. Mas hoje em dia, parece que isso perdeu o sentido. Alguns passaram a chamar somente de campos (ou atributos) e passaram a chamar de propriedades os campos (ou atributos) com metodos “getters” e “setters”. Para mim, isso é o mesmo que usar Dreamweaver e chamar o elemento div de layer.
__set não serve pra isso. Vide o conceito por detrás do comentário do Daniel: “mas gostaria que as propertys fossem mais parecida com as do delphi, é mais clara a escrita”.
Pegue uma classe com meia-dúzia de atributos com validações complexas e faça tudo através do __set. Percebe como perde o sentido? tudo o que for relativo a essas variáveis vai estar dentro de um grande método difícil de se manter.
My two cents
Post a Comment