Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

andyjameswhite's avatar

Laravel Query Builder - Simple Question!

I'm fairly new to Laravel and query builder I'm trying to do something I thought would be pretty easy, but I must be missing something really obvious.

To strip it back to it's simplest

I have 3 models

  1. PaperFormat, morphs to other models (e.g. Topic), and has many papers
  2. Paper, belongs to PaperFormat
  3. Topic , morphOne to PaperFormat and has a method of papers(), intended to retrieve all papers from that topic using query builder.

For the purposes of this example I'm trying to exclude where papers.id = 2 or 3 using whereNotIn()

I have 20 papers in the table (all with a PaperFormat ID of 1 that morphs to Topic which also has an ID of one). There's currently only 1 Topic and 1 Paperformat in their respective tables.

And the query returns 18 results, as I expected as I'm excluding 2 using whereNotIn().

However all 18 results in the array are Paper ID 1 !!!!!

Same if I change it whereIn(1, 2 ,3, 4) I get 4 results in the array are Paper ID 1 !!!!! again!

I'm guessing I've got something wrong that's causing it to mess up. (first post here please be kind!)

Please help!


class PaperFormat extends Model
{
    public function paperFormatable()
    {
        return $this->morphTo();
    }
    
    public function papers()
    {
        return $this->hasMany(Paper::class);
    }
}
class Paper extends Model
{
    public function paperFormat()
    {
        return $this->belongsTo(PaperFormat::class);
    }
}
class Topic extends Model
{
    public function paperFormat()
    {
        return $this->morphOne(PaperFormat::class, 'paper_formatable');
    }

    public function papers() 
    {
        $papers = Paper::
                        whereNotIn('papers.id', [2, 3])
                        ->join('paper_formats', 'papers.paper_format_id', '=', 'paper_formats.id')
                        ->where('paper_formatable_id', $this->id)
                        ->where('paper_formatable_type', 'App\Models\Topic')
                        ->get();
      
        return $papers;
    }
}
0 likes
5 replies
MichalOravec's avatar
Level 75

Always use select with join, otherwise columns will be replaced, like id in your case.

So

$papers = Paper::select('papers.*')
    ->whereNotIn('papers.id', [2, 3])
    ->join('paper_formats', 'papers.paper_format_id', '=', 'paper_formats.id')
    ->where('paper_formatable_id', $this->id)
    ->where('paper_formatable_type', 'App\Models\Topic')
    ->get();
1 like
andyjameswhite's avatar

I should add that when I remove the joins, no problem at all as expected it returns an array with all objects expected.

andyjameswhite's avatar

Thank you for such a quick response.

In my efforts to slim down my code I realise now I accidentally removed the select(), but it was that which was causing the problem, because I also had the joined table in there.

How would I return the joined table's data as well?

My actual code was more like this, so causing the same problem you identified in a different way

$papers = Paper::select('papers.*', 'paper_formats.*')
    ->whereNotIn('papers.id', [2, 3])
    ->join('paper_formats', 'papers.paper_format_id', '=', 'paper_formats.id')
    ->where('paper_formatable_id', $this->id)
    ->where('paper_formatable_type', 'App\Models\Topic')
    ->get();
andyjameswhite's avatar

What an obvious solution, too much staring at the screen and laziness at not selecting specific columns.

Thanks a bunch

Please or to participate in this conversation.