ngmy / laravel.aop
Laravel.Aop integrates Ray.Aop with Laravel.
Fund package maintenance!
ngmy
flattr.com/@ngmy
Requires
- php: ^8.1
- laravel/framework: ^9.0 || ^10.0 || ^11.0
- olvlvl/composer-attribute-collector: *
- ray/aop: ^2.10.1
- spatie/file-system-watcher: ^1.2
- symfony/finder: *
Requires (Dev)
- bamarni/composer-bin-plugin: ^1.8
- ergebnis/composer-normalize: ^2.42
- larastan/larastan: ^2.9
- mockery/mockery: ^1.6
- orchestra/testbench: ^7.0 || ^8.0 || ^9.0
- phpstan/extension-installer: ^1.3
README
Laravel.Aop integrates Ray.Aop with Laravel. It provides fast AOP by static weaving.
Installation
First, you should install Laravel.Aop via the Composer package manager:
composer require ngmy/laravel.aop
You will be asked if you trust the olvlvl/composer-attribute-collector
package, so you should press y
.
Next, you should configure the olvlvl/composer-attribute-collector
package.
Tip
Please see the composer-attribute-collector documentation
to learn how to configure the olvlvl/composer-attribute-collector
package.
Then, you should publish the Laravel.Aop configuration file using the vendor:publish
Artisan command. This command
will publish the aop.php
configuration file to your application's config
directory:
php artisan vendor:publish --provider="Ngmy\LaravelAop\ServiceProvider"
Usage
First, you should define the attribute.
For example, let's define the Transactional
attribute:
<?php declare(strict_types=1); namespace App\Attributes; #[\Attribute(\Attribute::TARGET_METHOD)] class Transactional {}
Next, you should define the interceptor.
For example, let's define the TransactionalInterceptor
interceptor:
<?php declare(strict_types=1); namespace App\Interceptors; use Illuminate\Support\Facades\DB; use Ray\Aop\MethodInterceptor; use Ray\Aop\MethodInvocation; class Transactional implements MethodInterceptor { public function invoke(MethodInvocation $invocation): mixed { return DB::transaction(static fn (): mixed => $invocation->proceed()); } }
Tip
Please see the Ray.Aop documentation to learn more about the interceptor.
Then, you should register the attribute and the interceptor in the intercept
configuration option of the
config/aop.php
configuration file.
For example, let's register the Transactional
attribute and the TransactionalInterceptor
interceptor:
use App\Attributes\Transactional; use App\Interceptors\TransactionalInterceptor; use Ngmy\LaravelAop\Collections\InterceptMap; 'intercept' => InterceptMap::default()->merge([ Transactional::class => [ TransactionalInterceptor::class, ], ])->toArray(),
Then, you should annotate the methods that you want to intercept with the attribute.
For example, let's annotate the createUser
method of the UserService
class with the Transactional
attribute:
<?php declare(strict_types=1); namespace App\Services; use App\Attributes\Transactional; use App\Models\User; class UserService { #[Transactional] public function createUser(string $name): void { User::create(['name' => $name]); } }
Finally, you should run the aop:compile
Artisan command to compile the AOP classes:
php artisan aop:compile
You must run the dump-autoload
Composer command before running the aop:compile
Artisan command.
By default, the aop:compile
Artisan command runs the dump-autoload
Composer command with the --no-scripts
option
internally before compiling the AOP classes.
If you want to run the dump-autoload
Composer command yourself, you should run the aop:compile
Artisan
command with the --no-dump-autoload
option:
composer dump-autoload php artisan aop:compile --no-dump-autoload
Warning
If you want to avoid overwriting the Composer autoload files, such as when optimizing the Composer autoload files in
a production environment, you should run the aop:compile
Artisan command with the --no-dump-autoload
option.
Important
After modifying the intercept
configuration option or the method attributes, you should recompile the AOP classes.
However, if you only modify the arguments of the method attributes, you do not need to recompile the AOP classes.
Now, the methods annotated with the attribute will be intercepted by the interceptor.
In this example, the createUser
method of the UserService
class will be intercepted by the
TransactionalInterceptor
and will be executed in a transaction.
Important
The methods annotated with the attribute are intercepted by the interceptor only when the class instance is dependency resolved from the service container. If the class instance is created directly, the methods are not intercepted.
Watcher
Laravel.Aop provides a watcher that watches the changes of the files and recompiles the AOP classes automatically.
This is useful when you are developing the application.
You may start the watcher using the aop:watch
Artisan command:
php artisan aop:watch
Note
The watcher runs the dump-autoload
Composer command with the --no-scripts
option internally before recompiling the
AOP classes.
You may configure the files to watch in the watcher.paths
configuration option of the config/aop.php
configuration
file.
Tips
Auto compilation
You may easily compile the AOP classes automatically after the dump-autoload
Composer command is run by adding the
@php artisan aop:compile --no-dump-autoload --ansi
script to the post-autoload-dump
event hook of the
composer.json
file:
{ "scripts": { "post-autoload-dump": [ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "@php artisan package:discover --ansi", "@php artisan aop:compile --no-dump-autoload --ansi" ] } }
Built-in attributes
Changelog
Please see the changelog.
License
Laravel.Aop is open-sourced software licensed under the MIT license.