ytake / laravel-aspect
Aspect Oriented Programming library for laravel framework, and lumen
Fund package maintenance!
ytake
Installs: 103 997
Dependents: 2
Suggesters: 0
Security: 0
Stars: 130
Watchers: 14
Forks: 19
Open Issues: 8
Requires
- php: ^8.1
- doctrine/annotations: ^1.10
- illuminate/bus: ^10.0
- illuminate/cache: ^10.0
- illuminate/config: ^10.0
- illuminate/console: ^10.0
- illuminate/contracts: ^10.0
- illuminate/database: ^10.0
- illuminate/events: ^10.0
- illuminate/filesystem: ^10.0
- illuminate/log: ^10.0
- illuminate/queue: ^10.0
- illuminate/support: ^10.0
- nikic/php-parser: ^4.2
- psr/log: ^1.0.1 || ^2.0 || ^3.0
- ray/aop: ^2.9
Requires (Dev)
- illuminate/encryption: ^10.0
- mockery/mockery: *
- pdepend/pdepend: ^2.2.4
- phploc/phploc: *
- phpmd/phpmd: @stable
- phpunit/phpunit: ^10.5.13
- sebastian/phpcpd: *
- squizlabs/php_codesniffer: ~2.7
- symfony/console: ^6.0.9
- symfony/framework-bundle: ^6.0
- vlucas/phpdotenv: ^5.2
- dev-main
- 9.0.0
- 8.0.0
- 7.0.0
- 6.0.1
- 6.0.0
- 5.0.2
- 5.0.1
- 5.0.0
- 4.0.0
- 3.1.0
- 3.0.0
- 2.1.1
- 2.1.0
- 2.0.2
- 2.0.1
- 2.0.0
- 1.7.0
- 1.6.0
- 1.5.4
- 1.5.3
- 1.5.2
- 1.5.1
- 1.5.0
- 1.4.1
- 1.4.0
- 1.3.3
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.3
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.0
- 0.2.2
- 0.2.1
- 0.2.0
- 0.1.7
- 0.1.6
- 0.1.5
- 0.1.4
- 0.1.3
- 0.1.2
- 0.1.1
- 0.1
- dev-feature/patch-for-laravel9
- dev-feature/separate-annotations
- dev-master-laravel7.0
- dev-master-laravel6.0
- dev-master-laravel5.8
- dev-master-laravel5.5
- dev-master-laravel5.6
- dev-master-laravel5-legacy
This package is auto-updated.
Last update: 2024-10-15 04:34:49 UTC
README
aspect-oriented programming Package for laravel framework
This library is heavily inspired by the jcabi/jcabi-aspects.
usage
Laravel version Compatibility
install
$ composer require ytake/laravel-aspect
Supported Auto-Discovery(^Laravel5.5)
for Laravel9
Laravel-Aspect Supported Laravel5.6
"require": { "php": ">=7.1.3", "laravel/framework": "^5.7", "ytake/laravel-aspect": "^8.0.0" },
added serviceProvider
'providers' => [ // added AspectServiceProvider \Ytake\LaravelAspect\AspectServiceProvider::class, // added Artisan Command \Ytake\LaravelAspect\ConsoleServiceProvider::class, ]
for Lumen
Add App\Providers\LumenAspectServiceProvider to your bootstrap/app.php file.
$app->register(\App\Providers\LumenAspectServiceProvider::class); $app->register(\Ytake\LaravelAspect\ConsoleServiceProvider::class);
publish aspect module class
$ php artisan ytake:aspect-module-publish
more command options [--help]
publish configure
- basic
$ php artisan vendor:publish
- use tag option
$ php artisan vendor:publish --tag=aspect
- use provider
$ php artisan vendor:publish --provider="Ytake\LaravelAspect\AspectServiceProvider"
register aspect module
config/ytake-laravel-aop.php
'modules' => [ // append modules // \App\Modules\CacheableModule::class, ],
use classes property
namespace App\Modules; use Ytake\LaravelAspect\Modules\CacheableModule as PackageCacheableModule; /** * Class CacheableModule */ class CacheableModule extends PackageCacheableModule { /** @var array */ protected $classes = [ \YourApplication\Services\SampleService::class ]; }
example
namespace YourApplication\Services; use Ytake\LaravelAspect\Annotation\Cacheable; class SampleService { /** * @Cacheable(cacheName="testing1",key={"#id"}) */ public function action($id) { return $this; } }
notice
- Must use a service container
- Classes must be non-final
- Methods must be public
for Lumen
override Ytake\LaravelAspect\AspectServiceProvider
use Ytake\LaravelAspect\AspectManager; use Ytake\LaravelAspect\AnnotationManager; use Ytake\LaravelAspect\AspectServiceProvider as AspectProvider; /** * Class AspectServiceProvider */ final class AspectServiceProvider extends AspectProvider { /** * {@inheritdoc} */ public function register() { $this->app->configure('ytake-laravel-aop'); $this->app->singleton('aspect.manager', function ($app) { $annotationConfiguration = new AnnotationConfiguration( $app['config']->get('ytake-laravel-aop.annotation') ); $annotationConfiguration->ignoredAnnotations(); // register annotation return new AspectManager($app); }); } }
bootstrap/app.php
$app->register(App\Providers\AspectServiceProvider::class); if ($app->runningInConsole()) { $app->register(Ytake\LaravelAspect\ConsoleServiceProvider::class); }
Cache Clear Command
$ php artisan ytake:aspect-clear-cache
PreCompile Command
$ php artisan ytake:aspect-compile
Annotations
@Transactional
for database transaction(illuminate/database)
you must use the TransactionalModule
- option
use Ytake\LaravelAspect\Annotation\Transactional; /** * @Transactional("master") */ public function save(array $params) { return $this->eloquent->save($params); }
Multiple Transaction
use Ytake\LaravelAspect\Annotation\Transactional; /** * @Transactional({"master", "second_master"}) */ public function save(array $params) { $this->eloquent->save($params); $this->query->save($params); }
@Cacheable
for cache(illuminate/cache)
you must use the CacheableModule
- option
use Ytake\LaravelAspect\Annotation\Cacheable; /** * @Cacheable(cacheName="testing1",key={"#id","#value"}) * @param $id * @param $value * @return mixed */ public function namedMultipleKey($id, $value) { return $id; }
@CacheEvict
for cache(illuminate/cache) / remove cache
you must use the CacheEvictModule
- option
use Ytake\LaravelAspect\Annotation\CacheEvict; /** * @CacheEvict(cacheName="testing",tags={"testing1"},allEntries=true) * @return null */ public function removeCache() { return null; }
@CachePut
for cache(illuminate/cache) / cache put
you must use the CachePutModule
- option
use Ytake\LaravelAspect\Annotation\CachePut; /** * @CachePut(cacheName={"testing1"},tags="testing1") */ public function throwExceptionCache() { return 'testing'; }
@Loggable / @LogExceptions
for logger(illuminate/log, monolog)
you must use the LoggableModule / LogExceptionsModule
- option
use Ytake\LaravelAspect\Annotation\Loggable; class AspectLoggable { /** * @Loggable(driver="stack") * @param null $id * @return null */ public function normalLog($id = null) { return $id; } }
sample)
[2015-12-23 08:15:30] testing.INFO: Loggable:__Test\AspectLoggable.normalLog {"args":{"id":1},"result":1,"time":0.000259876251221}
About @LogExceptions
Also, take a look at @Loggable. This annotation does the same, but also logs non-exceptional situations.
use Ytake\LaravelAspect\Annotation\LogExceptions; class AspectLoggable { /** * @LogExceptions(driver="custom") * @param null $id * @return null */ public function dispatchLogExceptions() { return $this->__toString(); } }
About @QueryLog
for database query logger(illuminate/log, monolog, illuminate/database)
use Ytake\LaravelAspect\Annotation\QueryLog; use Illuminate\Database\ConnectionResolverInterface; /** * Class AspectQueryLog */ class AspectQueryLog { /** @var ConnectionResolverInterface */ protected $db; /** * @param ConnectionResolverInterface $db */ public function __construct(ConnectionResolverInterface $db) { $this->db = $db; } /** * @QueryLog(driver="custom") */ public function multipleDatabaseAppendRecord() { $this->db->connection()->statement('CREATE TABLE tests (test varchar(255) NOT NULL)'); $this->db->connection('testing_second')->statement('CREATE TABLE tests (test varchar(255) NOT NULL)'); $this->db->connection()->table("tests")->insert(['test' => 'testing']); $this->db->connection('testing_second')->table("tests")->insert(['test' => 'testing second']); } }
testing.INFO: QueryLog:AspectQueryLog.multipleDatabaseAppendRecord {"queries":[{"query":"CREATE TABLE tests (test varchar(255) NOT NULL)","bindings":[],"time":0.58,"connectionName":"testing"},{"query":"CREATE TABLE tests (test varchar(255) NOT NULL)","bindings":[],"time":0.31,"connectionName":"testing_second"} ...
@RetryOnFailure
Retry the method in case of exception.
you must use the RetryOnFailureModule.
- option
use Ytake\LaravelAspect\Annotation\RetryOnFailure; class ExampleRetryOnFailure { /** @var int */ public $counter = 0; /** * @RetryOnFailure( * types={ * LogicException::class, * }, * attempts=3, * ignore=Exception::class * ) */ public function ignoreException() { $this->counter += 1; throw new \Exception; } }
@MessageDriven
Annotation for a Message Queue(illuminate/queue. illuminate/bus).
you must use the MessageDrivenModule.
- option
use Ytake\LaravelAspect\Annotation\EagerQueue; use Ytake\LaravelAspect\Annotation\LazyQueue; use Ytake\LaravelAspect\Annotation\Loggable; use Ytake\LaravelAspect\Annotation\MessageDriven; /** * Class AspectMessageDriven */ class AspectMessageDriven { /** * @Loggable * @MessageDriven( * @LazyQueue(3), * onQueue="message" * ) * @return void */ public function exec($param) { echo $param; } /** * @MessageDriven( * @EagerQueue * ) * @param string $message */ public function eagerExec($message) { $this->logWith($message); } /** * @Loggable(name="Queued") * @param string $message * * @return string */ public function logWith($message) { return "Hello $message"; } }
LazyQueue
Handle Class Ytake\LaravelAspect\Queue\LazyMessage
EagerQueue
Handle Class Ytake\LaravelAspect\Queue\EagerMessage
Ignore Annotations
use config/ytake-laravel-aspect.php file
default: LaravelCollective/annotations
'annotation' => [ 'ignores' => [ // global Ignored Annotations 'Hears', 'Get', 'Post', 'Put', 'Patch', 'Options', 'Delete', 'Any', 'Middleware', 'Resource', 'Controller' ], ],
Append Custom Annotations
'annotation' => [ 'ignores' => [ // global Ignored Annotations 'Hears', 'Get', 'Post', 'Put', 'Patch', 'Options', 'Delete', 'Any', 'Middleware', 'Resource', 'Controller' ], 'custom' => [ \Acme\Annotations\Transactional::class // etc... ] ],
for testing
use none driver
<env name="ASPECT_DRIVER" value="none"/>