20

I've noticed that in Laravel when chaining a skip() you must also use take() as well. I want to skip the first n rows but take the rest. The take method only allows integers how can I do this without resorting to some hacky trick such as specifying a large number for take?

Helen Che
  • 1,689
  • 4
  • 20
  • 38

3 Answers3

34

Basically, with every OFFSET, a LIMIT must be supplied for mysql to work. Therefore, there is no way to do this without sepcifying a limit. We need some php mojo to work here.

Let's say we have an Eloquent Class named Attendance. Here's what should work:

//Getting count
$count = Attendance::count();
$skip = 5;
$limit = $count - $skip; // the limit
$collection = Attendance::skip($skip)->take($limit)->get();
Yousof K.
  • 1,140
  • 8
  • 18
  • 1
    I agree. Interesting read also http://stackoverflow.com/questions/255517/mysql-offset-infinite-rows – jhmilan Dec 13 '14 at 18:05
3

If you're using MySQL and you don't want to have 2 queries to get the max rows, you may use the PHP maximum INT value as take() parameter e.g. take(PHP_INT_MAX).

It's because Laravel Query Grammar casts the limit to integer. So you can't use a larger number than that.

From MySQL documentation on LIMIT:

To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter.

For example:

\App\User::skip(10)->take(PHP_INT_MAX)->get();
SubRed
  • 3,039
  • 1
  • 15
  • 16
2

I think this is not a good answer, because you're forcing to do two queries, the right way will be:

$collection = Attendance::skip($skip)->take($limit)->get();
$collection.shift();

You can see more about collections here

Franco Risso
  • 1,544
  • 2
  • 12
  • 18
  • Cannot understand why? and no define the $limit first? – robspin Jan 20 '19 at 16:55
  • 1
    Basically calling count() first will trigger a count query, that's not what you want, you only want take a number and skip the first, this translate to SQL to LIMIT , – Franco Risso Jan 22 '19 at 11:33