codeclipse/sortable-behavior-bundle
Installation
composer require codeclipse/sortable-behavior-bundle
Enable the bundle in config/bundles.php:
return [
// ...
Codeclipse\SortableBehaviorBundle\CodeclipseSortableBehaviorBundle::class => ['all' => true],
];
Configure for Doctrine ORM
Update config/packages/codeclipse_sortable_behavior.yaml:
codeclipse_sortable_behavior:
db_driver: orm # default, no need to specify
position_field:
entities:
App\Entity\YourEntity: position
Extend Your Admin Class
Add SortableInterface to your entity and implement getSortableGroups():
use Codeclipse\SortableBehaviorBundle\Model\SortableInterface;
class YourEntity implements SortableInterface
{
// ...
public function getSortableGroups()
{
return ['group1', 'group2'];
}
}
Enable Sorting in Admin
Override configureListFields in your Admin class:
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('_sortable', 'sortable', [
'sortable_group' => 'group1',
]);
}
Clear Cache
php bin/console cache:clear
Add sortable functionality to a SonataAdmin listing for a Product entity:
position_field for App\Entity\Product (e.g., sort_order)._sortable field to the list with a group (e.g., category).Basic Sorting
_sortable field in configureListFields with a predefined group.$listMapper->add('_sortable', 'sortable', [
'sortable_group' => 'default_group',
]);
Dynamic Groups
getSortableGroups() in your entity to return dynamic groups based on logic (e.g., user roles).public function getSortableGroups()
{
return $this->isPremium() ? ['premium'] : ['standard'];
}
Custom Templates
# config/packages/codeclipse_sortable_behavior.yaml
codeclipse_sortable_behavior:
templates:
move: '@YourBundle/Sortable/_drag_drop.html.twig'
@CodeclipseSortableBehavior/Default/_sort_drag_drop.html.twig.MongoDB Integration
db_driver: mongodb and ensure your entity uses Doctrine\ODM\MongoDB\Mapping\Annotations./**
* @MongoDB\Field(type="int")
*/
private $sortRank;
Batch Updates
sort action in SonataAdmin to reorder multiple items at once:
$listMapper->add('_sortable', 'sortable', [
'sortable_group' => 'batch_group',
'batch_update' => true,
]);
codeclipse.sortable.pre_save or codeclipse.sortable.post_save events.
// src/EventListener/SortableListener.php
public static function getSubscribedEvents()
{
return [
'codeclipse.sortable.pre_save' => 'onPreSort',
];
}
position_field in your entity (e.g., @Assert\NotBlank).protected function configureListFields(ListMapper $listMapper)
{
$listMapper->add('_sortable', 'sortable', [
'sortable_group' => 'admin_only',
'access_control' => 'ROLE_ADMIN',
]);
}
Field Name Mismatch
position_field in config matches the actual field name in your entity (case-sensitive).php bin/console debug:container codeclipse_sortable_behavior for loaded config.Cache Issues
php bin/console cache:clear
php bin/console cache:pool:clear cache.app
Group Misconfiguration
sortable_group in configureListFields matches a group returned by getSortableGroups().sortable_groups.entities.Doctrine Events Conflict
position if you use other bundles that also define lifecycle callbacks (e.g., prePersist/preUpdate).MongoDB Quirks
/**
* @MongoDB\Index(keys={"sortRank"="asc"}, options={"unique"=true})
*/
APP_DEBUG=1 in .env to see Symfony profiler data for sortable actions.public function onPreSort(SortableEvent $event)
{
\Log::debug('Sortable event:', [
'entity' => $event->getEntity()->getId(),
'group' => $event->getGroup(),
'position' => $event->getPosition(),
]);
}
-- ORM Example
SELECT id, position FROM your_entity ORDER BY position;
Custom Sort Logic
SortableBehavior service to modify sorting behavior:
# config/services.yaml
Codeclipse\SortableBehaviorBundle\Sortable\SortableBehavior:
arguments:
$positionField: 'custom_position'
$groupField: 'custom_group'
Add UI Feedback
{# @YourBundle/Sortable/_drag_drop.html.twig #}
{% extends '@CodeclipseSortableBehavior/Default/_sort_drag_drop.html.twig' %}
{% block sortable_script %}
{{ parent() }}
<script>
$(document).on('sortupdate', function() {
alert('Order updated!');
});
</script>
{% endblock %}
Bulk Reordering
protected function configureListActions(ListMapper $listMapper)
{
$listMapper->add('reorder_group', 'button', [
'template' => '@App/Admin/reorder_group.html.twig',
'route' => ['name' => 'app_admin_reorder', 'parameters' => ['group' => 'your_group']],
]);
}
Fallback for Non-Sortable Groups
$listMapper->add('_sortable', 'sortable', [
'sortable_group' => 'default',
'disabled' => $this->getSortableGroups() === [],
]);
Localization
{% trans from 'SonataAdminBundle' %}Move up{% endtrans %}
How can I help you explore Laravel packages today?