I Has Many Through Relation (Laravel the missed shortcut)

Submitted by Mahmoud_Zalt - 8 years ago

This sample covers the following scenario: Every course has may chapters, while a chapter can belong to only one course. In the other hand every chapter has many videos while a video can belong to many chapters. I will write the description below.

/**
If you have table A and B and C
where table A has many of B (OneToMany) and B has many of C (OneToMany)
inorder to access the table C from table A you can use the Laravel shortcut (HasManyThrough) on the Table A and the problem is solved

BUT
if you have table A and B and C
where table A has many of B (OneToMany) and B has many of C (ManyToMany)
you cannot use the laravel's (HasManyThrough) shortcut to access the table C from table A,
what you can do in this case is very simple:


in this example table A will be [courses], table B will be [chapters], and table C will be [videos]
where every course has may chapters, while a chapter can belong to only one course. in the other hand every chapter has many videos while a video can belong to many chapters.
---------------------------------
*/





<?php namespace Moubarmij\Models;

use Eloquent;

class Video extends Eloquent{

   protected $table = 'videos';

    /*************************************************************
     * Query Scopes
     **************************************************************/

    public function scopePublished($query)
    {
        return $query->where('published', '=', '1');
    }
    
    public function scopeOrdered($query)
    {
        return $query->orderBy('order_number', 'ASC');
    }

    /*************************************************************
     * Relations
     **************************************************************/

    public function chapters()
    {
        return $this->belongsToMany('Moubarmij\Models\Chapter', 'chapters_videos');
    }


}




<?php namespace Moubarmij\Models;

use Eloquent;

class Chapter extends Eloquent{

   protected $table = 'chapters';

    /*************************************************************
     * Query Scopes
     **************************************************************/

    public function scopePublished($query)
    {
        return $query->where('published', '=', '1');
    }

    public function scopeOrdered($query)
    {
        return $query->orderBy('order_number', 'ASC');
    }

    public function scopeWithVideos($query)
    {
        return $query->with(['videos' => function($q)
        {
            $q->ordered();
        }]);
    }


    /*************************************************************
     * Relations
     **************************************************************/

    public function course()
    {
        return $this->belongsTo('Course');
    }
    
    public function videos()
    {
        return $this->belongsToMany('Moubarmij\Models\Video', 'chapters_videos');
    }

}

 



<?php namespace Moubarmij\Models;

use Eloquent;

class Course extends Eloquent{

   protected $table = 'courses';

    /*************************************************************
     * Query Scopes
     **************************************************************/

    public function scopeVisible($query)
    {
        return $query->where('visible', '=', '1');
    }

    public function scopeOrdered($query)
    {
        return $query->orderBy('order_number', 'ASC');
    }

    public function scopeWithChapters($query)
    {
        return $query->with(['chapters' => function($q)
        {
            $q->ordered();
        }]);
    }

    public function scopeWithChaptersAndVideos($query)
    {
        return $query->with(['chapters' => function($q)
        {
            $q->ordered()->withVideos();
        }]);
    }


    /*************************************************************
     * Relations
     **************************************************************/

    public function chapters()
    {
        return $this->hasMany('Moubarmij\Models\Chapter');
    }


}