hosmelq / laravel-model-preferences
A Laravel package for managing model preferences with type-safe caching.
Requires
- php: ^8.2
- illuminate/contracts: ^11.0 || ^12.0
- illuminate/database: ^11.0 || ^12.0
- illuminate/support: ^11.0 || ^12.0
- spatie/laravel-package-tools: ^1.92
- thecodingmachine/safe: ^3.3
Requires (Dev)
- ergebnis/composer-normalize: ^2.47
- larastan/larastan: ^3.6
- laravel/pint: ^1.24
- orchestra/testbench: ^9.0 || ^10.0
- pestphp/pest: ^3.8
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- rector/rector: ^2.1
- rector/type-perfect: ^2.1
- shipmonk/composer-dependency-analyser: ^1.8
- spaze/phpstan-disallowed-calls: ^4.6
- thecodingmachine/phpstan-safe-rule: ^1.4
- ticketswap/phpstan-error-formatter: ^1.1
- tomasvotruba/type-coverage: ^2.0
This package is auto-updated.
Last update: 2025-07-21 22:41:17 UTC
README
A Laravel package for managing model preferences with validation.
Features
- Model preferences - Any Eloquent model can have preferences.
- Validation support - Define Laravel validation rules for preference values.
- Default values - Set fallback values for undefined preferences.
- Batch operations - Set or delete multiple preferences at once.
Requirements
- PHP 8.2+
- Laravel 11.0+
Installation
composer require hosmelq/laravel-model-preferences
Configuration
The service provider will be automatically registered. You can use the install command for quick setup:
php artisan model-preferences:install
This command will publish the migrations, config file, and ask to run migrations automatically.
Alternatively, you can publish and run manually:
php artisan vendor:publish --tag="model-preferences-migrations"
php artisan migrate
Optionally, publish the config file:
php artisan vendor:publish --tag="model-preferences-config"
Basic Usage
Implement the interface and add the trait to any Eloquent model:
<?php use HosmelQ\ModelPreferences\Contracts\HasPreferences; use HosmelQ\ModelPreferences\Models\Concerns\InteractsWithPreferences; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements HasPreferences { use InteractsWithPreferences; public function preferenceDefaults(): array { return [ 'notifications' => true, 'theme' => 'light', 'timezone' => 'UTC', ]; } }
Set and get preferences:
$user = User::find(1); // Set a preference $user->setPreference('theme', 'system'); // Get a preference $theme = $user->preference('theme'); // 'system' // Get with custom fallback $timezone = $user->preference('timezone', 'UTC');
Usage
Setting Up Models
Implement the HasPreferences
interface, use the InteractsWithPreferences
trait, and optionally define default preferences and validation rules:
<?php use HosmelQ\ModelPreferences\Contracts\HasPreferences; use HosmelQ\ModelPreferences\Models\Concerns\InteractsWithPreferences; use Illuminate\Database\Eloquent\Model; class Team extends Model implements HasPreferences { use InteractsWithPreferences; public function preferenceDefaults(): array { return [ 'allow_invites' => false, 'max_members' => 10, 'visibility' => 'private', ]; } }
Setting Preferences
Set individual preferences:
$team = Team::find(1); $team->setPreference('max_members', 50); $team->setPreference('visibility', 'public');
Set multiple preferences at once:
$team->setPreferences([ 'allow_invites' => true, 'max_members' => 100, 'visibility' => 'public', ]);
Getting Preferences
Get individual preferences:
$notifications = $user->preference('notifications'); // Returns stored value or default $theme = $user->preference('theme', 'system'); // Custom fallback
Default Value Priority:
- Stored preference value
- Value from
preferenceDefaults()
method (if reference exists) - Method parameter default (only used if reference not in
preferenceDefaults()
)
Note that $user->preference('timezone', 'UTC')
will return the value from preferenceDefaults()['timezone']
if defined, ignoring the UTC
parameter.
Get all preferences merged with defaults:
$preferences = $user->getAllPreferences();
Check if a preference exists:
if ($user->hasPreference('notifications')) { }
Deleting Preferences
Delete individual preferences:
$user->deletePreference('notifications');
Delete multiple preferences:
$user->deletePreferences(['notifications', 'theme', 'timezone']);
Eager Loading Preferences
Eager load preferences into the model's relationship cache to avoid N+1 database queries. When you call preference()
later, Laravel can optimize these calls using the cached relationship data instead of hitting the database each time:
// Load specific preferences $user->loadPreferences(['theme', 'notifications']); // Load all preferences $user->loadPreferences(); // Now accessing these preferences won't trigger additional queries $theme = $user->preference('theme'); $notifications = $user->preference('notifications');
Validation
The package uses Laravel's validation system to validate preference values. Validation occurs automatically when calling setPreference()
or setPreferences()
using the rules defined in your preferenceRules()
method.
When validation fails, a PreferenceValidationException
is thrown, which has an errors()
method to access validation messages.
Define Laravel validation rules for preferences:
<?php use HosmelQ\ModelPreferences\Contracts\HasPreferences; use HosmelQ\ModelPreferences\Models\Concerns\InteractsWithPreferences; use Illuminate\Database\Eloquent\Model; use Illuminate\Validation\Rule; class User extends Model implements HasPreferences { use InteractsWithPreferences; public function preferenceRules(): array { return [ 'notifications' => ['boolean'], 'theme' => ['required', Rule::in(['dark', 'light', 'system'])], 'timezone' => ['string', 'timezone'], ]; } }
Handle validation errors when setting preferences:
<?php use HosmelQ\ModelPreferences\Exceptions\PreferenceValidationException; try { $user->setPreference('theme', 'invalid-theme'); } catch (PreferenceValidationException $e) { $errors = $e->errors(); }
Testing
composer test
Changelog
See CHANGELOG.md for a list of changes.
Credits
License
The MIT License (MIT). Please see License File for more information.