Răzvan
Răzvan

Reputation: 991

Eloquent ORM conditional model relationship

My schema is as follows:

courses
 -id
 -title
 -...

documents
 -id
 -...

videos
 -id
 -path
 -...

course_resources
 -id
 -course_id
 -type [docs OR videos]
 -resource_id

Every course resource can be of multiple types, in this case documents or videos. How should one write the relationship in order to retrieve either the document or the video based on the type column in the course_resources pivot table? Obviously the resource_id can take either the value of video_id or of the document_id.

Ideally I would like something like this:

$course=Course::with('resources')->find(1);
foreach($course->resources as $resource){
 //check resource type
 //do something
}

Upvotes: 2

Views: 133

Answers (1)

Bogdan
Bogdan

Reputation: 44526

You should use Many-to-Many Polymorphic Relations to accomplish this. Your course_resources table structure is almost right, you need however to replace it with this table, so that Laravel can understand the relation and fetch the correct resources:

| coursable        |
|------------------|
| course_id        |
| coursable_id     |
| coursable_type   |

First you need to have three models for Course, Document and Video. Then you need to add the polymorphic relations to the Course model:

class Course extends Model
{
    public function documents()
    {
        return $this->morphedByMany('App\Document', 'coursable');
    }

    public function videos()
    {
        return $this->morphedByMany('App\Video', 'coursable');
    }
}

Now you can do the following to access resources, no more conditions needed to differentiate them:

// Eager load both relations
$course = Course::with('documents', 'videos')->find(1);

// Iterate over documents
foreach($course->documents as $document) {
    // ...
}

// Iterate over videos
foreach($course->videos as $video) {
    // ...
}

Upvotes: 2

Related Questions