tito10047 / persistent-state-bundle
Easily manage persistent checkbox selections and key-value settings in Symfony applications.
Installs: 13
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/tito10047/persistent-state-bundle
Requires
- php: >=8.1
- symfony/framework-bundle: ^6.4|^7.4|^8.0
- symfony/property-access: ^6.4|^7.4|^8.0
Requires (Dev)
- dama/doctrine-test-bundle: ^8.4
- pagerfanta/pagerfanta: ^3.6
- phpunit/phpunit: ^10.5
- symfony/asset-mapper: ^6.4|^7.4|^8.0
- symfony/dotenv: ^6.4|^7.4|^8.0
- symfony/http-client: ^6.4|^7.4|^8.0
- symfony/maker-bundle: ^1.39
- symfony/orm-pack: ^2.5
- symfony/phpunit-bridge: ^6.4|^7.4|^8.0
- symfony/profiler-pack: ^1.0
- symfony/runtime: ^6.4|^7.4|^8.0
- symfony/serializer-pack: ^1.3
- symfony/stimulus-bundle: ^2.31
- symfony/translation: ^6.4|^7.4|^8.0
- symfony/twig-bundle: ^6.4|^7.4|^8.0
- symfony/uid: ^6.4|^7.4|^8.0
- symfony/yaml: ^6.4|^7.4|^8.0
- zenstruck/foundry: 2.6
README
Persistent State Bundle
This bundle provides a unified and robust solution for managing persistent user interface state in Symfony applications. It covers two key areas: Selections for efficient handling of bulk operations (e.g., "Select All" across pagination) and Preferences for storing key-value settings. With a flexible architecture based on context resolvers (e.g., binding to a user or company) and support for various storage backends (Session, Redis, Doctrine), it allows you to elegantly solve UI state persistence without cluttering your controllers with boilerplate code.
services: app.users_resolver: class: Tito10047\PersistentStateBundle\Resolver\ObjectContextResolver arguments: $targetClass: App\Entity\User $identifierMethod: 'getName' app.companies_resolver: class: Tito10047\PersistentStateBundle\Resolver\ObjectContextResolver arguments: $targetClass: App\Entity\Company app.storage.doctrine: class: Tito10047\PersistentStateBundle\Storage\DoctrinePreferenceStorage arguments: - '@doctrine.orm.entity_manager' - Tito10047\PersistentStateBundle\Tests\App\AssetMapper\Src\Entity\UserPreference persistent: preference: managers: default: storage: '@persistent.preference.storage.session' my_pref_manager: storage: '@app.storage.doctrine' selection: managers: default: storage: 'persistent.selection.storage.session' simple: storage: 'persistent.selection.storage.doctrine'
namespace ; use \Symfony\Component\DependencyInjection\Attribute\Autowire; use \App\Entity\User; use \App\Entity\Company; use \App\Entity\Product; class Foo{ public function __construct( private readonly PreconfiguredPreferenceInterface $sessionPrefManager #[Autowire('persistent.preference.my_pref_manager')] private readonly PreconfiguredPreferenceInterface $doctrinePrefManager, private readonly PreconfiguredSelectionInterface $sessionPrefManager, #[Autowire('persistent.selection.my_sel_manager')] private readonly PreconfiguredSelectionInterface $doctrinePrefManager, private readonly EntityManagerInterface $em ) {} public function bar(User $user, Company $company, Product $product){ $userPref = $this->sessionPrefManager->getPreference($user); $companyPref = $this->doctrinePrefManager->getPreference($company); $cartSelection = $this->sessionPrefManager->getSelection($user,"cart"); $companySelection = $this->doctrinePrefManager->getSelection($company, "products"); $cartSelection->select($product, [ 'quantity' => $request->get('qty', 1), 'added_at' => new \DateTime() ]); $companySelection->select($product); $userPref->set('foo', 'bar'); $userPref->set('baz', [1,2,3]); $companyPref->set('foo2', 'bar'); $companyPref->set('baz2', [1,2,3]); $em->flush(); $foo = $userPref->get('foo'); $baz = $userPref->get('baz'); $foo2 = $companyPref->get('foo2'); $baz2 = $companyPref->get('baz2'); $selectedItems = $cartSelection->getSelectedObjects(); $selectedProducts = $companySelection->getSelectedObjects(); $cart->destroy(); } }
<div> User Foo: {{ preference(user, 'foo') }}<br> Company pref: {{ company|pref('foo2') }} </div>
Console command: debug:preference
Inspect stored preferences for a specific context directly from CLI.
Usage:
php bin/console debug:preference "user_15" --manager=my_pref_manager
Output example:
Context: user_15
Storage: doctrine
+-------+-------+
| Key | Value |
+-------+-------+
| theme | dark |
| limit | 50 |
+-------+-------+
Notes:
- The
contextargument accepts either a pre-resolved key likeuser_15or any object supported by your configured context resolvers. - The
--manageroption selects which preference manager to use. It maps to the service idpersistent.manager.{name}and defaults todefaultwhen omitted. - The Storage line reflects the underlying storage:
session,doctrine, or the short class name for custom storages. - Non-scalar values are JSON-encoded for readability;
nulland booleans are rendered asnull,true/false.
