kingmaker / laravel-many-to-many-self-relationship
Laravel Many to Many Relationship on the same Model through a pivot table providing two-way association.
Installs: 23 411
Dependents: 0
Suggesters: 0
Security: 0
Stars: 16
Watchers: 1
Forks: 3
Open Issues: 1
Requires
- php: ^7.2|^8.0
- ext-json: *
- illuminate/database: ~8.35|~9.0|~10.0|~11.0
Requires (Dev)
- orchestra/testbench: ^6.0|^7.0|^8.0|^9.0
README
This package includes an extension to the belongsToMany
Relationship of the Laravel
allowing two-way association between the same model with a single Entry on the pivot table.
Installation
The package can be installed via Composer.
composer require kingmaker/laravel-many-to-many-self-relationship
Version
This package is available on specific Laravel versions.
Usage
Include the HasBelongsToManySelfRelation
trait in the Model class and
define the relation method as follows:
use Illuminate\Database\Eloquent\Model; use Kingmaker\Illuminate\Eloquent\Relations\HasBelongsToManySelfRelation; class Post extends Model { use HasBelongsToManySelfRelation; public function relatedPosts() { return $this->belongsToManySelf('related_posts', 'post1', 'post2'); } }
It is that simple and has all the Methods available on the belongsToMany()
.
The Related Posts can be accessed like any normal relation.
$post = Post::first(); $post->relatedPosts; // returns Collection of Related Posts
This is an extension over the native
BelongsToMany
class provided by the Eloquent.
Example
Consider there are 'posts' table and 'related_posts' table. The Post represent Post in the blog and it can have related posts similar to them.
posts: | id | title | body | +----+-------+------+ | 1 | a | ... | | 2 | b | ... | | 3 | c | ... | | 4 | d | ... | +----+-------+------+ related_posts: | id | post1 | post2 | +----+-------+-------+ | 1 | 1 | 3 | | 2 | 1 | 4 | | 3 | 2 | 1 | | 4 | 2 | 3 | | 5 | 3 | 4 | | 6 | 4 | 2 | +----+-------+-------+
The belongsToManySelf
relation provides two-way association when calling the Relation.
Post::find(1)->relatedPosts; // returns Posts with id 2, 3, 4 Post::find(2)->relatedPosts; // returns Posts with id 1, 3, 4 Post::find(3)->relatedPosts; // returns Posts with id 1, 2, 4 Post::find(4)->relatedPosts; // returns Posts with id 1, 2, 3
Caution
There is a possibility for the returning of duplicate related object if the entities are related by 2rows on the Pivot table.
Use Cases
This two-way associated Many-to-Many relationship can be used in few peculiar situations. This relation doesn't suit all the Scenarios.
a) Related Posts / Products
Consider a blog or shopping website, where we have post / product related to each other.
When the related Entity is matched via BelongsToMany
relationship, the association of one Post/Product as related to
the other post/product, on fetching the relatedPost or relatedProduct from the first Object will yield the second,
but the inverse is not true (ie, getting first post/product as related post/product from the second)
b) Friend list in social media
In Social Media, the concept of Users being friended to one another can be easily achieved using this relation (not followers & following, just mutual friends). Once a Users add another User as friends, we can attach the User and doesn't need to care about the attachment of reverse while using this relationship.
Note: The Concept of followers and following has to use the Laravel's
BelongsToMany
relation. This relation is for friends like in Facebook.
c) Messages in a Chat
The Message in a Chat application, where a message is directed from a User to another User. This relation lets you retrieve all the Users that have messaged a particular User.
Note: There may be possibility of duplicates in this case
API Reference
The trait HasBelongsToManySelfRelation
adds the method belongsToManySelf
to your Model.
/** * create the BelongsToManySelf relation on the same Model via a pivot table * * @param string $table Pivot table name * @param string $pivotKey1 Pivot table foreign key 1 * @param string $pivotKey2 Pivot table foreign key 2 * @param string|null $relatedKey Related key on the parent table * @param string|null $relation Relation name * @return BelongsToManySelf */ public function belongsToManySelf(string $table, string $pivotKey1, string $pivotKey2, $relatedKey = null, $relation = null)
The BelongsToManySelf
is a concrete/child/sub-class of the Eloquent BelongsToMany
class.
So, All the methods available on the BelongsToMany
is also available on this Relation.
Known Issues
The following Issues / Problems were found in this package or the underlying Database Engine.
- the
has
andwhereHas
constraint will not work in MySQL < v8.0.14
Tips
- To improve the performance of the relation, create two Pivot Table indexes such as
(pivot_key1, pivot_key2)
and(pivot_key2, pivot_key1)
Contributing
Contributions are always welcome!
Feel free to open Issues and submit Pull Requests