Crud: ajaxRequest order by relation column

Created on 6 Oct 2017  路  5Comments  路  Source: Laravel-Backpack/CRUD

how can i order by relation string column

$this->crud->addColumn([
            'type' => 'select',
            'name' => 'brand_id',
            'entity' => 'brand',
            'attribute' => 'name',
            'model' => 'App\Models\Brand'
        ]);

i need to sort by brands.name column, but now it doesnt work, wrong result

UPD it work when i disable enableAjaxTable(), but i need AjaxTable

Ask-It-On-Stack-Overflow pending

Most helpful comment

Ordering by a relationship column is anything but a niche use case.

All 5 comments

You could:

  1. Make a new relation which is sorted as you like;
  2. Install something like https://github.com/jedrzej/sortable (or pimpable) and pass the relevant parameters through/to the model;
  3. Use an AJAX based select.

There may be other ways too.

Here was a suggestion to solve this problem, but it was not accepted, but I'm using it and it works very well.
Ex:
AjaxTable.php.txt

Hi.

The problem derives from the AjaxTable::search() method checking whether the table field exists in order to add the order logic.

 if ($column['tableColumn']) {
      $this->crud->orderBy($column['name'], $column_direction);
  }

It would be nice to use a custom order function, but it will get ignored. So you need to override the search function.

Here's what I did:

  1. Installed https://github.com/jedrzej/sortable, added the trait in the model;
  2. Added a custom sort function in the model to add joins and sort by relation;
  3. Exteded \Backpack\CRUD\app\Http\Controllers\CrudFeatures\AjaxTable::search() in the desired CRUD Controller to check for the Sortable trait in the model and add the sorted scope if found:
    public function isSortable()
    {
         return method_exists($this->crud->getModel(), 'scopeSorted');
    }
    public function search()
    {
        if ($this->request->input('order')) {
            $column_number = $this->request->input('order')[0]['column'];
            $column        = $this->crud->findColumnById($column_number);
            $direction     = $this->request->input('order')[0]['dir'] ? : 'asc';
            $name          = $column['name'];

             // If the column is not in the database, add the sorted scope
            if (!$column['tableColumn']) {
                if ($this->isSortable()) {
                    $this->crud->addClause('sorted', $name . ',' . $direction);
                }
            }
        }
        return parent::search();
    }
  1. Also, in the CRUD controller, make the orderable parameter true in the column definition:

    $this->crud->addColumn(
        [
            'label'     => '...',
            'name'      => '...',
            'orderable' => true,
        ]);
    

This, of course, can be achieved without the Sortable trait (with a simple model scope).

It's butt ugly, but it works.

If you can achieve your custom ordering with a scope, you can add that scope on Backpack with:

if (!$this->request->input('order')) {
  $this->crud->addClause('scopeName');
}

If you can't, and you have to resort to using joins, I'm afraid it would make the results be something else than an Eloquent collection - so Backpack listing will stop working.

Looks like we have to make a choice here. And since supporting millions of rows is a very popular use case, and ordering by a relationship column is a niche use case, I'm afraid we're going with millions of rows. So I'm afraid ordering by a relationship column is not supported in Backpack. At least not at the moment, or not that I know of. If anybody comes up with a way to do it, please reopen this issue or raise another one.

Cheers!

Ordering by a relationship column is anything but a niche use case.

Was this page helpful?
0 / 5 - 0 ratings