PHPackages                             chamber-orchestra/doctrine-sort-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. chamber-orchestra/doctrine-sort-bundle

ActiveSymfony-bundle[Database &amp; ORM](/categories/database)

chamber-orchestra/doctrine-sort-bundle
======================================

Symfony bundle for automatic sort order management in Doctrine ORM entities. Recalculates positions on flush with grouped ordering, second-level cache support, and PHP attribute configuration.

v8.0.12(2mo ago)0541↓12.5%1MITPHPPHP ^8.5CI passing

Since Jan 4Pushed 2mo agoCompare

[ Source](https://github.com/chamber-orchestra/doctrine-sort-bundle)[ Packagist](https://packagist.org/packages/chamber-orchestra/doctrine-sort-bundle)[ Docs](https://github.com/chamber-orchestra/doctrine-sort-bundle)[ RSS](/packages/chamber-orchestra-doctrine-sort-bundle/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (16)Versions (15)Used By (1)

[![PHP Composer](https://github.com/chamber-orchestra/doctrine-sort-bundle/actions/workflows/php.yml/badge.svg)](https://github.com/chamber-orchestra/doctrine-sort-bundle/actions/workflows/php.yml)[![codecov](https://camo.githubusercontent.com/190c8f09a819c24295f0dca18556c63f63037392fbbd00265abcb0fcd172630f/68747470733a2f2f636f6465636f762e696f2f67682f6368616d6265722d6f72636865737472612f646f637472696e652d736f72742d62756e646c652f67726170682f62616467652e737667)](https://codecov.io/gh/chamber-orchestra/doctrine-sort-bundle)[![PHPStan](https://camo.githubusercontent.com/71936661c994bdd70ec588a6771c605f8584906d8054c5d607a3bcc6bd943f3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6d61782d627269676874677265656e)](https://phpstan.org/)[![Latest Stable Version](https://camo.githubusercontent.com/fce92566bca8a0ef6f895eeee71acd62ac443186a9f6fbaded8a522eb431e7ac/68747470733a2f2f706f7365722e707567782e6f72672f6368616d6265722d6f72636865737472612f646f637472696e652d736f72742d62756e646c652f76)](https://packagist.org/packages/chamber-orchestra/doctrine-sort-bundle)[![License](https://camo.githubusercontent.com/2ff899c9f9535122b8ca0ce19431abb69a96f4499b47c37e06eaa7bd45a8320a/68747470733a2f2f706f7365722e707567782e6f72672f6368616d6265722d6f72636865737472612f646f637472696e652d736f72742d62756e646c652f6c6963656e7365)](https://packagist.org/packages/chamber-orchestra/doctrine-sort-bundle)[![PHP 8.5](https://camo.githubusercontent.com/699b5e675b37d1256e54ec33a27ecfad75891142c2791f3ee3292c553cb31994/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e352d626c75653f6c6f676f3d706870)](https://camo.githubusercontent.com/699b5e675b37d1256e54ec33a27ecfad75891142c2791f3ee3292c553cb31994/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e352d626c75653f6c6f676f3d706870)[![Doctrine ORM 3](https://camo.githubusercontent.com/b52372e263348ab9a511539d5b6382c4628572d9ffc3bc4df8b175d704fc24c3/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446f637472696e652532304f524d2d332d6f72616e67653f6c6f676f3d646f637472696e65)](https://camo.githubusercontent.com/b52372e263348ab9a511539d5b6382c4628572d9ffc3bc4df8b175d704fc24c3/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446f637472696e652532304f524d2d332d6f72616e67653f6c6f676f3d646f637472696e65)[![Symfony 8](https://camo.githubusercontent.com/a7d902ab1b809ccff2eaa21df5aadd13f1b13e22e4e4c49f40d020b918f48e05/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53796d666f6e792d382d707572706c653f6c6f676f3d73796d666f6e79)](https://camo.githubusercontent.com/a7d902ab1b809ccff2eaa21df5aadd13f1b13e22e4e4c49f40d020b918f48e05/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53796d666f6e792d382d707572706c653f6c6f676f3d73796d666f6e79)

Doctrine Sort Bundle
====================

[](#doctrine-sort-bundle)

Symfony bundle for automatic sort order management in Doctrine ORM entities. Recalculates sort positions on every `EntityManager::flush()`, keeping ordered lists consistent without manual reindexing. Uses PHP attributes to mark the sort field, supports grouped ordering (e.g., per parent or category), and handles insertions, deletions, and reordering transparently.

Features
--------

[](#features)

- **Automatic reordering** — sort positions are recalculated on flush, no manual gaps or renumbering needed
- **Grouped sorting** — maintain independent sort orders per parent, category, or any relation via `groupBy`
- **PHP attribute configuration** — single `#[Sort]` attribute on your entity property, zero YAML/XML config
- **Drag-and-drop ready** — set the new position and flush; surrounding items shift automatically
- **Second-level cache support** — works with Doctrine SLC; optionally evict cache collections and query regions on sort changes
- **Change tracking policies** — compatible with both `DEFERRED_IMPLICIT` and `DEFERRED_EXPLICIT` tracking
- **Provided traits** — `SortTrait` and `SortByParentTrait` with convenience methods (`moveUp`, `moveDown`, `moveToBeginning`, `moveToEnd`)

Installation
------------

[](#installation)

```
composer require chamber-orchestra/doctrine-sort-bundle
```

If Symfony Flex is enabled, the bundle is registered automatically. Otherwise, add it to `config/bundles.php`:

```
return [
    // ...
    ChamberOrchestra\DoctrineSortBundle\ChamberOrchestraDoctrineSortBundle::class => ['all' => true],
];
```

Quick Start
-----------

[](#quick-start)

### 1. Mark a sort field

[](#1-mark-a-sort-field)

Add the `#[Sort]` attribute to any integer column. The bundle will automatically maintain sequential ordering starting from 1.

```
use ChamberOrchestra\DoctrineSortBundle\Mapping\Attribute\Sort;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class TodoItem
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(type: 'integer', options: ['unsigned' => true, 'default' => 0])]
    #[Sort]
    private int $sortOrder = 0;

    // Setting sortOrder to 0 appends the item to the end of the list.
    // Setting sortOrder to 1 moves it to the beginning.
    // Any value in between inserts at that position; surrounding items shift automatically.
}
```

### 2. Grouped ordering

[](#2-grouped-ordering)

Maintain separate sort sequences per parent, category, or any relation:

```
use ChamberOrchestra\DoctrineSortBundle\Mapping\Attribute\Sort;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class Task
{
    #[ORM\ManyToOne]
    private ?Project $project = null;

    #[ORM\Column(type: 'integer', options: ['unsigned' => true, 'default' => 0])]
    #[Sort(groupBy: ['project'])]
    private int $sortOrder = 0;

    // Each project has its own independent sort sequence.
    // Moving a task to a different project removes it from the old sequence
    // and inserts it into the new one.
}
```

### 3. Using traits

[](#3-using-traits)

For common cases, use the provided traits instead of writing boilerplate:

```
use ChamberOrchestra\DoctrineSortBundle\Contracts\Entity\SortInterface;
use ChamberOrchestra\DoctrineSortBundle\Entity\SortTrait;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class TodoItem implements SortInterface
{
    use SortTrait;

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;
}
```

`SortTrait` provides `getSortOrder()`, `setSortOrder()`, and convenience methods:

MethodEffect`moveUp()`Decrease sort position by 1 (minimum 1)`moveDown()`Increase sort position by 1`moveToBeginning()`Set sort position to 1`moveToEnd()`Set sort position to 0 (appends to end)`SortByParentTrait` extends `SortTrait` with a `$parent` ManyToOne field and `#[Sort(groupBy: ['parent'])]`.

Attribute Options
-----------------

[](#attribute-options)

```
#[Sort(
    groupBy: ['parent'],           // Fields that define independent sort groups
    evictCollections: [             // Second-level cache collections to evict on change
        [ParentEntity::class, 'children'],
    ],
    evictRegions: ['my_query_region'], // Query cache regions to evict on change
)]
```

OptionTypeDefaultDescription`groupBy``array``[]`Entity field names that define sort groups. Each unique combination of group values has its own sort sequence. Supports `Column`, `ManyToOne`, and `ManyToMany` fields.`evictCollections``array``[]`List of `[FQCN, collectionField]` pairs. These Doctrine second-level cache collections are evicted when sort order changes.`evictRegions``array``[]`Query cache region names to evict when sort order changes.How It Works
------------

[](#how-it-works)

1. The bundle listens to Doctrine's `onFlush` event
2. For each entity with a `#[Sort]` attribute that was inserted, updated, or deleted, it collects the changes
3. Overlapping changes within the same group are merged into ranges to minimize database queries
4. Affected entities are fetched, reordered in memory, and sort values are reassigned sequentially
5. Doctrine's `recomputeSingleEntityChangeSet()` ensures the corrected values are persisted in the same flush

This means you never need to manually manage gaps, shift items, or renumber sequences — just set the desired position and flush. Multiple reorder operations within a single flush or across multiple flushes in an explicit transaction are fully supported.

Compatibility
-------------

[](#compatibility)

BundlePHPSymfonyDoctrine ORM8.0^8.58.03.6+Running Tests
-------------

[](#running-tests)

```
composer test
```

License
-------

[](#license)

MIT

###  Health Score

46

—

FairBetter than 93% of packages

Maintenance86

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 86.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~5 days

Total

13

Last Release

62d ago

PHP version history (2 changes)v8.0.1PHP ^8.4

v8.0.3PHP ^8.5

### Community

Maintainers

![](https://www.gravatar.com/avatar/44037eb1c8dc2c4fa9871ac213653f33e22a9348dcec7132df07cc71933f2a2e?d=identicon)[wtorsi](/maintainers/wtorsi)

---

Top Contributors

[![wtorsi](https://avatars.githubusercontent.com/u/2115840?v=4)](https://github.com/wtorsi "wtorsi (13 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")

---

Tags

doctrinedoctrine-ormdrag-and-dropentity-orderinglist-orderorderablephpphp-attributesreordersecond-level-cachesortsort-ordersortablesortingsymfonysymfony-bundlesymfonydoctrinesortablesortSymfony Bundlesortingdrag-and-dropdoctrine-ormreorderorderablepositionphp-attributessort-orderentity-orderinglist-order

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/chamber-orchestra-doctrine-sort-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/chamber-orchestra-doctrine-sort-bundle/health.svg)](https://phpackages.com/packages/chamber-orchestra-doctrine-sort-bundle)
```

###  Alternatives

[rutorika/sortable

Adds sortable behavior and ordering to Laravel Eloquent models. Grouping and many to many supported.

299992.5k14](/packages/rutorika-sortable)[ahmed-bhs/doctrine-doctor

Runtime analysis tool for Doctrine ORM integrated into Symfony Web Profiler. Unlike static linters, it analyzes actual query execution at runtime to detect performance bottlenecks, security vulnerabilities, and best practice violations during development with real execution context and data.

813.1k](/packages/ahmed-bhs-doctrine-doctor)[andanteproject/soft-deletable-bundle

A Symfony Bundle to handle soft deletable with Doctrine Entities

1028.3k](/packages/andanteproject-soft-deletable-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
