imanghafoori / eloquent-relativity
A way to truly decouple eloquent models.
Installs: 24 958
Dependents: 0
Suggesters: 1
Security: 0
Stars: 151
Watchers: 4
Forks: 14
Open Issues: 1
Requires
- php: ^7.1.3|7.2.*|7.3.*|7.4.*|8.0.*|8.1.*|8.2.*|8.3.*
- laravel/framework: ~5.1|6.*|7.*|8.*|9.*|10.*|11.*
Requires (Dev)
- mockery/mockery: *
- orchestra/testbench: ~3.0
Suggests
- imanghafoori/laravel-decorator: Allows you to easily apply the decorator pattern in a laravel app.
- imanghafoori/laravel-masterpass: You can easily set a master password without code change.
- imanghafoori/laravel-smart-facades: Automatic method injection when calling a method with Facades
- imanghafoori/laravel-widgetize: Gives you a better structure and caching opportunity for your web pages.
README
This allows you to decouple your eloquent models from one another, by defining relations dynamically at run-time.
- Note that this package is NOT needed in laravel 7.x or above.
Read more: https://laravel.com/docs/7.x/eloquent-relationships#dynamic-relationships
Compatibility :
Laravel version 5.5 and above including version 6
▶️ A problem which stops true modularity :
Let's face it, imagine you have a modular blog application.
Then, you want to add a commenting
feature to it, so that users can comment on your articles.
In a modular structure, you have 2 modules (user
module and blog
module) and you will add a new module for comments
▶️ let's analyze dependencies and couplings :
Here the blog
module "knows" and "depends" upon the user
module.
But the user
module should not know or care about the blog
module. The blog
is a plug-in
on the top of the user
module.
Now we want to add a comment
module, on the top of user
and blog
module.
▶️ The Right way :
In a truely modular system when you add the comments
, you should NOT go and touch the code within the users
or blog
module.
(Remember the open-closed
principle in SOLID
?!)
Imagine you are in a team and each member is working on a seperate module.
Blog
module is not yours. your team mate is responsible for it and is allowed to code on it.
But when you want to start to define the eloquent relations between Comment
and User
and Article
models, you immediately realize that you have to put code on the eloquent models of other modules to define the inverse of the relationships. Crap !
Look How everything is pointing inward.
If you look at the User
folder you will have absolutely no footprint of Comment or Article.
We have to touch the code of both Blog
and User
module when add a new comment
module.
For example : You have to open User.php
and define the
public function comments() { return $this->hasMany(Comment::class); }
and this is a no no, because it makes an arrow from inside to outside.
So what to do ?!
How can Comment
be introduced to the system without modifying the other modules ?! (@_@)
▶️ Install: (the most painful step)
composer require imanghafoori/eloquent-relativity (and take a coffee...)
Now the installtion finished, you first have to make your models "relative" !!!
By using the Imanghafoori\Relativity\DynamicRelations
traits on your eloquent models.
So the User
, Article
, Comment
will have to have this trait one them.
Now comes the sweet part :
within the CommentsServiceProvider.php
class CommentsServiceProvider { public function register () { User::has_many('comments', Comment::class); // instead of defining method on the User class. Article::has_many('comments', Comment::class); Comment::belongs_to('author', User::class); // inverse of relations Comment::belongs_to('article', Article::class); } }
Now you can do these queries :
User::find(1)->comments; or User::find(1)->comments()->count();
So instead of going to User
model and define a method there...
public function comments() { return $this->hasMany(Comment::class); }
You have defined the method remotely from your new module at run-time:
User::has_many('comments', Comment::class);
Here is a list of supported relations :
- has_many
- has_one
- belongs_to
- belongs_to_many
- morph_to_many
- morph_many
- morph_one
- morph_to
- morphed_by_many
- has_many_through
They accept the same paramters as the eloquent equivalent counter part. except the first argument should be relation name.
▶️ Extra features :
sometimes you need to call extra methods on the relations.
User::has_many('comments', Comment::class)->orderBy('id', 'asc');
All the methods are available to you.
- Enforce eager-loading
On reqular eloquent models you may define the
User extends Model { protected $with = ['comments']; }
instead you can :
User::forceEagerLoading('comments');
remember this should be in the boot
method of your Service Provider not the register
method.
⭐ Your Stars Make Us Do More ⭐
As always if you found this package useful and you want to encourage us to maintain and work on it, Please press the star button to declare your willing.
▶️ More from the author:
Laravel Terminator
💎 A minimal yet powerful package to give you opportunity to refactor your controllers.
Laravel Widgetize
💎 A minimal yet powerful package to give a better structure and caching opportunity for your laravel apps.
Laravel Master Pass
💎 A simple package that lets you easily impersonate your users.
Laravel HeyMan
💎 It allows to write exressive and defensive code which is decoupled from the rest of your app.
🍌 Reward me a banana 🍌
so that I will have energy to start the next package for you.
Dodge Coin: DJEZr6GJ4Vx37LGF3zSng711AFZzmJTouN
LiteCoin: ltc1q82gnjkend684c5hvprg95fnja0ktjdfrhcu4c4
BitCoin: bc1q53dys3jkv0h4vhl88yqhqzyujvk35x8wad7uf9
Ripple: rJwrb2v1TR6rAHRWwcYvNZxjDN2bYpYXhZ
Etherium: 0xa4898246820bbC8f677A97C2B73e6DBB9510151e
Life is like riding a bicycle. To keep your balance you must keep moving.
"Albert Einstein"