anomaly/settings-module
Anomaly Settings Module provides a Laravel-based settings management interface for Anomaly CMS, letting administrators define, organize, and edit configurable settings through Streams fields and a simple control panel.
The settings module ships as part of the Streams Platform ecosystem (and PyroCMS), so in most projects it is already present transitively — confirm with composer show anomaly/settings-module before adding it explicitly. If you do need it, composer require anomaly/settings-module inside a Streams-enabled Laravel app is the only install step; Streams auto-discovers modules in vendor/ and addons/, so no manual service-provider wiring is required.
The first place to look is the repository contract, not the Eloquent model:
Anomaly\SettingsModule\Setting\Contract\SettingRepositoryInterfaceAnomaly\SettingsModule\Setting\SettingRepositorysetting() helper (defined by the module) for the 90% caseYour first real use case is almost always "read a stored setting with a sane fallback," e.g. in a view composer or controller:
$value = setting('anomaly.module.settings::example', 'default');
If you plan to expose settings in the control panel, the next stop is a module's resources/config/settings.php, which the settings module renders into an admin form automatically. Treat that config file as the source of truth for the setting key, field type, and default.
Repository over helper for anything non-trivial. Resolve the repository via the container rather than importing the model:
use Anomaly\SettingsModule\Setting\Contract\SettingRepositoryInterface;
public function __construct(SettingRepositoryInterface $settings)
{
$this->settings = $settings;
}
get() returns a setting entry object, not a raw scalar. Access the value through the entry ($entry->value or the entry's presenter/value accessor), or use the setting() helper when you genuinely want the processed scalar. Don't assume $settings->get('foo') is a string.
Namespace aggressively. Settings are scoped by namespace. The default namespace is the settings module itself; for addons use the vendor.module pattern:
$this->settings->namespace('acme.module.blog')->get('per_page', 10);
Set the namespace once in a service provider or a base class so every call in a package is scoped consistently.
Define settings declaratively. In resources/config/settings.php:
return [
'per_page' => [
'type' => 'anomaly.field_type.integer',
'default' => 15,
],
'enabled' => [
'type' => 'anomaly.field_type.boolean',
'default' => true,
],
];
The module uses the field type to render the CP form and to translate the stored value back into a typed value. This is the idiomatic integration point — resist the urge to build a bespoke settings page.
Reads in hot paths. Settings are DB-backed; if you read the same key on every request (e.g. in a middleware or a Blade component rendered many times), wrap the lookup or cache the result per-request. The repository does not guarantee per-request memoization across namespaces.
Writes and reset. For programmatic writes, use set()/forget() on the repository, and prefer doing so in migrations, seeders, or installers so the settings table is populated consistently. Direct SettingModel access bypasses field-type casting and will produce values that don't round-trip through the CP form.
Testing. Because everything resolves through SettingRepositoryInterface, bind a fake or in-memory implementation in tests instead of touching the database; that keeps tests fast and decoupled from the module's migrations.
$settings->get('key') yields an entry object. The most common bug is treating it as a string. Use ->value (or the helper) deliberately and be explicit about which you want.namespace(...) before get()/set(), otherwise a different service provider's default can silently win.settings table will mislead you during debugging; always read through the repository so the field type casts the value.has() is your friend when you need to distinguish "unset" from "set to null/default." Don't rely on get() alone to tell the difference.settings table by hand skips validation and casting. If you must, re-save through the CP or a seeder afterward so the field type re-casts the value.anomaly/field_type-* packages, not from the settings module itself. If you need a new control, add a field type rather than forking settings. Custom settings sections are registered from a module's service provider; keep them in the module that owns the settings, not in a central place.$settings->namespace(...)->get('key') including the entry, (2) verify the key exists in resources/config/settings.php and the field type is installed, (3) check the settings table row's namespace column matches what your code expects, (4) clear any settings/cache layer.How can I help you explore Laravel packages today?