Laravel belongsToMany relationship
There are often times when your data has a “belongsToMany” relationship. Laravel handles this relationship really beautifully!
I learn best by example, so we’ll do this post as an example I’m currently working on.
In our application we have multiple related websites. Each of these sites stands on its own with users being able to register individually on each site. We wanted to update this so that when a user registers on one site their details are automatically pushed to a central database server and then from there pushed to the other sites in the group.
The websites are written in WordPress (not my choice – I love wordpress as a CMS but I think for a pure app Laravel is better). The central database app I’ve written in Laravel.
Within our laravel app we have the users table:
table users id | name | email | updated_at | modified_at 1 John john@example.com 2018-01-01 01:00:00 2018-01-01 01:00:00
There is also a sites table:
table sites id | name | url | created_at | modified_at 1 Foo http://foo 2018-01-01 01:00:00 2018-01-01 02:00:00 2 Bar http://bar 2018-01-01 01:00:00 2018-01-01 02:00:00
As stated, each user should be pushed to all the sites so we have User belongsToMany relationship with Sites.
To achieve that in Laravel we need to add a pivot table. Laravel expects the pivot table to be named with the names of the table making up the relationship, and with the table belonging to the other table first…
In other words, our users belong to many sites, so our pivot table is:
table users_sites id | users_id | sites_id | updated_at | modified_at 1 1 1 2018-01-01 23:20:12 2018-01-01 23:20:12
In our users model we create a function called sites. This name is the name of the Sites model we have the belongs to many relationship with. In function sites we return the belongs to many relationship object:
<?php namespace App; use IlluminateDatabase\Eloquent\Model; class Users extends Model { public function sites() { return $this->belongsToMany(Sites::class); } }
Finding users belonging to sites:
It now becomes extremely easy to find which sites users belong to:
By viewing the table entries above you can see that user John (me:) belongs only to site Foo.
To see this is Laravel we use the sites function as a PROPERTY call on the user object! Open tinker and see this working as such:
>>> $c = \App\Users::find(1); => App\Users {#825 id: 1, name: "John", email: "it@rftags.co.za", created_at: "2018-02-14 09:53:01", updated_at: "2018-02-14 09:53:01", }
using the \App\Users::find(1); where 1 is the user’s ID we can an object ($c) of that user.
We can now call the sites function as a property on that object to see the sites the users belongs to, ie, $c->sites:
>>> $c->sites => Illuminate\Database\Eloquent\Collection {#784 all: [ App\Sites {#810 id: 1, name: "Foo", created_at: "2018-02-14 09:53:27", updated_at: "2018-02-14 09:53:27", pivot: Illuminate\Database\Eloquent\Relations\Pivot {#822 clients_id: 1, sites_id: 1, }, }, ], }
Finding users NOT in the belongsToMany Relationship in Laravel
As mentioned, our application calls for users to belong to all the sites. To do this we have a queue running over this relationship to see which sites a user still needs to be pushed to.
Of course, in the example above the relationship shows us which site the user DOES belong to and we want to see which (s)he DOESN’T belong to.
One approach is to use Laravel’s diff function on objects.
We first get an object with all the sites:
>>> $allSites = \App\Sites::all(); => Illuminate\Database\Eloquent\Collection {#826 all: [ App\Sites {#832 id: 1, site_name: "Foo", url: "http://foo", created_at: "2018-02-14 09:53:27", updated_at: "2018-02-14 09:53:27", }, App\Sites {#833 id: 2, site_name: "Bar", url: "http://bar", created_at: "2018-02-14 09:53:39", updated_at: "2018-02-14 09:53:39", }, ], }
Next, we call diff on the allSites object by passing in the User object ($c) we created earliers:
>>> $notIn = $allSites->diff($c->sites); => Illuminate\Database\Eloquent\Collection {#821 all: [ AppSites {#833 id: 2, site_name: "Bar", url: "http://bar", created_at: "2018-02-14 09:53:39", updated_at: "2018-02-14 09:53:39", }, ], }
Conclusion
And there we have it. With only a few simple lines of code Laravel reduces the complexity of these relationships!
Let me know in the comments if spot a mistake or improvement or ask if you have a question!
John, a seasoned Freelance Full Stack Developer based in South Africa, specialises in delivering bespoke solutions tailored to your needs. With expertise in PHP, Laravel, Vue3, and Nuxt3, I am equipped to tackle any project, ensuring robust, scalable, and cutting-edge outcomes.
My comprehensive skill set enables me to provide exceptional freelance services both remotely and in person. Whether you’re seeking to develop an innovative application or require meticulous refinement of existing systems, I am dedicated to elevating your digital presence through unparalleled technical prowess and strategic development methodologies. Let’s connect to transform your vision into reality.