Flukedit's avatar

Pagination view issue

This may be a really simple issue, however I can't for the life of me solve it.

I am trying to paginate a simple eloquent query, however when I pass the results of the query into my view, I get the following error: Method Tightenco\Collect\Support\Arr::query does not exist.

I'm fairly certain that the issue is not in the controller since if I dd() the response I get the following object which looks fine:

Paginator {#523 ▼
  #hasMore: true
  #items: Collection {#522 ▼
    #items: array:5 [▶]
  }
  #perPage: 5
  #currentPage: 1
  #path: "https://cms.test/iris/documentqueue"
  #query: []
  #fragment: null
  #pageName: "page"
  +onEachSide: 3
  #options: array:2 [▶]
}

Any ideas would be much appreciated. Cheers

0 likes
21 replies
Flukedit's avatar

My query is as simple as

$jobs = DocumentQueue::orderBy('id', 'desc')->paginate(5);

And I'm passing it to the view as follows:

return view('index')->with('jobs', $jobs);

May be good to note that even without the orderBy() part of the query, it has the same issue.

jlrdw's avatar

Then your view should have:

{{ $jobs->links() }}

If you dd $jobs in controller, do you see the results.

Flukedit's avatar

In my view I've tried with and without that. as well as

{!! $job->links() !!}

All it seems to do is change the exception from BadMethodException to Facade/Ignition/Exceptions/ViewException, and appends the view file path to the end of error:

Method Tightenco\Collect\Support\Arr::query does not exist. (View: /{full_path}/index.blade.php)
jlrdw's avatar

Read my reply jobs plural. No exclamation points.

Flukedit's avatar

Sorry that was just a typo on my end when adding in here.

I had tried the version you suggested {{ $jobs->links() }}, as well as {!! $jobs->links() !!}

Interestingly, when I dd() $jobs->links() in the controller I get the same error thrown, so that would mean that it is not a view error at all.

jlrdw's avatar

If you dd the jobs like:

$jobs = DocumentQueue::orderBy('id', 'desc')->paginate(5);

dd($jobs);

return view('index')->with('jobs', $jobs);

Do you get results.

Flukedit's avatar

Yeah, the following output of $jobs shows the following:

LengthAwarePaginator {#541 ▼
  #total: 195
  #lastPage: 39
  #items: Collection {#559 ▼
    #items: array:5 [▼
      0 => DocumentQueue {#558 ▶}
      1 => DocumentQueue {#556 ▶}
      2 => DocumentQueue {#552 ▶}
      3 => DocumentQueue {#554 ▶}
      4 => DocumentQueue {#553 ▶}
    ]
  }
  #perPage: 5
  #currentPage: 1
  #path: "https://cms.test/iris/documentqueue"
  #query: []
  #fragment: null
  #pageName: "page"
  +onEachSide: 3
  #options: array:2 [▼
    "path" => "https://cms.test/iris/documentqueue"
    "pageName" => "page"
  ]
}
jlrdw's avatar
{{ $jobs->links() }}

Should be working in the view.

Does the foreach work fine.

Flukedit's avatar

Yeah if I run the query with a get() instead of paginate(5) as follows, the foreach works totally fine.

$jobs = DocumentQueue::orderBy('id', 'desc')->get();
jlrdw's avatar

Show your entire controller method, paginate should be working.

Flukedit's avatar

Been testing it out with the else statement near the bottom.

<?php

namespace App\Http\Controllers;

use App\DocumentQueue;

class DocumentQueueController extends Controller
{
    public function index()
    {
        $status = request()->query('status');
        $header = 'Jobs';

        if ($status === 'failed') {
            $header = 'Failed jobs';
            $jobs = DocumentQueue::where('sent', 'f')
                ->where('tries', '>=', 3)
                ->orderBy('id', 'desc')
                ->get();
        } elseif ($status === 'completed') {
            $header = 'Completed jobs';
            $jobs = DocumentQueue::where('sent', true)
                ->orderBy('id', 'desc')
                ->get();
        } elseif ($status === 'pending') {
            $header = 'Pending jobs';
            $jobs = DocumentQueue::where('sent', false)
                ->where('tries', '<', config('documentqueue.maximum_number_of_attempts'))
                ->orderBy('id', 'desc')
                ->get();
        } else {
            $jobs = DocumentQueue::orderBy('id', 'desc')->paginate(5);
            // $jobs = DocumentQueue::orderBy('id', 'desc')->get();
        }
            
        return view('documentqueue.index')
            ->with('header', $header)
            ->with('jobs', $jobs);
    }
}
jlrdw's avatar

You probably need to break this query down into small steps and troubleshoot each step to figure out where the problem is.

I mean your original question it should definitely work with that query.

dd your way through various steps.

I would shift a lot of what you have into query scopes.

Flukedit's avatar

Yeah quite possibly.

I was hoping it was something simple that I had overlooked like a typo or something, but that does not seem to be the case at the moment :(

Cheers for taking a look.

Flukedit's avatar

As an update, after looking into it a bit deeper, it turns out that it was due to an older version of tightenco/collect being used in another project conflicting with Laravel collections.

Since we are using the same version of php for both projects, the older project has include paths set in the php.ini file which were also being loaded for the Laravel project, causing the conflict.

So, luckily it wasn't due to the code, which makes me feel a bit better about it :)

munazzil's avatar

Try with like below because you are using orderBy seems to be problem,

       $jobs = DocumentQueue::oldest()->paginate(5);

else you need new ,

       $jobs = DocumentQueue::latest()->paginate(5);
Flukedit's avatar

I gave it a go, however the issue seems to be on the paginate function rather than orderBy.

Using latest() and oldest() do look nicer in the code, so I will update my code to use those, however it did not make a difference regarding the pagination.

munazzil's avatar

Yo have to use end of the foreach condition,

    </tr>
    @endforeach
</table>               
<div>   {!!$jobs!!} </div>

else use,

           {{ $jobs->links() }}  ,  {!! $jobs->links() !!}
Snapey's avatar

I don't understand why you are getting TightenCo class in there?

Only your else statement actually returns a paginated class. All the others use get() (so ->links() will blow up)

You can more efficiently use a query that you extend

    public function index()
    {
        $status = request()->query('status');

    $query = DocumentQueue::query();

        if ($status === 'failed') {
            $header = 'Failed jobs';
            $query->where('tries', '>=', 3)
        } elseif ($status === 'completed') {
            $header = 'Completed jobs';
            $query->where('sent', true)
        } elseif ($status === 'pending') {
            $header = 'Pending jobs';
            $query->where('sent', false)
                ->where('tries', '<', config('documentqueue.maximum_number_of_attempts'))
        } else {
            $header = 'Jobs';
        }
        $jobs = $query->orderBy('id', 'desc')->paginate(5);
 
        return view('documentqueue.index')
            ->with('header', $header)
            ->with('jobs', $jobs);
    }
Snapey's avatar

oh, and when you get an error, state the file and line that throws the error

Flukedit's avatar

As far as I could tell, Tightenco was getting autoloaded by php, along with all the other libraries, and when I removed that it started working as intended.

Regarding only the else statement returning the pagination class, I was only doing that for testing purposes since it was simplest query being run in the file. The intention was to modify the rest of the statement once I had managed to get the pagination working.

The extension of the query is quite a nice idea. I was not exactly happy with the way the function was coded, however hadn't gotten around to refactoring it at all, so that could be a solution to that issue.

Please or to participate in this conversation.