Pulling next and previous records with Laravel

Pulling next and previous records with Laravel web View Project

Feb 27, 2014

During my journey to create the greatest portfolio of all time, I came across many design flaws in my own software. These things tend to happen a lot whenever you're trying something new, or exploring domains that you're not completely familiar with.

I've worked with Laravel before, but I'm still considered a newbie or maybe a novice when it comes to web programming. I've always been more focused on visual aspects and user experience. In other words, I'm not a PHP expert. I know how to make animated boxes and columned layouts with CSS3 and HTML5. I pay attention to Bootstrap's Github. But whenever I try to read blog posts by Laravel creators, I tend to end up confused and read it twice for good measure.

Most of these problems are things I encounter from lack of experience with them. Just like in order to solve IE compatibility problems requires direct experience, solving these issues also requires such experience. This is why StackOverflow is a good thing.


The problem was almost verbatim the above question.

I wanted to pull the next and previous records by their dates. The problem was of course that some records had the same dates. This meant that my attempted next and previous buttons encountered infinite loops whenever the next record was the same date as the current.

The solution above works out perfectly. All I did was add a couple parenthesis to the OR WHERE statement, and transcribed all of it to Laravel 4.

$next_record = Artwork::select('id')
   ->where('created_at', '>', $artwork->created_at) //where the art is newer
   ->orWhere(function($query) use ($artwork) //or, if the art was made on the same day and the id is greater
      $query->where('created_at', '=', $artwork->created_at)
         ->where('id', '>', $artwork->id);
   ->orderBy('created_at')->orderBy('id') //order by oldest first and smallest id first
   ->first(); //get just one record
$prev_record = Artwork::select('id')
   ->where('created_at', '<', $artwork->created_at) //where the art is older
   ->orWhere(function($query) use ($artwork) //or, if the art was made on the same day and the id is lesser
      $query->where('created_at', '=', $artwork->created_at)
         ->where('id', '<', $artwork->id);
   ->orderBy('created_at', 'desc')->orderBy('id', 'desc')  //order by newest first and largest id first
   ->first(); //get just one record

Note the funny bit in the orWhere method. Those functions are known as anonymous functions, closures, or lambda functions. They're the sexy new kid on the block in PHP.

In order to use my $artwork object I had created earlier in my closures, which is an Eloquent model, I had to add the "use" keyword. If you have never seen the use keyword, read about it here: http://blog.dubbelboer.com/2012/04/07/php-use-keyword.html

As Erik Dubbelboer writes, there are three ways to pass variables to your closures. In my case, the use keyword did just the trick I needed, allowing me to use my local variable in the scope of the closure.