terça-feira, dezembro 17, 2013

Restringindo a criação de atributo dinâmico em PHP

Muita gente não gosta de uma característica existente em PHP que permite a definição de atributos dinâmicos em objeto. Esta prática de fato frusta aos programadores menos experientes e aos veteranos causa, no mínimo, um pouco de trabalho para organizar a "casa".

Tal característica pode ser evitada se aplicado um pouco de organização. A organização referida trata-se na verdade em criar uma hierarquia de classes com uma super classe base e tomar o cuidado, por assim dizer, de todos os demais objetos descendam de uma classe filha da classe base.

Mas Augusto, você está propondo que seja criando uma super classe para todo um sistema? Exatamente!

Muitos programadores, principalmente PHPs, se assustam com esta idéia. Pior, por vezes não conseguem visualizar como fazer ou vislumbrar os benefícios desse tipo de abordagem. Mas isto ficará para um post futuro, por hora, vamos nos concentrarmos no assunto de hoje: Restringir a definição de atributos dinâmicos.

Restringir a criação de atributos dinâmicos pode ser feito com o uso do método __set (documentação). Este método recebe exatamente dois parâmetros e é executado sempre que uma tentativa de atribuir um valor qualquer a um atributo do objeto for realizada.

O fragmento de código abaixo demonstra a atribuição dinâmica.

# definição da classe Foo
class Foo {}

# instancia de Foo
$foo = new Foo;

# atributo dinâmico 
$foo->bar = 'value';

var_dump($foo);

// saída: object(Foo)#1 (1) { ["bar"]=> string(5) "value" } 

Agora apliquemos a restrição da definição dinâmica.

# definição da classe Foo
class Foo {
    public function __set ($name, $args)
    {
       return;
    }
}

# instancia de Foo
$foo = new Foo;

# atributo dinâmico 
$foo->bar = 'value';

var_dump($foo);

// saída: object(Foo)#1 (0) { }


Note que no segundo fragmento de código o atributo bar não foi criado, ao contrário do primeiro.

Como pode ser observado, definir o método __set para cada classe torna o trabalho inviável e é nesse ponto que entra o uso da hierarquia mencionada  acima.

abstract class Base
{
    public function __set ($name, $args)
    {
       return;
    }
}

# definição da classe Foo
class Foo extends Base
{
}

# instancia de Foo
$foo = new Foo;

# atributo dinâmico
$foo->attr = 'value';

var_dump($foo);

// Saída: object(Foo)#1 (0) { }

Com isso qualquer objeto oriundo de uma classe filha de Base não permitirá a definição de um atributo que não tenha sido explicitamente definido na classe referente ao objeto.

Nenhum comentário: