juampi92 / phpstan-eloquent-bounded-context
PHPStan rules that make sure your models are only being mutated from within its Domain.
Installs: 3
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Type:phpstan-extension
Requires
- php: ^7.4|^8.0|^8.1
- ext-json: *
- illuminate/database: ^7.0|^8.40|^9.0
- illuminate/support: ^7.0|^8.0|^9.0
- phpstan/phpstan: ^1.0
- symfony/yaml: ^5.0|^6.0
Requires (Dev)
- phpunit/phpunit: ^9.4
README
A set of PHPStan rules to make sure your models are only being mutated from within their Domains.
Description
These rules will detect when your Eloquent Model is being mutated outside of its Domain. The moment the Model leaves the Domain namespace, it becomes read-only.
Let's assume the following structure:
📁 app
├─ 📁 Http
│ └─ 📁 Controllers
│ └─ 📃 PostController.php
└─ 📁 Domains
└─ 📁 Posts
└─ 📁 Actions
└─ 📃 CreatePostAction.php
└─ 📁 Models
└─ 📃 Post.php
└─ 📃 Comment.php
If app/Http/Controllers/PostController.php
has the following method:
public function store(Request $request) { $post = new Post($request->validated()); $post->save(); }
PHPStan will fail saying:
---------------------------------------------------------------------------
app/Http/Controllers/PostController.php
---------------------------------------------------------------------------
Calling 'save' on 'App\Models\Post' outside of its Domain is not allowed.
---------------------------------------------------------------------------
To fix this error, instead of calling
save
inside the Controller directly, create an Action inside the Post domain (or a PostService class) and use that class to create and persist the model.
This package will also detect:
- Model attribute mutations like:
$post->title = 'My title';
, - Methods persist the data in the database, like
save
,update
,delete
, etc, - Static methods that persist the data, like
::create()
,::updateOrCreate()
, etc.
Installation
To use this extension, require it in Composer:
composer require --dev juampi92/phpstan-eloquent-bounded-context
If you also install phpstan/extension-installer then you're all set!
Manual installation
If you don't want to use phpstan/extension-installer
, include extension.neon in your project's PHPStan config:
includes: - vendor/juampi92/phpstan-eloquent-bounded-context/extension.neon
Configuration
No configuration
If your models are placed inside their Domain folder, the package will know they are not using Laravel's default folders, and assume the domain is App/Domains/Posts
. Any class inside that domain is allowed to mutate an eloquent model.
📁 app
├─ 📁 Domains
│ └─ 📁 Posts
│ | └─ 📁 Actions
│ | └─ 📁 Repositories
│ | └─ 📁 Models ✅
│ | └─ 📃 Post.php
│ | └─ 📃 Comment.php
│ └─ 📁 Users
│ └─ ...
└── ...
Manual configuration
If your models are placed inside App\Models
, then you will have to configure your domain manually.
To do so, you must first create a configuration file that holds the information about your models and domains:
domains: - namespace: App\Domain\Posts models: - App\Models\Post - App\Models\Comment - namespace: App\Domain\Users models: - App\Models\User - App\Models\UserProfile
And after you must reference this file inside the phpstan.neon.dist
config:
parameters: eloquentBoundedContextConfigFiles: - app/Domain/domains.yml
Configuring ignored namespaces
You might want to ignore some namespaces and allow Models to be modified there.
parameters: eloquentBoundedContextConfigFiles: - app/Domain/domains.yml eloquentBoundedContextIgnoredNamespaces: - Database\Factories - Tests
Contribute
Features to do:
- Ignore no-configuration resolution when a config is used.
- Propose /** @mutates */ tag or #Attribute to prohibit these methods being called outside of the domain.
Testing
./vendor/bin/phpunit
Credits
License
The MIT License (MIT). Please see License File for more information.