# Orientação a objetos em PHP

> Orientação a objetos em PHP: classes, interfaces, traits e enums, novos recursos do PHP 8.0 ao 8.4 e a relação com a desserialização e a segurança.

Fonte: https://phpsos.de/pt/php/objektorientierung/  
Atualizado em: 25/10/2026  
Prestador: PHP SOS, Assistência de emergência PHP e segurança de servidores. Ajuda imediata por WhatsApp: https://wa.me/491736494914?text=Ol%C3%A1%2C%20PHP%20SOS%2C%20precisamos%20de%20ajuda%20com%20o%20nosso%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Site%3A%20%E2%80%A6

**Em resumo:** A programação orientada a objetos (POO) reúne os dados e as respetivas funções em classes. Para isso, o PHP oferece classes, classes abstratas, interfaces, traits e, desde o PHP 8.1, enums. Do PHP 8.0 ao 8.4 foram acrescentados muitos recursos da linguagem, como a promoção de propriedades no construtor, `readonly`, property hooks e visibilidade assimétrica. Importante para a segurança: o código bem encapsulado é mais fácil de verificar, e os métodos mágicos tornam perigosa a desserialização insegura. Contra vulnerabilidades no interpretador, como o PHP2Shell, a POO não ajuda.

## O que significa a programação orientada a objetos em PHP

Em vez de usar funções soltas e variáveis globais, uma classe descreve uma coisa do mundo do negócio: uma encomenda, um cliente, uma fatura. Define que dados lhe pertencem (propriedades) e o que se pode fazer com eles (métodos). Um objeto é uma instância concreta dessa classe.

Para quem decide, isto tem um valor prático: o código orientado a objetos, com classes claras, pode ser melhor testado, verificado e entregue a prestadores de serviços. As aplicações PHP antigas, feitas de muitos scripts isolados com variáveis globais, são, pelo contrário, difíceis de manter e propensas a erros nas atualizações.

Uma ideia central é o encapsulamento: uma classe só disponibiliza para o exterior os métodos de que outros realmente precisam e protege o seu estado interno. Uma encomenda só pode, por exemplo, ser marcada como paga através de um método que verifica antes se isso é sequer permitido. Concentrar essas regras num único ponto é também um ganho para a segurança.

## Os blocos de construção em resumo

| Bloco | Finalidade | Exemplo curto |
|---|---|---|
| Classe | planta para objetos com propriedades e métodos | `class Rechnung { ... }` |
| classe abstrata | base comum, não instanciável diretamente | `abstract class Zahlart { ... }` |
| Interface | contrato: que métodos uma classe tem de oferecer | `interface Versandfaehig { ... }` |
| Trait | métodos reutilizáveis para classes sem classe-mãe comum | `trait MitZeitstempel { ... }` |
| Enum | conjunto fixo de valores permitidos como tipo próprio, desde o PHP 8.1 | `enum Status { case Offen; ... }` |

As visibilidades (`public`, `protected`, `private`) regulam quem pode aceder a propriedades e métodos. As classes são organizadas em espaços de nomes e carregadas por um autoloader; como isso funciona mostra-o a página [Espaços de nomes e autoloading](https://phpsos.de/pt/php/namespaces-autoloading/).

## PHP moderno: as novidades do 8.0 ao 8.4

Os recursos da linguagem seguintes estão documentados no manual do PHP ou nos anúncios de lançamento:

| Versão | Novidade |
|---|---|
| 8.0 | promoção de propriedades no construtor, operador nullsafe `?->`, `::class` em objetos |
| 8.1 | propriedades `readonly`, enums, `new` em inicializadores, `final` para constantes de classe |
| 8.2 | classes `readonly`; as propriedades dinâmicas passam a ser consideradas obsoletas |
| 8.3 | atributo `#[\Override]`, constantes de classe com tipo |
| 8.4 | property hooks, visibilidade assimétrica, `new` sem parênteses envolventes |

Um exemplo que combina vários destes recursos:

```php
<?php
declare(strict_types=1);

enum Status: string
{
    case Offen = 'offen';
    case Bezahlt = 'bezahlt';
}

final class Bestellung
{
    public function __construct(
        public readonly int $id,
        public private(set) Status $status = Status::Offen,  // a partir do PHP 8.4
    ) {}

    public function alsBezahltMarkieren(): void
    {
        $this->status = Status::Bezahlt;
    }
}

$b = new Bestellung(42);
$b->alsBezahltMarkieren();
echo $b->status->value;              // bezahlt
$s = Status::tryFrom('storniert');   // null em vez de erro
```

O `readonly` impede que o ID seja alterado depois de criado. O `private(set)` permite a leitura a partir do exterior, mas a escrita apenas dentro da classe. Estas garantias no código tornam menos prováveis os erros que, de outro modo, só se notariam em funcionamento. Os tipos subjacentes explica-os a página [O sistema de tipos do PHP](https://phpsos.de/pt/php/typsystem/).

### Armadilhas de atualização no código orientado a objetos

Para as aplicações mais antigas, duas alterações são particularmente relevantes. Desde o PHP 8.2.0, a criação de propriedades dinâmicas, ou seja, de propriedades não declaradas na classe, é obsoleta, a menos que a classe tenha o atributo `#[\AllowDynamicProperties]`. O código mais antigo usa-as muitas vezes sem se aperceber e enche então os registos de avisos. Além disso, segundo o manual, as propriedades com tipo têm de estar inicializadas antes da primeira leitura, caso contrário o PHP lança um `Error`.

É útil o atributo `#[\Override]`, do PHP 8.3: marca um método como substituição de um método da classe-mãe. Se esse método deixar de existir, por exemplo após uma mudança de nome numa biblioteca, o PHP assinala um erro, em vez de deixar o método a funcionar em silêncio no vazio. Estas verificações tornam as atualizações mais previsíveis; nos projetos antigos bloqueados, ajuda a nossa [migração para uma versão do PHP suportada](https://phpsos.de/pt/leistungen/php-migration-legacy/).

## Objetos e memória

Em PHP, os objetos são passados através de identificadores (handles). Quando se passa um objeto a uma função, esta trabalha com o mesmo objeto, não com uma cópia. É eficiente, mas leva facilmente a referências circulares, por exemplo quando uma encomenda conhece as suas linhas e cada linha conhece de novo a sua encomenda. Estes ciclos não são limpos só pela contagem de referências; para isso, o PHP tem um garbage collector próprio. Os detalhes estão na página [Gestão de memória em PHP](https://phpsos.de/pt/php/speicherverwaltung/).

## POO e segurança: métodos mágicos e desserialização

O PHP conhece métodos mágicos, que são chamados automaticamente, como `__construct`, `__destruct`, `__toString`, `__get` ou `__wakeup`. É prático, mas tem um lado sombrio: quando uma aplicação transforma dados alheios de novo em objetos com `unserialize()`, um atacante pode determinar que classes são criadas e, com isso, desencadear código existente em métodos mágicos. Como evitá-lo descreve-o o guia [Desserialização insegura em PHP](https://phpsos.de/pt/ratgeber/deserialisierung-php/). Em resumo: para a troca de dados, usar `json_encode()` e `json_decode()`, e usar `unserialize()` apenas para dados próprios e de confiança, idealmente com a opção `allowed_classes`.

No caso do PHP2Shell, o bom código orientado a objetos não ajuda. A CVE-2026-109618 e a CVE-2026-109619 estão no interpretador e, no mod_php, segundo a equipa do PHP, foi demonstrado um exploit antes de o código da aplicação ser executado. É obrigatória a atualização para o PHP 8.5.12, 8.4.27, 8.3.36 ou 8.2.35 e o reinício de todos os processos PHP.

## Como ajuda concretamente a PHP SOS?

- Avaliamos a estrutura da sua aplicação e mostramos que partes dificultam uma atualização para uma versão do PHP suportada.
- Procuramos de forma dirigida padrões de risco, como `unserialize()` sobre dados alheios e métodos mágicos perigosos.
- Verificamos desenvolvimentos próprios no âmbito de uma [auditoria de segurança e teste de intrusão](https://phpsos.de/pt/leistungen/sicherheitsaudit-penetrationstest/).
- Aplicamos a atualização do PHP, reiniciamos todos os workers e testamos depois a aplicação.


## Perguntas frequentes

**O PHP é uma linguagem orientada a objetos?**  
O PHP suporta tanto código procedimental como orientado a objetos. As frameworks, os núcleos de CMS e os sistemas de loja são hoje, porém, na sua maioria construídos de forma orientada a objetos, com classes, interfaces e espaços de nomes.

**Qual é a diferença entre interface e classe abstrata?**  
Uma interface descreve apenas que métodos uma classe tem de oferecer. Uma classe abstrata pode conter também código e propriedades, mas não pode ser instanciada diretamente. Uma classe pode ter várias interfaces, mas só uma classe-mãe.

**Desde quando existem enums no PHP?**  
As enumerações surgiram com o PHP 8.1. Substituem coleções de constantes por um tipo próprio que só admite os casos definidos. Os backed enums têm, além disso, um valor int ou string.

**Porque é que os métodos mágicos são relevantes para a segurança?**  
Métodos como __destruct ou __wakeup são chamados automaticamente pelo PHP, por exemplo ao desserializar dados. Se dados alheios chegarem sem verificação ao unserialize(), podem desencadear fluxos inesperados em classes existentes.

## Fontes

- [Manual do PHP: classes e objetos, fundamentos](https://www.php.net/manual/de/language.oop5.basic.php)
- [Manual do PHP: propriedades](https://www.php.net/manual/en/language.oop5.properties.php)
- [Manual do PHP: visibilidade](https://www.php.net/manual/en/language.oop5.visibility.php)
- [Lançamento do PHP 8.1](https://www.php.net/releases/8.1/en.php)
