Pular para o conteúdo principal

← Primeiros passos · Voltar ao README · Carregamento antecipado →

Trabalhando com configurações

O mesmo serviço gerencia valores padrão e valores dos modelos. O ponto de entrada determina qual escopo é lido ou alterado:

Ponto de entradaEscopo
(new User)->defaultSettings()Valores padrão compartilhados pelos modelos User persistidos
$user->settings()Configurações efetivas de um usuário persistido

Valores padrão compartilhados​

Os valores padrão são aplicados a todos os modelos persistidos com a mesma classe morph do Eloquent:

$defaults = (new User)->defaultSettings();

$defaults->set('timezone', 'UTC');
$defaults->set('notifications', ['email' => true]);

Leia ou remova valores padrão usando o mesmo serviço:

$timezone = $defaults->get('timezone');
$all = $defaults->all();

$defaults->forget('timezone');

Os valores padrão são independentes para cada classe de modelo.

Sobrescritas por modelo​

set() cria uma configuração ou substitui o valor existente:

$user->settings()->set('timezone', 'Europe/Paris');
$user->settings()->set('timezone', 'America/Toronto');

Somente a configuração desse modelo é alterada. Os demais modelos continuam usando sua própria sobrescrita ou o valor padrão compartilhado.

get(), has() e all() resolvem os valores com a mesma precedência:

$timezone = $user->settings()->get('timezone');
$hasTimezone = $user->settings()->has('timezone');
$settings = $user->settings()->all();

all() retorna uma Illuminate\Support\Collection indexada pelas chaves das configurações.

get() aceita somente a chave. Ele retorna primeiro a sobrescrita do modelo, depois o valor padrão persistente da classe e, por fim, null. Ele não aceita um valor alternativo fornecido pelo chamador. has() distingue uma chave ausente de um JSON null armazenado:

if ($user->settings()->has('timezone')) {
$timezone = $user->settings()->get('timezone');
}

Por exemplo, uma sobrescrita substitui somente o valor padrão correspondente:

(new User)->defaultSettings()->set('timezone', 'UTC');
(new User)->defaultSettings()->set('locale', 'en');

$user->settings()->set('timezone', 'Europe/Paris');

assert($user->settings()->all()->sortKeys()->all() === [
'locale' => 'en',
'timezone' => 'Europe/Paris',
]);

Remover um valor​

Remover uma sobrescrita do modelo volta a expor o valor padrão:

(new User)->defaultSettings()->set('timezone', 'UTC');

$user->settings()->set('timezone', 'Europe/Paris');
$user->settings()->forget('timezone');

assert($user->settings()->get('timezone') === 'UTC');

Para remover o próprio valor padrão, chame forget() por meio de defaultSettings():

(new User)->defaultSettings()->forget('timezone');

Chamar forget() para uma chave inexistente não tem efeito.

Alterações em lote​

Use setMany() e forgetMany() quando um escopo precisar de várias alterações:

$user->settings()->setMany([
'timezone' => 'Europe/Paris',
'locale' => 'fr',
]);

$user->settings()->forgetMany(['timezone', 'locale']);

Os dois métodos aceitam qualquer iterable. setMany() normaliza cada chave antes da escrita. Quando várias chaves de entrada são normalizadas para a mesma chave armazenada, o último valor vence. Todos os valores são armazenados; somente forget() e forgetMany() removem linhas.

Um lote não vazio de setMany() usa um único upsert nativo dentro de uma transação. forgetMany() remove todas as chaves informadas com uma consulta. A quantidade de consultas é limitada pelo tipo de operação, não pelo número de chaves.

Use purge() para remover todo o escopo atual:

$user->settings()->purge();

Em settings(), purge() remove somente as sobrescritas desse proprietário e volta a expor os valores padrão persistentes. Em defaultSettings(), remove os padrões dessa classe sem excluir as sobrescritas dos modelos. Os três métodos em lote retornam void.

Valores JSON​

set() e setMany() armazenam valores JSON exatos:

ValorResultado
nullArmazenado
'' ou string contendo apenas espaçosArmazenado
[]Armazenado
0Armazenado
falseArmazenado
'0'Armazenado

Um null armazenado é considerado um valor existente. has($key) retorna true, enquanto get($key) retorna null. Uma sobrescrita de modelo com null também oculta um valor padrão preenchido da classe até que a sobrescrita seja removida com forget().

Chaves de configuração​

As chaves podem ser strings, inteiros ou enums PHP que implementem UnitEnum:

enum SettingKey: string
{
case Timezone = 'timezone';
}

$user->settings()->set(SettingKey::Timezone, 'Europe/Paris');

$timezone = $user->settings()->get(SettingKey::Timezone);

O Laravel armazena um backed enum pelo seu valor subjacente e um pure unit enum pelo nome do case. Use a mesma chave ou case ao ler, substituir ou remover uma configuração.

Chaves vazias ou contendo apenas espaços lançam DragonCode\LaravelModelSettings\Exceptions\InvalidSettingKey. A validação ocorre depois da normalização de inteiros e enums para a string armazenada. A exceção nunca inclui a chave rejeitada nem o payload da configuração.

Pontos são caracteres literais. A chave mail.from.address é uma única chave opaca e nunca representa um caminho aninhado:

$user->settings()->set('mail.from.address', '[email protected]');

$address = $user->settings()->get('mail.from.address');

Identificadores de modelo​

Chaves primárias inteiras, string, UUID e ULID são compatíveis.

Alterações nas configurações de um modelo exigem um proprietário persistido com uma chave diferente de null. Para um modelo não persistido, get() retorna null, has() retorna false e all() retorna uma coleção vazia sem consultar as sobrescritas do modelo. Seus métodos set(), setMany(), forget(), forgetMany() e purge() lançam InvalidSettingsOwnerException antes de uma consulta ao armazenamento ou do consumo do iterable.

Modelos persistidos com identificador inteiro 0 ou string '0' aceitam as mesmas leituras e alterações que qualquer outro proprietário persistido. O discriminador de escopo separa suas sobrescritas dos padrões da classe, mesmo que as duas linhas mantenham item_id = '0'. Outras chaves string, incluindo '00', continuam válidas.

As configurações são armazenadas usando a classe morph atual do modelo. Adicionar ou alterar um alias do morph map depois que as configurações forem gravadas exige a atualização dos valores item_type existentes.

Veja também​