Installation
Add the bundle to your composer.json:
composer require akeneo/storage-utils-bundle
Enable it in config/bundles.php:
return [
// ...
Akeneo\StorageUtilsBundle\AkeneoStorageUtilsBundle::class => ['all' => true],
];
First Use Case: Querying with Criteria
The bundle provides a Criteria class for building complex queries across Doctrine ORM/DBAL/MongoDB.
Example:
use Akeneo\Tool\Component\StorageUtils\Query\Criteria;
$criteria = new Criteria();
$criteria->addFilter(Criteria::FILTER_EQUAL, 'field_name', 'value');
$criteria->addSort('field_name', Criteria::SORT_ASC);
Where to Look First
Akeneo\Tool\Component\StorageUtils\Query\Criteria and Akeneo\Tool\Component\StorageUtils\Repository\RepositoryInterface.Akeneo\Tool\Component\StorageUtils\Doctrine\Query\QueryBuilderFactory.Akeneo\Tool\Component\StorageUtils\MongoDB\Query\QueryBuilderFactory.Use the RepositoryInterface to standardize repository operations across ORM/DBAL/MongoDB:
use Akeneo\Tool\Component\StorageUtils\Repository\RepositoryInterface;
$repository = $this->get('akeneo_storage_utils.repository.product');
$results = $repository->findBy($criteria);
Build reusable criteria for filtering, sorting, and pagination:
$criteria = new Criteria();
$criteria
->addFilter(Criteria::FILTER_EQUAL, 'status', 'enabled')
->addSort('created_at', Criteria::SORT_DESC)
->setLimit(10)
->setOffset(0);
Generate query builders dynamically for different storage backends:
use Akeneo\Tool\Component\StorageUtils\Doctrine\Query\QueryBuilderFactory;
$qbFactory = $this->get(QueryBuilderFactory::class);
$qb = $qbFactory->create($entityManager, $entityClass, $criteria);
Extend functionality via Symfony events (e.g., akeneo_storage_utils.query_builder.create):
# config/services.yaml
services:
App\EventSubscriber\CustomQuerySubscriber:
tags:
- { name: kernel.event_subscriber }
For MongoDB, leverage the MongoDBQueryBuilderFactory:
use Akeneo\Tool\Component\StorageUtils\MongoDB\Query\MongoDBQueryBuilderFactory;
$mongoQbFactory = $this->get(MongoDBQueryBuilderFactory::class);
$query = $mongoQbFactory->create($dm, $documentClass, $criteria);
Criteria to DQL under the hood. Complex joins may require manual DQL adjustments.@Document and @Field annotations for proper mapping.Criteria with MongoDB’s native aggregation framework.LIMIT/OFFSET with complex joins).config/packages/akeneo_storage_utils.yaml:
akeneo_storage_utils:
query_builder:
default_limit: 50
Criteria Translation Limits
Criteria filters/sorts translate perfectly to MongoDB or raw SQL. Test edge cases (e.g., nested filters, custom functions).MongoDB vs. ORM Differences
Criteria implementation may behave differently (e.g., $lookup vs. joins).MongoDBQueryBuilderFactory directly for MongoDB-specific optimizations.Performance with Large Datasets
Criteria with deep nesting or unbounded sorts. Use setLimit() and setOffset() for pagination.Event Subscriber Conflicts
akeneo_storage_utils.query_builder.create may override each other.priority: 10) to control execution order.Doctrine Event Listeners
stopPropagation() in event subscribers.Query Logging Enable Doctrine/MongoDB query logging to inspect generated queries:
# config/packages/dev/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
Criteria Validation
Use Criteria::validate() to check for unsupported operations before execution:
if (!$criteria->validate()) {
throw new \RuntimeException('Invalid criteria for this storage backend.');
}
MongoDB Debugging
For MongoDB, enable debug mode in the MongoDBQueryBuilderFactory:
$query = $mongoQbFactory->create($dm, $documentClass, $criteria, true); // Debug mode
Custom Criteria Filters
Extend Criteria by implementing Akeneo\Tool\Component\StorageUtils\Query\Filter\FilterInterface:
class CustomFilter implements FilterInterface {
public function apply(QueryBuilder $qb, $field, $value) {
// Custom logic
}
}
Register it in services:
services:
App\Query\CustomFilter:
tags:
- { name: akeneo_storage_utils.criteria.filter, alias: 'custom' }
Query Builder Decorators
Decorate the default QueryBuilderFactory to add pre/post-processing:
use Akeneo\Tool\Component\StorageUtils\Doctrine\Query\QueryBuilderFactoryInterface;
class CustomQueryBuilderFactory implements QueryBuilderFactoryInterface {
private $decorated;
public function __construct(QueryBuilderFactoryInterface $decorated) {
$this->decorated = $decorated;
}
public function create(EntityManagerInterface $em, string $entityClass, Criteria $criteria) {
$qb = $this->decorated->create($em, $entityClass, $criteria);
// Add custom logic (e.g., global filters)
return $qb;
}
}
Repository Decorators
Decorate RepositoryInterface to add cross-cutting concerns (e.g., logging, caching):
use Akeneo\Tool\Component\StorageUtils\Repository\RepositoryInterface;
class CachedRepository implements RepositoryInterface {
private $decorated;
public function __construct(RepositoryInterface $decorated) {
$this->decorated = $decorated;
}
public function findBy(Criteria $criteria) {
$cacheKey = md5($criteria->serialize());
if ($cached = $this->cache->get($cacheKey)) {
return $cached;
}
$result = $this->decorated->findBy($criteria);
$this->cache->set($cacheKey, $result, 3600);
return $result;
}
}
Default Limit
The bundle sets a default limit (e.g., 50). Override it globally:
akeneo_storage_utils:
query_builder:
default_limit: 100
MongoDB Document Classes
Ensure your MongoDB documents are properly mapped with @Document and @Field annotations. The bundle uses these for query generation.
Doctrine Event Dispatcher The bundle dispatches events for query building. Disable if conflicts arise:
akeneo_storage_utils:
query_builder:
dispatch_events: false
How can I help you explore Laravel packages today?