How to build query with multi level relations in Laravel Eloquent

Viewed 344

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");
}

EDIT: After rethinking the structure I figured out that Optin has a many-to-one relation with Participant.

2 Answers

Since Participant has a one-to-many relation with Optin I added the following relation on the Sponsor model. With the passing the Optin model als a second parameter to the belongsToMany method, since it functions as an intermediate table.

public function participants()
{
    return $this->belongsToMany(Participant::class, Optin::class);
}

From there out I could easily get all the participants with adding subqueries belonging to the sponsor like so:

$sponsor = Sponsor::find(1); 
$participants = $sponsor->participants()->createdToday()->get();
foreach($participants as $participant)
{
    //do something with $participant
}

if you want multi level data from same table this solution help you with hasmany relationship in laravel.and with('point') is function name.your name will be diferent.

class Master extends Model
{
    public function point() {
        return $this->hasMany(Master::class,'point_id')->with('point');
    }
}
Related