Skip to content

[BC Break] Drop support for the "dynamic" pointcut type#583

Merged
lisachenko merged 1 commit into
masterfrom
chore/drop-dynamic-pointcut-type
Jul 18, 2026
Merged

[BC Break] Drop support for the "dynamic" pointcut type#583
lisachenko merged 1 commit into
masterfrom
chore/drop-dynamic-pointcut-type

Conversation

@lisachenko

Copy link
Copy Markdown
Member

Summary

Removes the dynamic(...) pointcut type for 4.0.0. It was the only pointcut requiring runtime matching, and it forced extra machinery through the whole pointcut layer:

  • the Pointcut::KIND_DYNAMIC flag,
  • the runtime-wrapping DynamicInvocationMatcherInterceptor,
  • the $instanceOrScope/$arguments parameters threaded through Pointcut::matches() in every implementation.

The same behavior is achievable with a traditional execution() pointcut for the __call/__callStatic magic methods plus a method-name check inside the advice.

BC Break / Migration

Instead of:

#[Before('dynamic(public Demo\Example\DynamicMethodsDemo->save*(*))')]

use a traditional execution pointcut on the magic method and filter by the real method name (first invocation argument) inside the advice:

#[Before('execution(public Demo\Example\DynamicMethodsDemo->__call(*))')]
public function beforeMagicMethodExecution(MethodInvocation $invocation): void
{
    [$methodName, $args] = $invocation->getArguments();
    if (!str_starts_with($methodName, 'save')) {
        return;
    }
    // ...
}

(and execution(public Foo::__callStatic(*)) for the static counterpart). The DynamicMethodsAspect demo has been converted to this pattern as a live migration example, producing identical output. The BC break is documented in the CHANGELOG.

Changes

  • Deleted MagicMethodDynamicPointcut, DynamicInvocationMatcherInterceptor and their tests
  • Removed the dynamic lexer token and the dynamicExecutionPointcut grammar rule; regenerated the LALR parse table via the Dissect analyzer
  • Removed Pointcut::KIND_DYNAMIC and the $instanceOrScope/$arguments parameters of Pointcut::matches() — clean 2-arg signature across the interface and all 11 implementations; interface docblock now describes static matching only
  • GenericPointcutAdvisor::getAdvice() simplified to a plain getter
  • Converted the demo aspect + updated CHANGELOG and src/Aop/AGENTS.md

Unrelated names using "dynamic" in the instance-vs-static sense (DynamicMethodInvocation, isDynamic(), the dynamic-traits demo) are intentionally untouched.

Testing

  • vendor/bin/phpunit: all 2471 tests pass
  • vendor/bin/phpstan analyse --memory-limit=1G: no errors
  • Parser check: dynamic(...) now throws UnexpectedTokenException; all other pointcut syntaxes still parse
  • Demo run end-to-end (?showcase=dynamic-interceptor with cleared cache): saveById/find intercepted, load filtered out — identical observable behavior to the old dynamic() pointcut

🤖 Generated with Claude Code

@lisachenko lisachenko changed the title Drop support for the "dynamic" pointcut type [BC Break] Drop support for the "dynamic" pointcut type Jul 18, 2026
@lisachenko lisachenko added this to the 4.0.0 milestone Jul 18, 2026
The dynamic(...) pointcut was the only pointcut requiring runtime
matching, forcing extra machinery through the whole pointcut layer:
the KIND_DYNAMIC flag, the runtime-wrapping
DynamicInvocationMatcherInterceptor and the $instanceOrScope/$arguments
parameters threaded through Pointcut::matches() in every
implementation.

The same behavior is achievable with a traditional execution pointcut
for the __call/__callStatic magic methods plus a method-name check
inside the advice, as now shown by the updated DynamicMethodsAspect
demo.

* Remove MagicMethodDynamicPointcut and
  DynamicInvocationMatcherInterceptor
* Remove the "dynamic" lexer token and the dynamicExecutionPointcut
  grammar rule, regenerate the LALR parse table
* Remove Pointcut::KIND_DYNAMIC and the $instanceOrScope/$arguments
  parameters of Pointcut::matches() from the interface and all
  implementations
* Simplify GenericPointcutAdvisor::getAdvice() to a plain advice getter
* Convert the DynamicMethodsAspect demo to traditional execution
  pointcuts as a migration example
* Document the BC break in the CHANGELOG

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lisachenko
lisachenko force-pushed the chore/drop-dynamic-pointcut-type branch from e144291 to 053e0b6 Compare July 18, 2026 21:54
@lisachenko
lisachenko merged commit 9b71b06 into master Jul 18, 2026
5 checks passed
@lisachenko
lisachenko deleted the chore/drop-dynamic-pointcut-type branch July 18, 2026 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

1 participant