Skip to content

ngmy/Laravel.Aop

Repository files navigation

Laravel.Aop

Latest Stable Version Test Status Lint Status Code Coverage Total Downloads

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.