refactor: replace the __aop__ prefix with OriginalTrait / OriginalAlias suffixes - #662
Merged
Merged
Conversation
…enerated code Generated proxies read much better when the marker trails the name instead of leading it, so every `__aop__`-prefixed symbol becomes an `Original`-suffixed one: * `AbstractMethodInvocation::TRAIT_ALIAS_PREFIX` becomes `TRAIT_ALIAS_SUFFIX` and the private trait aliases backing the original method bodies are now `doSomethingOriginal` instead of `__aop__doSomething` (the constructor alias is `__constructOriginal`, composed from the same constant). * `AspectContainer::AOP_PROXIED_SUFFIX` becomes `Original`, so the trait holding the original class body is `FooOriginal` instead of `Foo__AopProxied`. * The two remaining prefixed hooks drop it entirely: `InitializationAware` and `StaticInitializationAware` now declare `__initialization()` and `__staticInitialization()`. `Original` is a far more common substring than `__AopProxied`, so the places that sniffed for the marker are anchored to where it can actually appear: the cache-file marker is matched at the end of the file name, the proxied parent at the end of the class name, and a woven source is recognised by its `trait <Name>Original` declaration rather than by any mention of the word. Without this a class such as `OriginalRequest` would have had its proxy and its woven body written to the same cache file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CExUbcQgZTC1EmbWrTTTYS
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #662 +/- ##
=========================================
Coverage 96.00% 96.01%
- Complexity 1637 1638 +1
=========================================
Files 99 99
Lines 4510 4514 +4
=========================================
+ Hits 4330 4334 +4
Misses 180 180 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
`Original` served both roles, which read ambiguously wherever the two appear side by side in a trait-use block. Each marker now says what it is: * `AspectContainer::AOP_PROXIED_SUFFIX` is `OriginalTrait`, so the trait holding the original class body is `FooOriginalTrait`. * `AbstractMethodInvocation::TRAIT_ALIAS_SUFFIX` is `OriginalAlias`, so the private aliases backing the original method bodies are `fooBarOriginalAlias` (and `__constructOriginalAlias` for the constructor). The `__initialization()` / `__staticInitialization()` hooks are unchanged, as are the anchored marker checks — both markers stay recognisable only where they can actually occur. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CExUbcQgZTC1EmbWrTTTYS
__aop__ prefix with an Original suffix in generated code__aop__ prefix with OriginalTrait / OriginalAlias suffixes
lisachenko
marked this pull request as ready for review
September 4, 2026 21:03
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
__aop__fooBarreads badly in generated code. Moving the marker to the end is much easier on the eye, and the same applies to the__AopProxiedtrait suffix. The two markers get distinct names so a trait-use block says which is which.What changed
AspectContainer::AOP_PROXIED_SUFFIX='__AopProxied'AspectContainer::AOP_PROXIED_SUFFIX='OriginalTrait'trait Foo__AopProxiedtrait FooOriginalTraitAbstractMethodInvocation::TRAIT_ALIAS_PREFIX='__aop__'AbstractMethodInvocation::TRAIT_ALIAS_SUFFIX='OriginalAlias'$this->__aop__doSomething(...)$this->doSomethingOriginalAlias(...)$this->__aop____construct(...)$this->__constructOriginalAlias(...)InitializationAware::__aop__initialization()InitializationAware::__initialization()StaticInitializationAware::__aop__staticInitialization()StaticInitializationAware::__staticInitialization()The constructor alias is composed from
TRAIT_ALIAS_SUFFIXinstead of being spelled out, so there is a single source of truth for it.A generated proxy now looks like:
Anchoring the marker checks
The old
__AopProxiedwas collision-proof, so the places that recognised it could get away with a loosestr_contains(). AnOriginal…marker is ordinary English and can appear in real class names, so each check is now anchored to where the marker can actually occur:SourceTransformingLoader::saveToCache()— the cache file name is matched withstr_ends_with(), and a woven source is recognised by itstrait <Name>OriginalTraitdeclaration rather than by any mention of the word. Without this, a class such asOriginalTraitRegistrywould have had its generated proxy and its woven body written to the same cache file, silently clobbering the proxy.MagicConstantTransformer::resolveFileName()— only a trailingOriginalTrait.phpis stripped, soOriginalTraitRegistry.phpkeeps its name.DebugWeavingCommand— skips only files actually ending inOriginalTrait.php.AdviceMatcher— the proxied parent is matched withstr_ends_with()on the class name.MetadataLoadInterceptorwas already anchored with/.+(<suffix>)$/and is unchanged.Tests
Four new tests cover the anchoring:
SourceTransformingLoaderTest::testWovenBodyTraitIsCachedUnderTheProxiedSuffix()SourceTransformingLoaderTest::testTransformedSourceMerelyMentioningTheSuffixKeepsItsCacheFileName()MagicConstantTransformerTest::testTransformerDropsProxiedSuffixFromWovenBodyFileName()MagicConstantTransformerTest::testTransformerKeepsFileNameThatOnlyContainsProxiedSuffix()All proxy/weaving fixtures under
tests/Instrument/Transformer/_files/were regenerated with the new names, and the docs (README.md,CHANGELOG.md,docs/php85-limitations.md, theAGENTS.mdfiles) were updated to match.Verified locally:
php-cs-fixer checkclean,phpstan(level 10) clean,phpunit2803 tests with only the 32 failures that already fail on the base commit in this container (the fixture-project functional tests, which shell out tobin/console cache:warmup:aopand fail there on pointcut parsing before and after this change — they pass in CI).BC
A
[BC BREAK]entry was added to the unreleased 4.0.0 changelog:TRAIT_ALIAS_PREFIXis gone,AOP_PROXIED_SUFFIXhas a new value, the two*Awareinterface methods are renamed, and caches generated by an earlier 4.0 development version must be regenerated.🤖 Generated with Claude Code
https://claude.ai/code/session_01CExUbcQgZTC1EmbWrTTTYS