DEV Community

William Martins 🇧🇷
William Martins 🇧🇷

Posted on

Property Hooks no PHP 8.4

Property Hooks

Os property hooks são funções que controlam como uma propriedade é setada ou como seu valor é lido. Esta funcionalidade é comum em linguagens orientadas a objeto, mas, até então, o PHP não oferecia suporte nativo. Tradicionalmente, a alternativa era recorrer a funções getter/setter ou fazer uso de métodos mágicos. Contudo, por 35 votos a 1, a RFC dos property hooks foi aprovada para a próxima versão do PHP. Este artigo explora as abordagens atuais e como os property hooks podem nos ajudar na validação dos dados.

Getter e Setter

Nesta abordagem, definimos a propriedade email como privada e a só pode ser acessada através da função getEmail/setEmail. Como queremos validar o email, incluímos essa validação no set.

class User
{
    private string $email;

    public function getEmail(): string
    {
        return $this->email;
    }

    public function setEmail(string $email): void
    {
        if (! filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new Exception('Invalid email');
        }
        $this->email = $email;
    }
}

$user = new User();
$user->setEmail('valido@hotmail.com');
echo $user->getEmail(); //valido@hotmail.com
Enter fullscreen mode Exit fullscreen mode

Essa abordagem é bastante comum, mas é muito verbosa e não funciona bem quando trabalhamos com algum ORM.

Propriedades mágicas

Aqui quem não tá acostumado com a ideia dos métodos mágicos do PHP fica maluco.

A ideia é que sempre que uma propriedade for acessada, vai chamar o método __get e passar o nome da propriedade como parâmetro.
Quando for definir alguma propriedade o método __set é executado, passando o nome da propriedade e o valor.

Não preciso dizer que é fácil ficar confuso quando temos muitas prioridades já que uma única função lida com todas as propriedades da classe.

class User
{
    private string $properties = [];

    public function __get($property)
    {
        return $this->properties[$property] ?? null
    }

    public function __set($property, $value)
    {
        switch ($property) {
            case 'email':
                if (! filter_var($value, FILTER_VALIDATE_EMAIL)) {
                    throw new Exception('Email inválido');
                }
                $this->properties['email'] = $value;
                break;
            case 'name':
                $this->properties['name'] = $value;
                break;
        }
    }
}
//

$user = new User();
$user->name = 'John Doe';
$user->email = 'invalido'; //Exception: Email inválido
echo $user->getEmail();
Enter fullscreen mode Exit fullscreen mode

Normalmente essa é a solução adotadas por ORMs, porque as propriedades não precisam de fato existirem no objeto e tudo é passado para os métodos mágicos.

property hooks

Com a chegada do properties hooks, a definição de como uma propriedade vai ser acessada fica no local da declaração da propriedade, separando melhor as responsabilidades e adotando uma abordagem um pouco mais declarativa.

Exemplo de set

class User
{
    public string $name;
    public string $email {
         set {
            if (! filter_var($value, FILTER_VALIDATE_EMAIL)) {
                throw new Exception('Email inválido');
            }
            $this->_email = $value;
        }
    }
}
//

$user = new User();
$user->name = 'John Doe';
$user->email = 'invalid'; //Exception: Email inválido
echo $user->getEmail();
Enter fullscreen mode Exit fullscreen mode

Exemplo de get

class User
{

    public string $fullName {
        get {
            return "$this->firstName $this->lastName";
        }
    }

    public function __construct(private readonly string $firstName, private readonly string $lastName)
    {
    }


}
//

$user = new User("Roberto", "Murari");
echo $user->fullName; //Roberto Murari
Enter fullscreen mode Exit fullscreen mode

Conclusão

Os property hooks prometem transformar a forma como gerenciamos e acessamos propriedades em classes PHP, oferecendo uma sintaxe mais limpa e um controle mais fino. Não vem como substituição aos métodos mágicos ou uso de funções getter/setter mas uma nova alternativa que podemos utilizar onde fizer mais sentido.

Top comments (0)