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

matthias's avatar

Model referencing another in multiple different ways

Hi there, I'm new to laravel and I'm asking myself how to do it better:

I have a model (Book) wich references another model (Person) in multiple different ways.

There are the following database tables:

| books                |              |
| -------------------- | ------------ |
| int id               |              |
| int author_id        | -> person.id |
| int lecturer_id      | -> person.id |
| string title etc...  |              |


| persons            |
| ------------------ |
| int id             |
| string name etc... |


| pivot_book_reviewer |              |
| ------------------- | ------------ |
| int book_id         | -> book.id   |
| int reviewer_id     | -> person.id |

So a book references persons in 3 ways. There is a book's author, it's lecturer and multiple reviewers.

My models looks like this:

class Book extends Model {
    //[...]

    public function author(){
        return $this->hasOne('App\Person', 'id', 'author_id');
    }

    public function lecturer(){
        return $this->hasOne('App\Person', 'id', 'lecturer_id');
    }

    public function reviewers(){
        return $this->belongsToMany('App\Person', 'pivot_book_reviewer', 'reviewer_id', 'book_id');
    }
}
class Person extends Model {
    //[...]
    public function book_author(){
        return $this->hasMany('App\Book', 'author_id', 'id');
    }

    public function book_lecturer(){
        return $this->hasMany('App\Book', 'lecturer_id', 'id');
    }

    public function books_reviewer(){
        return $this->belongsToMany('App\Book', 'pivot_book_reviewer', 'book_id', 'reviewer_id');
    }
}

This seems to work, but is this the right way of doing it? Obviously not.

But what is the right way? Should I create a child class for every type of person?

A little hint would be very helpful! :)

0 likes
4 replies
JarekTkaczyk's avatar
Level 53

@matthias If you ask about differently named method referencing the same model, then yes, that's the way to go.

However, most of these relations are defined wrong. Here's the right way:

// Book
public function author(){
    return $this->belongsTo('App\Person', 'author_id', 'id'); // you can skip `id`
}

public function lecturer(){
    return $this->belongsTo('App\Person', 'lecturer_id');
}

public function reviewers(){
    return $this->belongsToMany('App\Person', 'pivot_book_reviewer', 'book_id', 'reviewer_id'); // keys order
}


// Person
public function books_reviewer(){
    return $this->belongsToMany('App\Book', 'pivot_book_reviewer', 'reviewer_id', 'book_id');
}

hasMany relations are OK.

matthias's avatar

Thank you for answering my question!

But wouldn't it be better to define a child class for every sub-type of Person?

class Author extends Person { //[...] }
class Lecturer extends Person { //[...] }
class Reviewer extends Person { //[...] }

...and reference to the child class:

class Book extends Model {
    //[...]

    public function author(){
        return $this->hasOne('App\Author', 'id', 'author_id');
    }

   //[...]
}
JarekTkaczyk's avatar

@matthias Only for the relations? No.

If you have any other reasons to do that, then yes. I guess you don't.

1 like

Please or to participate in this conversation.