4.0.0 (unreleased)
- [BC BREAK] Requires PHP 8.4+
- [BC BREAK] Proxy engine switched from inheritance-based to trait-based: the original class body is converted to a PHP trait (
Foo__AopProxied) and the proxy class uses it viausewith private method aliases instead of extending the renamed class. This removes the__AopProxiedparent from the inheritance chain. - [BC BREAK] All invocation class constructors (
DynamicTraitAliasMethodInvocation,StaticTraitAliasMethodInvocation,ReflectionFunctionInvocation) now require aClosure $closureToCallparameter (non-nullable). Generated proxy code always passes a first-class callable:$this->__aop__method(...)for own instance methods,self::__aop__method(...)for own static methods,parent::method(...)for inherited methods, and\functionName(...)for functions. - [Feature] Private method interception — both dynamic (
private function foo()) and static (private static function bar()) private methods can now be intercepted by aspects. This was impossible with the old extend-based engine because PHP does not allow overriding private methods in subclasses. - [Feature] PHP 8.5+ first-class callable default values — proxy generation for method parameters and constructor-promoted properties now supports
Closuredefault values expressed via first-class callable syntax (e.g.,function foo($cb = strlen(...))). The raw AST expression node is preserved through the proxy-generation pipeline so the generated source code reproduces the original FCC default verbatim. - [Feature] PHP 8.1+ enum interception — instance and static methods on both unit (pure) and backed enums can now be intercepted by aspects. The enum body is extracted into a trait (
Foo__AopProxied); a proxy enum re-declares the cases and dispatches intercepted methods via per-methodstatic $__joinPointcaching. Built-in enum methods (cases,from,tryFrom) and initialization joinpoints are never woven. - [Feature]
self::in proxied classes now resolves to the proxy class naturally (via PHP trait semantics), removing the need forSelfValueTransformer. - [Feature] First-class callable syntax — generated proxy code and invocation constructors use PHP 8.1+ first-class callable syntax (
$this->__aop__method(...),parent::method(...),\func(...)) to reference original method and function bodies, eliminating the need forClosure::bindat construction time. - [BC BREAK] Removed
Features::PARAMETER_WIDENINGand the parameter-widening code path in the proxy generators. The feature was a PHP 7.0/7.1 compatibility aid (parameter type widening, wiki.php.net/rfc/parameter-no-type-variance) that has been a no-op concern since the PHP 7.2 baseline: generated proxies always keep the original parameter types. Remove the flag fromAspectKernel::configureAop()options if you passed it. - [BC BREAK] Removed DeclareError support, including the
DeclareErrorattribute,DeclareErrorInterceptor, andPointcutBuilder::declareError(). UseBeforeorAroundinterceptors to emit user warnings or throw exceptions instead. - [BC BREAK] Removed support for the "dynamic" pointcut (
dynamic(public Foo->method*(*))), includingMagicMethodDynamicPointcut,DynamicInvocationMatcherInterceptor, thePointcut::KIND_DYNAMICconstant and the$instanceOrScope/$argumentsparameters ofPointcut::matches(). Use a traditional execution pointcut for the magic methods instead, e.g.execution(public Foo->__call(*))orexecution(public Foo::__callStatic(*)), and check the invoked method name from$invocation->getArguments()[0]inside the advice. - [Removed]
SelfValueTransformerandSelfValueVisitor— no longer needed with the trait-based engine. - [Performance] Direct static joinpoint initialization — leveraging PHP 8.3+ support for dynamic expressions in static variable initializers, all generated proxy method bodies now initialize their static joinpoint variables directly.
- [Performance] [BC BREAK] Truly lazy container services —
AspectContainer::addLazyService()stores a factory instead of building a PHP 8.4 lazy proxy, so registering the built-in services no longer reflects/autoloads them on every request; a service is constructed on first retrieval. Code relying on lazy-proxy instances being available from boot must usegetService()instead. - [Performance] [BC BREAK] Lazy aspect registration —
AspectContainer::registerAspect()accepts an aspect class-name plus an optional factory closure (required for aspects with constructor dependencies); such aspects are constructed on first use instead of duringconfigureAop(). The signature widened toregisterAspect(Aspect|string $aspectOrClassName, ?Closure $aspectFactory = null); instance registration behaves as before. - [Performance] [BC BREAK] Class-keyed runtime cache map, integrated into composer — the weaver records the FQCN of every discovered class into the cache metadata, and the runtime cache file
_include.cacheholds a woven-class => cached-file map plus a skip set of known untransformed classes. At production boot the class map is handed to composer viaClassLoader::addClassMap(), so woven classes resolve natively to their cached files (composer consults the class map before PSR-4) with no per-classrealpath(); untransformed classes are served untouched._transformation.cachekeeps the full build metadata and is loaded lazily, only on the cache-miss/weaving paths. Cache format bump: a pre-4.0 cache directory carries no class names and is treated as stale — everything re-weaves once (or runcache:warmup:aopat deploy). New accessors:CachePathManager::queryClassMap(),querySkippedClasses(),registerClassForResource(). - [Performance] [BC BREAK]
PREBUILT_CACHEnow really trusts the cache — withFeatures::PREBUILT_CACHEenabled, an existing cache record is used without any freshness checks: cache directory existence/writability probes, sourcefilemtimecomparisons, tracked-resource checks and advisor cache freshness are all skipped (previously the flag only skipped one writability check). Build the cache at deploy time (bin/aspect cache:warmup:aop); staleness is the deployer's responsibility. A corrupt advisor cache file falls back to the direct loader without writing (read-only file systems stay safe). - [Performance] [BC BREAK] Lazy transformation pipeline — every source transformer is a deferred container service, tagged by the
SourceTransformerinterface and assembled in registration order; the stream filter and the transformers are only registered/constructed on the first cache miss (SourceTransformingLoader::ensureRegistered()), never on a warm-cache request. The protectedAspectKernel::registerTransformers()hook (returning transformer instances, used e.g. by AspectMock to swap in its own weaver) is replaced byAspectKernel::registerTransformerServices(AspectContainer $container), which registers deferred container definitions: override it to replace, omit, reorder or extend the built-in transformers, or simplyaddLazyService()an extraSourceTransformerservice fromconfigureAop()to append one. - [Performance] [BC BREAK] Caching moved into the core:
CachingTransformerremoved — the cache decision now lives directly inSourceTransformingLoader::filter(): a usable cache record makes the filter emit the cached file content as-is, without parsing the source, constructing a single transformer or buildingStreamMetaData; only a real miss parses and runs the transformer chain, then persists the result. This also removes the old cached-branch double work of re-parsing the cached file to rebuild the token stream, so the warm-cache fast path now applies in debug mode too (freshness checks preserved).SourceTransformingLoader::transformCode()returns the overallTransformerResultEnumandaddTransformer()is gone — register transformers as container services instead (AspectKernel::registerTransformerServices()).
3.0.0 (December 4, 2019)
- [BC BREAK] Switched to the PHP7.2 and upper, strict types, return type hints and new syntax
- [BC BREAK] Removed the Joinpoint->getThis() method, as not all joinpoints belongs to classes (eg. FunctionInvocation)
- [BC BREAK] Removed the Joinpoint->getStaticPart() method as it can return anything, better to use explicit methods
- [Feature] Introduced the new ClassJoinpoint interface with getScope(), getThis() and isDynamic() methods
- [Feature] Implemented parameter widening feature for generated code #380
- [Feature] AnnotatedReflectionProperty provides simple access to property annotations #388 by @TheCelavi
- [Feature] Switched to the
zendframework/zend-codepackage to generate code for proxies - [Feature] Add private properties interception #412
2.0.0 (May 14, 2016)
- Dropped support for PHP<5.6, clean all old code
- [BC BREAK] Removed ability to rebind closures, because of PHP restrictions, see #247
- [BC BREAK] Removed getDefaultFeatures() method from the AspectKernel, no need in it since PHP5.6
- Migrated from the
Andrewswille/Token-Reflectionto thegoaop/parser-reflectionlibrary for PHP5.6 and PHP7.0 support - Added support for PHP5.6 and 7.0 features: variadic methods, scalar type hints, return type hints
- [Feature] Command-line tools for debugging aspects and advisors
1.0.0 (Feb 13, 2016)
- Dropped support for PHP<5.5, clean all old code
- Tagged public methods and interfaces with @api tag. No more changes for them in future.
- Refactored core code to use general interceptors for everything instead of separate classes
- New static initialization pointcut to intercept the moment of class loading
- New feature to intercept object initializations, requires INTERCEPT_INITIALIZATIONS to be enabled
- [BC BREAK] remove class() pointcut from the grammar #189
- [BC BREAK] make within() and @within() match all joinpoints #189
- [BC BREAK] drop @annotation syntax. Add @execution pointcut
- Pointcuts can be build now directly from closures via
PointcutBuilderclass - Do not create files in the cache, if no aspects were applied to them, respects
includePathoption now FilterInjectoris now disabled by default, this job for composer integration now- Automatic opcache invalidation for cache state file
0.6.1 (Jul 5, 2015)
- Minor patch to fix a bug with overwriting files
0.6.0 (Feb 1, 2015)
- Interceptor for magic methods via "dynamic" pointcut. This feature also gives an access for dynamic pointcuts with different checks and conditions.
- PSR-4 standard for the codebase, thanks to @cordoval
- Added a support for splat (...) operator for more efficient advice invocation (requires PHP5.6)
- New feature system. All tunings of kernel are configured with feature-set. This breaks old configuration option
interceptFunctions=>trueuse'features' => $defaultFeatures | Features::INTERCEPT_FUNCTIONSnow - Proxy can generate more effective invocation call with
static::classfor PHP>=5.5 - Bug-fixes with empty cache path and PSR4 code, thanks to @andy-shea
- Make pointcut grammar class compatible with PHP7.0
0.5.0 (May 24, 2014)
- Proxies are now stored in the separate files to allow more transparent debugging
- Cache warmer command added
- Extended pointcut syntax for or-ed methods: ClassName->method1|method2(*)
- Access to the annotations for method from MethodInvocation
- Support for read-only file systems (phar, GAE, etc)
- Direct access to advisors (no more serialize/unserialize)
- New @within pointcut to match classes by annotation class
- Nice demo GUI
- Deprecate the usage of submodules for framework
- Inheritance support during class-loading and weaving
- List of small fixes and imrovements
0.4.1 (Aug 27, 2013)
- Better parsing of complex "include" expressions for Yii (by @zvirusz)
- Support for dynamic arguments count for methods by checking for func_get_args() inside method body
- Fixed a bug with autoloaders reodering (by @zvirusz)
0.4.0 (Aug 04, 2013)
- Privileged advices for aspect: allows to access private and protected properties and methods of objects inside advice
- Full integration with composer that allows for easy configuration and workflow with AOP
- Fix some bugs with caching on Windows
- "True" pointcut references that gives the ability to compose a complex pointcut from a simple pointcuts.
- Pointcut now accept "$this" in references to point to the current aspect instance (Allows for abstract aspects and abstract pointcuts)
- AspectContainer interface was extracted. This gives the way to integrate with another DIC. Look at Warlock framework.
- Intercepting system functions such as
fopen(),file_get_contents(), etc - Annotation property pointcut was added
- Ability to declare multiple interfaces and/or traits with single
DeclareParentintroduction - DeclareError interceptor was added. This can be used for generating an runtime error for methods that should not be executed in such a way.
0.3.0 (May 27, 2013)
- Support for dynamic pointcuts: pointcut that match a specific point in the code, if it is under the control flow (look at AspectJ cflow and cflowbelow)
- Performance optimizations
- Case-sensitive matching for pointcuts
- Primitive pointcuts (&&, ||, !)
- [BC break] Changes in the kernel configuration (look at the demo for appLoader and autoloadPaths)
- Fix a logic bug for a composite pointcuts
0.2.0 (Mar 15, 2013)
- Intercepting methods in traits
- Pointcut parser/grammar
- Huge pointcuts refactoring, cleaning
- Lazy loading services, pointcuts
0.1.1 (Jan 20, 2013)
- Introduction advice support
- Fix bug with composer autoloader prepending
- Fix doctrine/common dependency: >=2.0.0, <2.4.0
0.1.0 (Jan 08, 2013)
- Initial release of library