warpig's avatar
Level 12

exclude first 3 rows, arranging by vote count

I want to get the latest posts based by vote counts but i want it to ignore the first 3 rows because i am already showing those 3 records

        $popularPosts = Post::query()
            ->leftJoin('upvote_downvotes', 'post_id', '=', 'upvote_downvotes.post_id')
            ->select('posts.*', DB::raw('COUNT(upvote_downvotes.id) as upvote_count'))
            ->where(function($query) {
                $query->whereNull('upvote_downvotes.is_upvote')
                    ->orWhere('upvote_downvotes.is_upvote', '=', 1);
            })
            ->where('active', '=', 1)
            ->where('published_at', '<', Carbon::now())
            ->orderByDesc('upvote_count')
            ->groupBy('posts.id')
            ->skip(3)
            ->limit(5)
            ->get();

this is how im displaying them

<article class="mx-auto px-4 bg-white dark:bg-zinc-900 shadow-md py-3">
    <div class="md:flex-col w-full">
        <div class="flex-col md:col-span-4 flex">
            @foreach($popularPost->categories as $category)
                <a href="category/{{ $category->slug }}" class="text-red-600 font-bold uppercase">
                    {{ $category->title }}
                </a>
            @endforeach
            <a href="{{ route('view', $popularPost) }}">
                <h3 class="text-lg dark:text-gray-200 dark:hover:text-red-600 hover:text-red-600 transition ease-out">
                    {{$popularPost->title}}
                </h3>
            </a>
            <!-- <p>
                {{ $popularPost->getFormattedDate() }} | {{ $popularPost->human_read_Time }}
            </p> -->
        </div>
    </div>
</article> <!-- latest news end -->

how can i do it? the part where it says orderByDesc('upvote_count') is arranging the records by vote count but it is currently showing posts from the first 2 rows on my posts table.

0 likes
18 replies
MohamedTammam's avatar

When you skip, you skip rows from the results rows. Thus, you're skipping after filtering, so if you're not using the same filter for the first three rows you will have duplicate results.

If I understand you correctly, here's how you can do it:

$firstPosts = Post::limit(3)->get();
$popularPosts = Post::query()
  ->whereNotIn('id', $firstPosts->pluck('id'))
// The rest of the query like you did without the "skip" method.
1 like
warpig's avatar
Level 12

@MohamedTammam hello sir, I have this on my variable

        $latestPost = Post::where('active', '=', 1)
            ->where('published_at', '<', Carbon::now())
            ->orderBy('published_at', 'desc')
            ->with('categories')
            ->limit(3)
            ->first();

If i change first to ->get() i get an error because If im not mistaken get retrieves a collection. This error appears:

Method Illuminate\Database\Eloquent\Collection::getThumbnail does not exist.

It's a relationship i have currently on my Posts model, i am just making sure I retrieve the thumbnail with that method.

how can i overcome this, i simply want to use this variable to retrieve the frist 3 posts so i dont have to make a 2nd variable just for the other 2 posts. Thank you.

MohamedTammam's avatar

@warpig I don't understand what do you want exactly, but if your question on how to get the first three posts and store the first on a variable, here's how

$firstPosts = Post::where('active', '=', 1)
            ->where('published_at', '<', Carbon::now())
            ->orderBy('published_at', 'desc')
            ->with('categories')
            ->limit(3)
            ->get();

$latestPost = $firstPosts->count() ? $firstPosts[0] : null;
Snapey's avatar

@warpig

If i change first to ->get() i get an error because If im not mistaken get retrieves a collection. This error appears:

you MUST use get. you want a collection of posts

This error appears:

because you must loop over the collection to get the image for individual posts

warpig's avatar
Level 12

@MohamedTammam

SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous 
        //show the latest post created
        $latestPosts = Post::where('active', '=', 1)
            ->where('published_at', '<', Carbon::now())
            ->orderBy('published_at', 'desc')
            ->limit(3)
            ->get();

        // show the 3 most popular posts
        $popularPosts = Post::query()
            ->whereNotIn('id', $latestPosts->pluck('id'))
            ->leftJoin('upvote_downvotes', 'post_id', '=', 'upvote_downvotes.post_id')
            ->select('posts.*', DB::raw('COUNT(upvote_downvotes.id) as upvote_count'))
            ->where(function($query) {
                $query->whereNull('upvote_downvotes.is_upvote')
                    ->orWhere('upvote_downvotes.is_upvote', '=', 1);
            })
            ->where('active', '=', 1)
            ->where('published_at', '<', Carbon::now())
            ->orderByDesc('upvote_count')
            ->groupBy('posts.id')
            ->limit(8)
            ->get();
MohamedTammam's avatar

@warpig Change this line

->whereNotIn('id', $latestPosts->pluck('id'))

To be

->whereNotIn('posts.id', $latestPosts->pluck('id'))
warpig's avatar
Level 12

@MohamedTammam thanks, and how do i exclude the current post from showing in the "latest posts" sidebar while being in the the post.view page?

i've tried this ->where('id', '!=', $post->id) but doesn't work

    public function show(Post $post, Request $request)
    {
        if (!$post->active || $post->published_at > Carbon::now()) {
            throw new NotFoundHttpException();
        }
	        $popularPosts = Post::query()
            ->where('id', '!=', $post->id)
            ->get();
}

SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous

Snapey's avatar

@warpig It tells you..... you are joining tables and there are two tables with id

        $popularPosts = Post::query()
        ->where('posts.id', '!=', $post->id)
        ->get();
warpig's avatar
Level 12

@Snapey i thought i was saying not to use the post id of the current post id, current post id being the variable in relation with the id column last thing i want to do is join anything wtf

Snapey's avatar

@warpig in which case, the error is from some other code. Look more closely at the error message.

Your previous code, you were definitely joining tables. My guess is that still the code you are running.

warpig's avatar
Level 12

@Snapey yes, definitely, im making a left join with the "upvote_downvotes", and the "posts" table, but then what thing in common from these 2 tables can i use to exclude the current post and avoid from getting it rendered? this being the code:

        $popularPosts = Post::query()
            ->where($post->id, '=', 'post_id')->pluck('id')
            ->leftJoin('upvote_downvotes', 'post_id', '=', 'upvote_downvotes.post_id')
            ->select('posts.*', DB::raw('COUNT(upvote_downvotes.id) as upvote_count'))
            ->where(function($query) {
                $query->whereNull('upvote_downvotes.is_upvote')
                    ->orWhere('upvote_downvotes.is_upvote', '=', 1);
            })
            ->where('active', '=', 1)
            ->where('published_at', '<', Carbon::now())
            ->orderByDesc('upvote_count')
            ->groupBy('posts.id')
            ->limit(5)
            ->get();

i think im missing to communicating the id of the post... i believe i am doing the right thing in grabbing the current post id ?? and then applying the pluck but it doesn't make human sense to say "grab this current post and exclude it from itself" that's how im viewing it. sorry if that doesn't make any sense 🤷‍♂️

Snapey's avatar

@warpig I already showed you by using posts.id

but why have you ruined your query with this crap;

->where($post->id, '=', 'post_id')->pluck('id')
1 like
Snapey's avatar
        $popularPosts = Post::query()
            ->whereNotIn('id', $latestPosts->pluck('id'))
            ->where('posts.id', '!=', $post->id)
            ->leftJoin('upvote_downvotes', 'post_id', '=', 'upvote_downvotes.post_id')
            ->select('posts.*', DB::raw('COUNT(upvote_downvotes.id) as upvote_count'))
            ->where(function($query) {
                $query->whereNull('upvote_downvotes.is_upvote')
                    ->orWhere('upvote_downvotes.is_upvote', '=', 1);
            })
            ->where('active', '=', 1)
            ->where('published_at', '<', Carbon::now())
            ->orderByDesc('upvote_count')
            ->groupBy('posts.id')
            ->limit(8)
            ->get();
warpig's avatar
Level 12

@Snapey yea that might be correct only that i forgot to mention i am doing this from another function but in the same controller. so i guess calling the home function and then grabbing the $latestpost like this:

->whereNotIn('id', $this->home($latestPosts)->pluck('id'))

needs to be switched to something else, or maybe that's not where the error is..

Snapey's avatar

@warpig who can tell? Just seems complete chaos from here, and if you can't read error messages then you are going to struggle.

warpig's avatar
Level 12

@Snapey thank you, for your time invested in here now get lost lol

Snapey's avatar

so one query is getting three latest posts (ignoring votes)

and the second is getting the popular posts ( with most votes )

It is possible to get duplicates in the two sets, but not guaranteed. So skipping the three most popular seems the wrong strategy

You should use @mohamedtammam suggestion to ignore the ids of the latest posts from the results

Please or to participate in this conversation.