vendredi 17 novembre 2017

Constraining a nested 3rd level relationship

I'm building an api using eager loading so i can simply return the user model with its deep relations and it automatically be converted as json. Here's the set up.

users
    id
    ..

clients
    id
    ..

user_clients
    id
    user_id
    client_id
    ..

campaigns
    id
    ..

client_campaigns
    id
    client_id
    campaign_id
    ..

campaign_activities
    id
    campaign_id
    ..

client_campaign_activity_templates
    id
    campaign_activity_id
    client_id *(templates are unique per client)*
    ..

I've setup the models' relationships.

User
    public function clients() {
        return $this->belongsToMany('App\Client','user_clients');
    }

Client
    public function campaigns() {
        return $this->belongsToMany('App\Campaign','client_campaigns');
    }

Campaign
    public function activities() {
        return $this->hasMany('App\CampaignActivity');
    }

CampaignActivity
    public function templates() {
        return $this->hasMany('App\ClientCampaignActivityTemplate')
    }

I have a simple api endpoint to provide a JSON of a User object including its deep relations using eager loading.

public function getLoggedInUser(Request $request) {
    return \App\User::with('clients.campaigns.activities.templates')->find($request->user()->id);
}

Testing this using postman, I can get the user including its deep relations.

{
    "user": {
        "id": 1,
        "name": "user1",
        "clients": [
            {
                "id": 1,
                "name": "client1",
                "campaigns": [
                    {
                        "id": 1,
                        "name": "campaign1",
                        "activities": [
                            {
                                "id": 1,
                                "name": "activity1",
                                "templates": [
                                    {
                                        "id": 1,
                                        "name": "template1 for client1",
                                        "client_id": 1,
                                        "body": "this is a template.",
                                    }, {
                                        "id": 2,
                                        "name": "template1 for client2",
                                        "client_id": 2,
                                        "body": "This is a template for client2"
                                    }
                                ]
                            }, {
                                "id": 2,
                                "name": "activity2",
                                "templates": []
                            }, {
                                "id": 3,
                                "name": "activity3",
                                "templates": []
                            }
                        ]
                    }
                ]
            }
        ]
    }
}

However, on the user->clients->campaigns->activities->templates level, it will list all the templates for that activity. I know based on the code of the relationships of the models above that it's supposed to behave like that.

So the question is How would you filter the templates to filter for both campaign_activity_id and client_id?

I've been experimenting on how to filter the templates so it will only list templates for that activity AND for that client as well. I have a working solution but it's N+1, I'd prefer eloquent approach if possible. I've been scouring with other questions, answers and comments for a closely similar problem, but I had no luck, hence I'm posting this one and seek for your thoughts. Thank you



from Newest questions tagged laravel-5 - Stack Overflow http://ift.tt/2j3hjQu
via IFTTT

Aucun commentaire:

Enregistrer un commentaire