Settings System
Quick Start
use App\Enumerations\SettingType;
// Create a settings record (globally, for the system agency)
Setting::create([
'agency_id' => Agency::SystemAgencyId,
'type' => SettingType::XeroIntegration,
'data' => ['key' => encrypt('value')],
]);
// Read with fallback chain (agency → global)
$setting = Setting::forAgency($agencyId, SettingType::XeroIntegration);
$data = $setting?->data;
Model
App\Models\Setting extends TenantModel. Key details:
datacolumn is JSON, cast toarrayon read$guarded = []— all fields mass-assignableTenantModelauto-populatesagency_idon create viaAgencyScopingtrait (can override by explicitly setting it)
Fallback Chain Resolution
Settings resolve in priority order, returning the first match:
- Agency-specific (
agency_id= current agency) - Global default (
agency_id=Agency::SystemAgencyId, which is 1)
Use Setting::forAgency($agencyId, $type) for this. To query a specific level directly, use scopeOfType() and/or scopeForAgency().
Composite Unique Constraint
The migration enforces unique(agency_id, type) — one record per setting type per agency. Use updateOrCreate() for upsert scenarios:
Setting::updateOrCreate(
['agency_id' => $agencyId, 'type' => SettingType::XeroIntegration],
['data' => $payload],
);
Data Payload & Encryption
- Only secrets (
access_token,refresh_token, API keys) are encrypted via Laravel'sencrypt()/decrypt() - Non-sensitive fields (
expires_at,connected_at, tenant IDs) are plaintext - The
dataJSON column stores everything together
Adding a New Setting Type
- Add case to
App\Enumerations\SettingType - Create/update a settings record via the model — no schema changes needed
Creating Global vs Agency-Specific Records
When creating via Setting::create(), the AgencyScoping trait auto-sets agency_id to the current tenant. To create a global record (agency 1), explicitly set the agency_id:
Setting::create([
'agency_id' => Agency::SystemAgencyId, // must be explicit
'type' => SettingType::XeroIntegration,
'data' => [...],
]);
See Also
docs/WIP/Mike/settings-system.md— detailed human-readable documentationapp/Models/Setting.php— model with scopes and helpersapp/Enumerations/SettingType.php— enum of available setting typesdatabase/migrations/2026_05_15_000000_create_settings_table.php— table schema