Filter And Scoped Data
This is one of the most practical parts of account-bundle: turning the current account route context into automatic read and write scoping for account-owned entities.
The Usual Account-Scoped Pattern
The normal flow is:
- the route contains
/{_account} - the bundle resolves that value to the current account
- Doctrine enables the
accountfilter for the request - entities implementing
AccountFilterInterfaceare limited to the current account automatically
That means your controllers can often load data normally and still remain scoped to the current account.
Requirements For Automatic Filtering
For automatic filtering to work:
- the route must carry the current account, usually as
/{_account} - the entity must implement
AccountFilterInterface - the entity must expose an account relation compatible with the bundled filter
sfs_account.filter.enabledmust be true
SQL Filter Assumption
The bundled SQL filter adds a condition like:
<table_alias>.account_id = :_account
So the default implementation assumes:
- the entity has an
account_idcolumn - the current account should be matched against that column
If your mapping uses another column name or another ownership strategy, treat the bundled filter as a starting point and replace it.
Automatic Account On PrePersist
AccountFilteredEventListener also helps on writes.
When an entity:
- implements
AccountFilterInterface - does not already have an account
- also implements
SingleAccountedInterfaceorAccountRelatedInterface
the listener copies the current request account into the entity during Doctrine prePersist.
This is useful for account-aware create flows:
$project = new Project();
$project->setName('Intranet redesign');
$entityManager->persist($project);
$entityManager->flush();
If the request already resolved /_account, the entity can receive that account automatically.
Good Use Cases
This pattern works especially well for:
- projects
- invoices
- subscriptions
- customer records
- provider resources
- account-specific settings
These are entities that belong clearly to one account and should never leak across account contexts.
Limitations To Keep In Mind
- the bundled filter expects
account_id - some runtime helpers still read
_accountdirectly - complex ownership models may need a custom filter or custom persistence logic
The bundle removes a lot of repeated andWhere('entity.account = :account'), but it is still a base implementation, not a universal multitenancy engine.