Search code examples
phplaraveleloquentlaravel-7eloquent-relationship

Retrieving records with _____________ relationship?


I have 5 tables.

User tabel => This table stores the data of users.
Exam table => This table stores the data of exams.
Feeds table => This table stores the data of feeds.
Exam_User_Pivot table => This table stores the data of users and exams means the user_id and exam_id.
Exam_Feed_Pivot table => This table stores the data of exams and feeds means the exam_id and feed_id.

Now, I want to retrieve the no. of users per each feed ?

I have three models :

1. User Model

<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable implements MustVerifyEmail
{
    use Notifiable;

    protected $primaryKey = 'uid';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password', 'phone',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function exams()
    {
        return $this->belongsToMany(exam::class, 'exam_user', 'user_id', 'exam_id')->withTimeStamps();
    }
}

2. Exam Model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class exam extends Model
{
    protected $primaryKey = 'eid';

    protected $fillable = [
        'exam_name',
    ];
}

3. Feed Model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Feed extends Model
{
    protected $primaryKey = 'fid';

    protected $fillable = [
        'feed_type', 'title', 'description', 'feed_media', 'source',
    ];

    public function feedexams()
    {
        return $this->belongsToMany(exam::class, 'exam_feed', 'feed_id', 'exam_id')->withTimeStamps();
    }
}
  • Users have many-to-many relationship with Exams
  • Feeds have many-to-many relationship with Exams

I want to retrieve the no. of users per each feed And I don't know which relationship can be use ?


Solution

  • So first add the following two functions to your Exam Model.

    Add to Exam model:

     public function feeds() {
             return $this->belongsToMany('App\Feed')->withTimeStamps(); // 
      }
    
     public function users() {
        return $this->belongsToMany('App\User')->withTimeStamps(); //
      }
    

    I want to retrieve the no. of users per each feed .....

    The reasoning is based on the following three points:

    1. get the feed,
    2. then get exams of that feed (one feed has many exams)
    3. then get users in each of these exams (here we will use a loop to ensure we count users of each exam from 2 above)

    Loop through all feeds as:

     foreach(App\Feed::all() as $feed) { 
     //here you are accessing all related exams using the function feedexams() that you have created in the feeds model
     
       $exams  = $feed->feedexams();  
    
     //because each exam will have its own users, we need a way to count the users for each exam, and finally ensure we sum or count all of them. we create a counter called $user_per_feed_count to keep or remember the users count as we loop through all exams. 
     //Finally we will output this counter which will have the total of all users belonging to exams which belong to the feed.
    
       $users_count = 0; //initialize a users counter with zero
    
       foreach($exams as $exam) {
        //now we update our counter by adding the number of users for each exam
        $users_count +=  $exam->users()->count();
       }
       //HERE IS YOUR no. of users per each feed.
      echo "Feed " . $feed->name . "has " . $users_count . " users"; 
     }
    

    Expected output will be as follows ...

    Feed myfeed has 10 users

    Feed otherfeed has 38 users

    Now to test it, just go to your routes/web.php and add the following code

    Route::get('getusers',  function () {
        foreach (App\Feed::all() as $feed) {
            $exams  = $feed->feedexams();
            $users_count = 0; //initialize a users counter with zero
            foreach ($exams as $exam) {
            //$users_count +=  $exam->users()->count();
            $users_count +=  $exam->has('users') ? $exam->users()->count() : 0;
    
        }
            echo "Feed " . $feed->name . "has " . $users_count . " users";
        }
    });
    

    then open your browser and type this link:

    http://YOUR_PROJECT_NAME_HERE/getusers and press enter:

    Note: Replace YOUR_PROJECT_NAME_HERE with your actual project name. Make sure you have some exams,users, and feeds already in your database. MY RESULTS

    exam_user table

    exam_feed table

    final result