Skip to content

Incorrect sorting by columns with non-unique value #6881

@TheDoctor0

Description

@TheDoctor0
  • Laravel Version: 12.17.0
  • Nova Version: 5.7.2
  • PHP Version: 8.4.8
  • Database Driver & Version: MySQL 8
  • Operating System and Version: Ubuntu 24
  • Browser type and version: Chrome
  • Reproduction Repository: None

Description:

When ordering the table in Nova by a column that has the same value more than once, you will likely see the same record twice, or some not at all, when switching between pages.

The explanation is quite simple here, and it just comes down to how the database handles sorting in such cases. It does not guarantee that you will see the same order when limiting + offsetting (paginating) records. To mitigate that, a secondary column with unique values must be provided for sorting to ensure consistency, which Nova surprisingly does not do by default.

I found that this issue was already reported back in 2022, but closed: #4481

Detailed steps to reproduce the issue on a fresh Nova installation:

Add a Nova resource with a field that has multiple non-unique values, enough to have at least 2 pages, sort by that column, and switch pages. As a result, you will see some records appear for the second time, and some will be missing.

Fix:

Logic in applyOrderings needs to be changed to apply ordering by model key at the end by default.
I also added an option to specify default ordering for a resource using a static property called $orderBy,
following the general Nova convention. It was requested in #156.

protected static function applyOrderings($query, array $orderings): Builder
{
    $orderings = array_filter($orderings);

    if (empty($orderings) && property_exists(static::class, 'orderBy')) {
        $orderings = array_filter(static::$orderBy);
    }

    if (empty($orderings)) {
        return empty($query->getQuery()->orders) && ! static::usesScout()
            ? static::defaultOrderings($query)
            : $query;
    }

    foreach ($orderings as $column => $direction) {
        $query->orderBy($column, $direction);
    }

    return ! static::usesScout()
        ? static::defaultOrderings($query)
        : $query;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions