Introdução: O Que é Orientação a Objetos em PHP
Orientação a Objetos (OO) é um paradigma de programação que organiza o código em estruturas chamadas classes e objetos, permitindo criar aplicações mais modulares, reutilizáveis e fáceis de manter. Em PHP, desde a versão 5, você tem suporte robusto a OO, tornando-o uma linguagem viável para projetos de médio e grande porte. Nesta aula, você aprenderá a estrutura fundamental: como declarar classes, instanciar objetos e trabalhar com propriedades.
A grande vantagem de usar OO é a organização do código. Em vez de funções soltas espalhadas por arquivos, você agrupa dados (propriedades) e comportamentos (métodos) relacionados em uma única classe. Isso reduz bugs, facilita testes e melhora a legibilidade.
Classes e Objetos: Fundamentos Práticos
Declarando uma Classe
Uma classe é um "molde" que define a estrutura de um objeto. Você a declara com a palavra-chave class:
<?php
class Produto {
// Propriedades (atributos)
public $nome;
public $preco;
public $estoque;
// Método construtor (inicializa o objeto)
public function __construct($nome, $preco, $estoque) {
$this->nome = $nome;
$this->preco = $preco;
$this->estoque = $estoque;
}
// Método simples
public function descricao() {
return "Produto: {$this->nome}, Preço: R$ {$this->preco}";
}
}
?>
Instanciando Objetos
Um objeto é uma instância de uma classe. Para criar um, use a palavra-chave new:
<?php
// Criando dois objetos diferentes da mesma classe
$produto1 = new Produto("Notebook", 2500.00, 5);
$produto2 = new Produto("Mouse", 45.50, 20);
// Acessando propriedades e métodos
echo $produto1->descricao(); // Saída: Produto: Notebook, Preço: R$ 2500
echo $produto1->nome; // Saída: Notebook
?>
Cada objeto tem seus próprios valores de propriedades, independentes um do outro. O método __construct (construtor) é chamado automaticamente quando você usa new, sendo ideal para inicializar valores.
Propriedades: Tipos de Acesso e Visibilidade
Modificadores de Acesso
As propriedades (e métodos) possuem modificadores de visibilidade que controlam quem pode acessá-las:
<?php
class Conta {
// Pública: acessível de qualquer lugar
public $titular;
// Protegida: acessível apenas dentro da classe e subclasses
protected $saldo;
// Privada: acessível apenas dentro da classe
private $senha;
public function __construct($titular, $saldo, $senha) {
$this->titular = $titular;
$this->saldo = $saldo;
$this->senha = $senha;
}
// Método público para acessar propriedade protegida
public function getSaldo() {
return $this->saldo;
}
// Método para modificar saldo com validação
public function depositar($valor) {
if ($valor > 0) {
$this->saldo += $valor;
return true;
}
return false;
}
// Método privado (uso interno apenas)
private function validarSenha($senha) {
return $this->senha === $senha;
}
}
// Usando a classe
$conta = new Conta("João Silva", 1000, "1234");
echo $conta->titular; // Funciona (público)
echo $conta->getSaldo(); // Funciona (método público retorna valor protegido)
// echo $conta->saldo; // Erro! É protegido
// echo $conta->senha; // Erro! É privado
?>
Por Que Usar Private e Protected?
Usar private e protected é uma boa prática chamada encapsulamento. Você expõe apenas o necessário através de métodos públicos, controlando como os dados são acessados e modificados. No exemplo acima, alguém não consegue depositar valores negativos na conta porque a validação está no método depositar().
Propriedades Tipadas e Inicialização
Propriedades com Type Hints (PHP 7.4+)
A partir do PHP 7.4, você pode declarar o tipo das propriedades, tornando o código mais seguro:
<?php
class Autor {
// Declarando tipos das propriedades
private string $nome;
private int $idade;
private float $royalties;
private array $livros;
public function __construct(string $nome, int $idade) {
$this->nome = $nome;
$this->idade = $idade;
$this->royalties = 0.0;
$this->livros = [];
}
public function adicionarLivro(string $titulo): void {
$this->livros[] = $titulo;
}
public function obterLivros(): array {
return $this->livros;
}
public function receberRoyalties(float $valor): void {
$this->royalties += $valor;
}
public function dados(): string {
return "{$this->nome} ({$this->idade} anos) - {$this->royalties} reais";
}
}
// Usando
$autor = new Autor("Machado de Assis", 69);
$autor->adicionarLivro("Dom Casmurro");
$autor->adicionarLivro("Memórias Póstumas de Brás Cubas");
$autor->receberRoyalties(500.50);
echo $autor->dados();
// Saída: Machado de Assis (69 anos) - 500.5 reais
?>
Com type hints, se você tentar atribuir um tipo incompatível (por exemplo, uma string a uma propriedade declarada como int), PHP lançará um erro, evitando comportamentos inesperados.
Boas Práticas e Padrões Comuns
Getters e Setters
Para propriedades private ou protected, crie métodos para ler (getter) e modificar (setter) valores:
<?php
class Usuario {
private string $email;
private int $idade;
public function __construct(string $email, int $idade) {
$this->setEmail($email);
$this->setIdade($idade);
}
public function getEmail(): string {
return $this->email;
}
public function setEmail(string $email): void {
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->email = $email;
} else {
throw new Exception("Email inválido!");
}
}
public function getIdade(): int {
return $this->idade;
}
public function setIdade(int $idade): void {
if ($idade >= 18) {
$this->idade = $idade;
} else {
throw new Exception("Usuário deve ter 18 anos ou mais!");
}
}
}
$usuario = new Usuario("joao@example.com", 25);
echo $usuario->getEmail(); // joao@example.com
$usuario->setIdade(30); // Funciona
// $usuario->setIdade(10); // Lança exceção
?>
Getters e setters permitem validação de dados antes de atribuir valores, garantindo a integridade do objeto. Isso é essencial em aplicações profissionais.
Conclusão
Nesta aula, você aprendeu que classes são moldes e objetos são instâncias desses moldes. Você entendeu como declarar classes com propriedades e métodos, instanciar objetos com new e usar o construtor para inicializar valores. Também conheceu os modificadores de acesso (public, protected, private) e percebeu que o encapsulamento e a validação através de getters/setters são fundamentais para código robusto e seguro. Por fim, aprendeu que type hints em propriedades trazem segurança de tipo e deixam o código mais legível e fácil de manter. Esses conceitos são a base para herança, polimorfismo e design patterns que virão em próximos estudos.