orchidsoftware / platform

Orchid is a @laravel package that allows for rapid application development of back-office applications, admin/user panels, and dashboards.
https://orchid.software
MIT License
4.43k stars 651 forks source link

Sort and Filter by a Specific Field of Relation Table #2234

Open KLA6 opened 2 years ago

KLA6 commented 2 years ago

Is your feature request related to a problem? Please describe.

I'm always frustrated when I make a layout with relation table and field, e.g., ...

I've already seen there are some discussions about this issue as well (e.g., https://github.com/orchidsoftware/platform/discussions/1766), but it seems using Eloquent Filter (https://orchid.software/en/docs/filters/#eloquent-filter) is the only way to solve it, however it is a little bit complicated.


Describe the solution you'd like

So, what I want to suggest is...

public function columns(): array { return [

  TD::make( 'user_id.name' , 'Author Name'  )->sort()->filter( Input ::make() )
  TD::make( 'user_id.email', 'Author Email' )->sort()->filter( Input ::make() )

  # I hope just calling by dot notation makes sorting and filtering to be possible.

]; }

Describe alternatives you've considered

Because the Eloquent Filter gives the alternative solution, so my request is only about coding convenience.

I always really appreciate Orchid's cool structure which makes productions quick, and this suggestion may be loved by others as well. : )


Additional context

What if there is another easy way for this, and if I couldn't know it, I want to apologize first, and also please let me know that. T T

Edinburgher commented 1 year ago

@tabuna This is something a lot of people struggle with as there is also no documentation on how to achieve this with sorts. Sorts are not filters. My solution feels hacky and I don't know if you intended a sort using a relation to be implemented like this. To use the sort in a table I named the TD 'customer_name' and added the CustomerNameSort Filter to the query in the list screen.

<?php

namespace App\Orchid\Filters;

use App\Models\Customer;
use Illuminate\Database\Eloquent\Builder;
use Orchid\Filters\Filter;

class CustomerNameSort extends Filter
{
    /**
     * The array of matched parameters.
     *
     * @return array|null
     */
    public function parameters(): ?array
    {
        return ['sort'];
    }

    /**
     * Apply to a given Eloquent query builder.
     *
     * @param Builder $builder
     *
     * @return Builder
     */
    public function run(Builder $builder): Builder
    {
        $sort = $this->request->get('sort', '');
        if (str_contains($sort, 'customer_name')) {
            $direction = str_starts_with($sort, '-')? 'desc' : 'asc';
            return $builder->orderBy(Customer::select('name')
                ->whereColumn('customers.id', 'orders.customer_id')
                ->orderBy('name')
                ->limit(1), $direction);
        } else {
            return $builder;
        }
    }
}