__get, __set, __isset, __unset
Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy — lição 46 de 91.
O PHP fornece quatro métodos mágicos que interceptam o acesso a propriedades: __get(), __set(), __isset() e __unset(). Estes são acionados quando você tenta acessar propriedades que não existem ou estão inacessíveis.
O método __get() é chamado ao ler uma propriedade inacessível, enquanto o __set() lida com a escrita em uma. Isso permite que você crie propriedades dinâmicas ou adicione lógica quando as propriedades são acessadas:
<?php
class DynamicObject {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
}
$obj = new DynamicObject();
$obj->title = "Hello";
$obj->count = 42;
echo $obj->title . " - " . $obj->count;
Saída:
Hello - 42O método __isset() é acionado por isset() ou empty(), e o __unset() responde à função unset():
<?php
class DynamicObject {
private array $data = [];
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
public function __unset(string $name): void {
unset($this->data[$name]);
}
}
$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing";
Saída:
existsEstes métodos são comumente usados para criar contêineres de dados flexíveis, implementar lazy loading ou construir objetos que se comportam como arrays, mantendo uma estrutura orientada a objetos.
Desafio
FácilVamos construir um gerenciador de configuração flexível que armazena configurações dinamicamente usando métodos mágicos. Sua classe interceptará o acesso a propriedades para gerenciar valores de configuração, verificar se as configurações existem e removê-las quando necessário — tudo sem definir explicitamente cada propriedade.
Você organizará seu código em dois arquivos:
Config.php— Crie uma classeConfigque use um array privado para armazenar valores de configuração internamente. Implemente todos os quatro métodos mágicos de propriedade:__get($name)— Retorna o valor para a chave fornecida, ou"undefined"se a chave não existir__set($name, $value)— Armazena o valor sob a chave fornecida__isset($name)— Retorna se a chave existe na configuração__unset($name)— Remove a chave da configuração
count()que retorne o número de configurações armazenadas.main.php— Inclua o arquivo Config. Você receberá três entradas: um nome de configuração, um valor de configuração e um segundo nome de configuração. Crie uma instância deConfige realize estas operações:- Defina a primeira configuração com o valor fornecido
- Imprima se a primeira configuração existe usando
isset()— saída"exists"ou"missing" - Imprima o valor da primeira configuração
- Imprima a contagem atual de configurações
- Use
unset()para remover a primeira configuração - Imprima se a primeira configuração existe agora — saída
"exists"ou"missing" - Imprima o valor da segunda configuração (que nunca foi definida)
Cada saída deve estar em sua própria linha. Os métodos mágicos permitem que você interaja com seu objeto Config usando a sintaxe natural de propriedade, como $config->theme = "dark" e isset($config->theme), mesmo que nenhuma propriedade real esteja definida.
Folha de consulta
O PHP fornece quatro métodos mágicos para interceptar o acesso a propriedades:
__get(string $name): mixed— Chamado ao ler uma propriedade inacessível__set(string $name, mixed $value): void— Chamado ao escrever em uma propriedade inacessível__isset(string $name): bool— Acionado porisset()ouempty()__unset(string $name): void— Acionado porunset()
Exemplo de __get() e __set():
<?php
class DynamicObject {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
}
$obj = new DynamicObject();
$obj->title = "Hello";
echo $obj->title; // Hello
Exemplo de __isset() e __unset():
<?php
class DynamicObject {
private array $data = [];
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
public function __unset(string $name): void {
unset($this->data[$name]);
}
}
$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing"; // exists
Esses métodos permitem propriedades dinâmicas, lazy loading e contêineres de dados flexíveis, mantendo a estrutura orientada a objetos.
Experimente você mesmo
<?php
require_once 'Config.php';
// Ler entradas
$settingName1 = trim(fgets(STDIN));
$settingValue = trim(fgets(STDIN));
$settingName2 = trim(fgets(STDIN));
// TODO: Criar uma instância de Config
// TODO: Definir a primeira configuração com o valor fornecido
// TODO: Imprimir se a primeira configuração existe ("exists" ou "missing")
// TODO: Imprimir o valor da primeira configuração
// TODO: Imprimir a contagem atual de configurações
// TODO: Usar unset() para remover a primeira configuração
// TODO: Imprimir se a primeira configuração existe agora ("exists" ou "missing")
// TODO: Imprimir o valor da segunda configuração (que nunca foi definida)
?>Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave $thisMétodosPropriedadesConstrutor (__construct)Destrutor (__destruct)Recapitulação - Calculadora Simples4Herança
Herança BásicaA Palavra-chave parent::Sobrescrita de MétodoA Palavra-chave finalClasses AbstratasRecapitulação - Hierarquia de Funcionários7Encapsulamento
Público, Protegido, PrivadoModificadores de Acesso em DetalhesGetters e SettersOcultação de InformaçãoPromoção de Construtor (8.0)Recapitulação - Sistema de Registro de Alunos10Conceitos Avançados de POO
Composição vs HerançaInjeção de DependênciaClasses AnônimasEnums (PHP 8.1)Fibers (PHP 8.1)Mergulho Profundo em Clonagem de ObjetosGeradores e Iteradores13Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Repository2Namespaces e Autoloading
Introdução a NamespacesA Palavra-chave usePadrão de Autoloading PSR-4Autoloader do ComposerRecapitulação - Projeto Organizado5Interfaces e Contratos
Introdução a InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesInterface vs Classe AbstrataType Hinting com InterfacesRecapitulação - Calculadora de Formas8Métodos Mágicos
Introdução aos Métodos Mágicos__toString e __debugInfo__get, __set, __isset, __unset__call e __callStatic__clone e Clonagem de Objetos__serialize e __unserializeRecapitulação - Coleção Personalizada11Sistema de Tipos e Tratamento de Erros
Declarações de TiposTipos AnuláveisTipos de União e InterseçãoClasses de ExceçãoHierarquia de Exceções PersonalizadasTry, Catch, FinallyRecapitulação - Validador de Formulário14Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e Usuário3Propriedades de Classe
Propriedades de Instância vs EstáticasConstantes em ClassesMétodos e Propriedades EstáticosPropriedades Privadas e ProtegidasPropriedades Readonly (PHP 8.1)Recapitulação - Gerenciador de Conta Bancária6Polimorfismo
Sobrescrita de Métodos RevisitadaPolimorfismo via InterfacesType Hinting e Union TypesLate Static BindingRecapitulação - Processador de Pagamentos9Traits
Introdução a TraitsUsando Múltiplos TraitsResolução de Conflitos de TraitsMétodos Abstratos em TraitsTraits vs Herança12Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy