1

I have an issue where I need to paginate an eloquent collection that has calculated fields, fields not in the database. Livewire's WithPagination trait only wants to be applied to an Eloquent query builder, not collections. This, on its own, works. I can display the calculated field in the blade file with a paginated set. The problem comes when I want to filter or sort by the calculated fields. Normally, I can do this with the collections methods where() and sortBy(); But the paginate method doesn't return a collection so I can't use those.

The calculated field is not in the database so I can't use orderBy() or the builders where() method. And if I do those with the collection methods the I no longer have a paginator object in my blade and the link() method no longer exists.

I'm not sure what the solution here would be.

The 'health' field is calculated by an attribute (Illuminate\Database\Eloquent\Casts\Attribute) on the model.

$this->search() returns a query builder object.

public function render()
{
    $projects = $this->search()->get();
    
    if (array_key_exists('health', $this->searchParms)) {
        $projects = $projects->whereIn('health', $this->searchParms['health']['value']);
    }
    
    $this->projectCount = $projects->count();
    foreach (array_reverse($this->sortFields) as $col => $dir) {
        if ($dir == 'desc')
            $projects = $projects->sortByDesc($col);
        elseif ($dir == 'asc')
            $projects = $projects->sortBy($col);
    }
    $projects = $projects->paginate(10); //Fails ->paginate can't be applied to collections

    return view( ...
    

If I try paginate first it also doesn't work. This {{$projects->links()}} fails when called from the blade because $projects is just a collection at that point. Method Illuminate\Database\Eloquent\Collection::links does not exist.

public function render()
{
    $projects = $this->search()->paginate(10);
    
    if (array_key_exists('health', $this->searchParms)) {
        $projects = $projects->whereIn('health', $this->searchParms['health']['value']);// blade fails
    }
    
    $this->projectCount = $projects->count();
    foreach (array_reverse($this->sortFields) as $col => $dir) {
        if ($dir == 'desc')
            $projects = $projects->sortByDesc($col);//blade fails 
        elseif ($dir == 'asc')
            $projects = $projects->sortBy($col);//blade fails 
    }

    return view( ...

Larval 12 with Livewire 3.

2
  • 1
    Would this help? stackoverflow.com/q/65710480/5808894 stackoverflow.com/a/75755710/5808894 Commented Sep 8 at 4:59
  • Use SQL not Collections Push the computed attribute into the SELECT alias it then filter/sort on that alias and paginate php $q = $this->search()->addSelect([ 'health' => DB::raw("CASE WHEN score>=80 THEN 'good' WHEN score>=50 THEN 'ok' ELSE 'bad' END") ]); Then php if (!empty($this->searchParms['health']['value'])) { $q->whereIn('health', $this->searchParms['health']['value']); } foreach ($this->sortFields as $c => $d) { $q->orderBy($c, $d); } $projects = $q->paginate(10); This keeps Livewire pagination working and lets you where/orderBy by health Commented Sep 8 at 8:56

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.