Install the package:
composer require arturdoruch/list-bundle
Register the bundle in config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 3).
Basic Controller Integration:
Create a controller action with a GET route returning an ItemList object:
use ArturDoruch\ListBundle\ItemList;
use ArturDoruch\ListBundle\Paginator;
use ArturDoruch\ListBundle\Request\QueryParameterBag;
public function list(Request $request)
{
$parameterBag = new QueryParameterBag($request);
$items = $this->fetchItems(); // Your data source (array, QueryBuilder, etc.)
$pagination = Paginator::paginate($items, $parameterBag->getPage(), $parameterBag->getLimit(10));
return [
'itemList' => new ItemList($pagination)
];
}
Template Rendering: Use Twig functions to render the list:
{{ arturdoruch_list_items_and_pagination(itemList.pagination) }}
ArturDoruch\ListBundle\Form\FilterType or use FilterType directly in the controller:
$form = $this->createForm(BookFilterType::class, null, ['method' => 'GET', 'csrf_protection' => false]);
$form->handleRequest($request);
$criteria = $form->isSubmitted() && $form->isValid() ? $form->getData() : [];
$items = $repository->findBy($criteria);
QueryParameterBag to extract sort parameters from the request:
$sort = $parameterBag->getSort(); // Returns ["field" => "order"]
$items = $repository->findBy([], $sort);
$sortChoices = new SortChoiceCollection();
$sortChoices
->add('Name (A-Z)', 'name', 'asc')
->add('Name (Z-A)', 'name', 'desc');
return new ItemList($pagination, $form, $sortChoices);
$pagination = Paginator::paginate($items, $page, $limit);
$pagination->setItemLimits([10, 25, 50]); // Custom limits
config/packages/arturdoruch_list.yaml:
arturdoruch_list:
pagination:
item_limits: [10, 25, 50]
{% extends app.request.xmlHttpRequest ? '@App/ajax_list.html.twig' : '@App/base.html.twig' %}
Only render the list block for AJAX:
{% block list %}
{{ arturdoruch_list_items_and_pagination(itemList.pagination) }}
{% endblock %}
ArturDoruch\ListBundle\Paginator\PaginatorInterface:
class CustomPaginator implements PaginatorInterface {
public function paginate($items, $page, $limit) { ... }
}
Register in config/packages/arturdoruch_list.yaml:
arturdoruch_list:
paginators:
custom: App\Paginator\CustomPaginator
CSRF Protection:
Filter forms must have csrf_protection: false to work with query parameters.
$form = $this->createForm(BookFilterType::class, null, ['csrf_protection' => false]);
Form Name Matters:
The filter form’s name (e.g., filter) determines the query parameter prefix for filtering.
Use createNamed() to customize:
$form = $this->createForm(BookFilterType::class, null, ['name' => 'custom_filter']);
Sorting Conflicts:
If sorting fails, ensure your QueryBuilder supports dynamic ordering:
$qb->orderBy($sort['field'], $sort['order']);
Pagination Edge Cases:
count === 0 in templates to avoid rendering empty tables.QueryParameterBag throws exceptions for invalid values. Validate or catch:
try {
$page = $parameterBag->getPage();
} catch (\InvalidArgumentException $e) {
$page = 1;
}
Inspect Request Parameters:
Dump QueryParameterBag to verify sorting/filtering:
dump($parameterBag->getSort()); // ["field" => "order"]
dump($parameterBag->getFilter()); // Filter criteria
Twig Debugging:
Use {{ dump(itemList) }} to inspect the ItemList object structure.
JavaScript Integration:
For @arturdoruch/list, ensure the JS bundle is properly linked and configured to match the PHP bundle’s settings.
Eager-Loading:
Use QueryBuilder with join() and addSelect() to avoid N+1 queries:
$qb->join('b.category', 'c')->addSelect('c');
Limit Query Complexity:
Avoid overly complex WHERE clauses in filters. Use indexed fields where possible.
Caching:
Cache ItemList objects if data changes infrequently:
$cacheKey = md5(serialize($criteria));
$itemList = $cache->get($cacheKey, function() use ($criteria) {
return new ItemList($pagination);
});
Custom Twig Functions: Override or extend Twig functions in your bundle’s compiler pass:
// src/Twig/ArturDoruchListExtension.php
class ArturDoruchListExtension extends \Twig_Extension {
public function getFunctions() {
return [
new \Twig_SimpleFunction('custom_list_function', [$this, 'renderCustomList']),
];
}
}
Event Listeners:
Hook into the bundle’s lifecycle (e.g., modify ItemList before rendering):
// config/services.yaml
services:
App\EventListener\ListListener:
tags:
- { name: kernel.event_listener, event: arturdoruch.list.pre_render, method: onPreRender }
Configuration Overrides:
Use environment-specific configs (e.g., config/packages/dev/arturdoruch_list.yaml) to tweak behavior per environment.
How can I help you explore Laravel packages today?