Milos Sretin
Milos Sretin

Reputation: 1748

Retrieving data in Laravel

I can't find solution how to retrieve links that belongs to user where campaign is active?

Here are my models:

User model:

public function links(){
    return $this->hasMany('Link','user_id');
}
public function analytic(){
    return $this->hasManyThrough('Analytic','Link');
}

Campaign model:

public function task(){
    return $this->hasMany('Task','campaign_id');
}
public function links(){
    return $this->hasManyThrough('Link','Task');
}

Task model:

public function campaign(){
    return $this->belongsTo('Campaign','campaign_id');
}
public function links(){
    return $this->hasMany('Link','task_id');
}
public function analytic(){
    return $this->hasManyThrough('Analytic','Link');
}

Link model:

public function task(){
    return $this->belongsTo('Task','task_id');
}
public function user(){
    return $this->belongsTo('User','user_id');
}
public function analytic(){
    return $this->hasMany('Analytic','link_id');
}

So, admin creates a campaign and task that belongs to campaign and users can start task, once they start task they are getting their link assigned for that task and campaign.

In this case I can easily count all user links:

$user = User::find(1);
echo $user->links->count();

But my question is how to echo only links that are related to active campaigns.

Again: CAMPAIGN has many TASK, TASK has many LINKS, USER has many LINKS.

Get the number of links that belongs to user only for active campaigns.

Similar thing with analytics :(

Every link has many analytics ( tracking clicks )

Analytic model:

public function links(){
    return $this->belongsTo('Link','link_id');
}

Also need to echo the count of links only for tasks that are under active campaign.

Upvotes: 0

Views: 177

Answers (1)

Jarek Tkaczyk
Jarek Tkaczyk

Reputation: 81187

First off, you don't need to run query for a user if you have his id:

$user=User::find($id); // redundant

// instead
Link::where('user_id', $id)->count();

Now to get those links for active campaigns:

Link::whereHas('task', function ($q) {
  $q->whereHas('campaign', function ($q) {
     $q->active(); // or where('status', 'active'); see below
  });
})->where('user_id', $id)->get();

// of course you can start with $user->links()->whereHas ... instead

My example covers scope for a campaign:

// Campaign model
public function scopeActive($query)
{
  $query->where('status', 'active');
}

The same goes for count:

Link::whereHas('task', function ($q) {
  $q->whereHas('campaign', function ($q) {
     $q->active();
  });
})->where('user_id', $id)->count();

You can wrap that whereHas chain in a scope as well:

// Link model
public function scopeOnlyActiveCampaigns($query)
{
  $query->whereHas('task', function ($q) {
    $q->whereHas('campaign', function ($q) {
       $->active();
    });
  });
}

// then simply:
Link::onlyActiveCampaigns()->where('user_id', $id)->count();

And as stated in the comment: use consistent names for relations, it will make your life easier:

$link->analytic; // collection, better analytics
$analytic->links; // single Link model, better link etc

Upvotes: 4

Related Questions