Home > Enterprise >  How to build query with multi level relations in Laravel Eloquent
How to build query with multi level relations in Laravel Eloquent

Time:11-18

I have three models. Sponsor, Optin and Participant. Sponsor has a one-to-many relationship with Optin and Optin has a one-to-one Participant.

Which make the models look like this:

Sponsor model

class Sponsor extends Model
{ 
    public function optins()
    {
        return $this->hasMany(Optin::class);
    }
}

Optin model

class Optin extends Model
{    

    public function sponsor()
    {
        return $this->belongsTo(Sponsor::class);
    }
    public function participant()
    {
        return $this->belongsTo(Participant::class);
    }
}

Participant model

class Participant extends Model
{
    public function optins()
    {
        return $this->hasMany(Optin::class);
    }

    public function scopeCreatedToday($query)
    {
        return $query->whereDate('created_at', Carbon::today());
    } 
}

Now in a daily scheduled task I want to iterate through all participants that where created today and that opted in to a certain Sponsor to send them like an email or something. Now I got as far as echoing the id's of the belonging participants. But the next step is to get the participant object and filter them by the right created date. But I am a little lost on how to handle this.

$sponsor = Sponsor::find(1);
$count = $sponsor->optins()->count();
echo("Count: " . $count . "\n");
$optins = $sponsor->optins()->get();
foreach($optins as $optin)
{
    echo($optin->participant_id . "\n");
}

CodePudding user response:

Step 1 is to define the relationship between Sponsor and Participant models using a belongsToMany relationship. I assume your optins table has both participant_id and sponsor_id columns.

class Sponsor extends Model
{ 
    public function optins()
    {
        return $this->hasMany(Optin::class);
    }
    public function participants()
    {
        return $this->belongsToMany(Participant::class, 'optins');
    }
}

Then you want to eager load the relationship using the with() method, and also filter it based on your condition of the creation date. This will make the participants available as a collection.

$date = now()->subDay(); // or whatever you like.
$start = $date->startOfDay();
$end = $date->endOfDay();

$sponsor = Sponsor::where('id', 1)
    ->with([
        'participants' => function($q) use ($start, $end) {
            $q->whereBetween('participants.created_at', [$start, $end]);
        }
    ])
    ->firstOrFail();

$count = $sponsor->participants->count();
echo("Count: $count\n");
foreach($sponsor->participants as $participant)
{
    echo("$participant->name\n");
}

CodePudding user response:

please try to define the primary key's of all models and when use the function's set the foreign keys of every function

  • Related