Gabesz
Gabesz

Reputation: 303

Eloquent next record

I am trying to get the last 3 blog post from the database into single variables (for templates). I saw a good implementation at some other thred and it works fine for the next record but on the third query returns with NULL. What is your opinion about this problem?

BlogController.php:

public function getIndex($l = 'hu')
    {
        $post_last = Post::orderBy('created_at', 'desc')->first();
        $post_2 = $post_last->next($post_last->created_at);
        $post_3 = $post_2->next($post_2->created_at);

        var_dump($post_3);
    }

Post.php:(Model)

<?php

namespace Civitas;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
     * Physical table name
     */
    protected $table = 'posts';


    /**
     * Get next result in record list
     *
     * @param $created_at
     * @return mixed
     */
    public function next($c) {
        return Post::where('created_at', '<', $c)->get()->first();
    }
}

Upvotes: 0

Views: 3151

Answers (2)

Phi Nguyen
Phi Nguyen

Reputation: 3056

In your next function, the result will give the earliest post, not the next one. Therefore, the third call will return null because there is no post after the earliest one. Adding orderBy for created_at field, it will work as expected.

public function next(){
    return static::where('created_at', '<' , $this->created_at)
                    ->orderBy('created_at','desc')
                    ->first();
}

Then in your controller, you can call like this:

$post_last = Post::orderBy('created_at', 'desc')->first();
$post2 = $post_last->next();
$post3 = post_last->next()->next();

Upvotes: 1

lukasgeiter
lukasgeiter

Reputation: 152950

I can't tell why your function doesn't work, but I suggest you try this approach:

$posts = Post::orderBy('created_at', 'desc')->take(3)->get();
$post1 = $posts->shift();
$post2 = $posts->shift();
$post3 = $posts->shift();

This will only run one query instead of three. Calling shift() on the collection will then return the first item and remove it so the second post will be "first" the next time you call it.

Upvotes: 1

Related Questions