Search code examples
phplaraveleloquentmodelrelationship

Defining Eloquent relationships and tables between three Laravel models


I'm working on an admin tool app using Laravel/Vue/Inertia for a club that I belong to, and I'm trying to determine how best to create the Eloquent relationships for three models.

Every year, each member is required to put in a certain number of work hours around the club helping out. The club is broken out into multiple areas, referred to as Disciplines. When a member puts in their time, currently they fill out a paper slip that contains the discipline, the date, the hours, and requires an approval signature by the "owner" of a discipline or a designated approver for the area. This is what I want to implement in my app. When a WorkHours entry is created, the user will enter the date, number of hours, discipline, and a designated approver for that discipline.

What this means is that a user record can be both a) an approver on a Discipline and b) a user for whom the WorkHours record is being submitted (but not both on one WorkHours record, for obviuos reasons).

So as I see it, I need three models and the following fields based on the facts that:

  • A Discipline model can have multiple approvers (users) and a user can be an approver for multiple disciplines (aka many to many)
  • A WorkHours entry belongs to exactly one user (user_id) and has exactly one approver (approver_id)
  • A User can have multiple WorkHours records and belong to multiple Disciplines

Discipline

  • name
  • approvers() = ->belongsToMany(User::class)

WorkHours

  • date
  • hours
  • member() = ->belongsTo(User::class) as user_id
  • discipline() = ->belongsTo(Discipline::class)
  • approver() = ->hasOne(User::class) as approver_id

User

  • disciplines() = ->belongsToMany(Discipline::class)
  • workHours() = ->hasMany(WorkHours::class)

And my tables and relevant fields would look like this:

work_hours

  • id
  • user_id
  • approver_id

disciplines

  • id
  • name

users

  • id
  • name

disciplines_users

  • user_id
  • discipline_id

Does that all seem correct? Or is there a better way I could define my relationships?


Solution

  • As detailed here, this was the answer.

    My issue (as I suspected) was in a relationship definition. Once I changed the approval() definition in User from this

        public function approval()
        {
            return $this->belongsTo(WorkHours::class, 'approver_id');
        }
    

    to this

        public function approvals()
        {
            return $this->haMany(WorkHours::class, 'approver_id');
        }
    

    it worked fine. There was no user id value to write since the relationship for the approver was wrong, which was why it was looking for a default value.