phpbotgram

Scene
in package

AbstractYes

Abstract base for all scene classes in the Scene subsystem.

A scene encapsulates a logical conversation step — the user is "in" a scene while the FSM state matches the scene's declared state. Subclasses declare their FSM state via the #[SceneState] class attribute and attach handlers via the #[On*] method attributes (OnMessage, OnCallbackQuery, etc. in Scene/Attribute/).

Mirrors Scene (aiogram/fsm/scene.py:297-441).

Usage

#[SceneState('greeting')] final class GreetingScene extends Scene { #[OnMessage] public function onMessage(object $message): void { // ... }

  #[OnMessage(action: SceneAction::Enter)]
  public function onEnter(object $message): void
  {
      // ...
  }

}

Lifecycle actions

Transition hooks are registered with #[On*] attributes and SceneAction values, for example #[OnMessage(action: SceneAction::Enter)].

The enter() / leave() / exit() / back() / retake() methods below are parity stubs for user code that wants to call them explicitly; framework transitions dispatch attribute actions through SceneWizard.

SceneWizard

The $wizard property is typed as SceneWizard (Task 5.9). Subclasses receive a fully initialised wizard instance from the framework.

Table of Contents

Properties

$wizard  : SceneWizard
The wizard that manages scene transitions for this instance.
$cachedSceneConfig  : array<Scene>, SceneConfig>
Per-class cache of reflection-built `SceneConfig` instances.

Methods

__construct()  : mixed
Construct a scene instance.
addToRouter()  : void
Wire this scene's handlers into an existing router.
asHandler()  : callable(object, mixed...): void
Return a callable that enters this scene when invoked.
asRouter()  : Router
Return a `Router` sub-tree that registers this scene's handlers.
back()  : mixed
Parity stub for custom scene code.
enter()  : mixed
Parity stub for custom scene code.
exit()  : mixed
Parity stub for custom scene code.
leave()  : mixed
Parity stub for custom scene code.
retake()  : mixed
Parity stub for custom scene code.
sceneConfig()  : SceneConfig
Return the `SceneConfig` for this scene class.
sceneState()  : null|string
Return the FSM state string declared by the `#[SceneState]` attribute on this class (or a subclass), or `null` when no attribute is present.
buildSceneConfig()  : SceneConfig
Build a `SceneConfig` for this class by reflecting on `#[SceneState]` (class) and `#[On*]` (method) attributes.
prepareSceneMethodArguments()  : array<int|string, mixed>
Bind the event and dispatcher kwargs to a reflected scene method.
sceneParameterIsPositionalEvent()  : bool
sceneParameterNameLooksLikeEvent()  : bool

Properties

$wizard

The wizard that manages scene transitions for this instance.

public SceneWizard $wizard

$cachedSceneConfig

Per-class cache of reflection-built `SceneConfig` instances.

private static array<Scene>, SceneConfig> $cachedSceneConfig = []

Keyed by static::class so each subclass gets its own entry. Populated lazily by buildSceneConfig() on first access.

Methods

__construct()

Construct a scene instance.

public __construct(SceneWizard $wizard) : mixed
Parameters
$wizard : SceneWizard

Scene wizard that drives transitions.

addToRouter()

Wire this scene's handlers into an existing router.

public static addToRouter(Router $router) : void

For each HandlerContainer in sceneConfig()->handlers:

  • Create a SceneHandlerWrapper around the handler.
  • Register it with the matching observer (keyed by $handler->name, which is the Telegram event-type string such as 'message').
  • Track which observer names were used.

After all handlers are registered, add a StateFilter as a global observer filter on every used observer (except callback_query when callbackQueryWithoutState is true).

Mirrors Scene.add_to_router() (aiogram/fsm/scene.py:379-405).

Parameters
$router : Router

asHandler()

Return a callable that enters this scene when invoked.

public static asHandler([bool $checkActive = true ], mixed ...$handlerKwargs) : callable(object, mixed...): void

The returned closure is suitable for registering as a handler on any observer. When invoked it calls $scenes->enter(static::class, $checkActive) where $scenes is the ScenesManager injected by SceneRegistry middleware.

Mirrors Scene.as_handler() (aiogram/fsm/scene.py:423-438).

$checkActive — top-level parameter, not a kwarg

$checkActive is declared as an explicit typed parameter rather than flowing through ...$handlerKwargs. This avoids a PHP duplicate-named-arg error that would crash production when a middleware-injected kwarg named checkActive collides with the same-named key being forwarded positionally to ScenesManager::enter.

// Correct — uses the dedicated parameter: MyScene::asHandler(checkActive: false)

checkActive in the merged kwargs bag — silently dropped

Any kwarg literally named checkActive that arrives via $handlerKwargs or the middleware bag is removed from the merged array before the enter() call. This prevents the duplicate-named-arg crash for callers that inadvertently include a checkActive key in their own kwargs payload. The safety property from Cycle 1 is preserved: any other duplicate key collision still produces a PHP Error at the enter() call site.

Parameters
$checkActive : bool = true

When true (default) the currently active scene is exited before entering this one. Pass false to skip that step (e.g. for chained transitions).

$handlerKwargs : mixed

Extra kwargs merged into the enter() call.

Return values
callable(object, mixed...): void

asRouter()

Return a `Router` sub-tree that registers this scene's handlers.

public static asRouter([string|null $name = null ]) : Router

Mirrors Scene.as_router() (aiogram/fsm/scene.py:407-421).

The router name defaults to: "Scene '<FQCN>' for state ''"

Parameters
$name : string|null = null

Optional router name override.

Return values
Router

back()

Parity stub for custom scene code.

public back(mixed ...$kwargs) : mixed

Framework transitions dispatch SceneAction::Back attribute handlers via SceneWizard; they do not call this method directly.

Mirrors Scene.back() (aiogram/fsm/scene.py:414-416). Default: returns null.

Parameters
$kwargs : mixed

enter()

Parity stub for custom scene code.

public enter(mixed ...$kwargs) : mixed

Framework transitions dispatch SceneAction::Enter attribute handlers via SceneWizard; they do not call this method directly.

Mirrors Scene.enter() (aiogram/fsm/scene.py:400-404) as an overridable method user code may call explicitly. Default: returns null. Subclasses may return mixed.

Parameters
$kwargs : mixed

exit()

Parity stub for custom scene code.

public exit(mixed ...$kwargs) : mixed

Framework transitions dispatch SceneAction::Exit attribute handlers via SceneWizard; they do not call this method directly.

Mirrors Scene.exit() (aiogram/fsm/scene.py:410-412). Default: returns null.

Parameters
$kwargs : mixed

leave()

Parity stub for custom scene code.

public leave(mixed ...$kwargs) : mixed

Framework transitions dispatch SceneAction::Leave attribute handlers via SceneWizard; they do not call this method directly.

Mirrors Scene.leave() (aiogram/fsm/scene.py:406-408). Default: returns null.

Parameters
$kwargs : mixed

retake()

Parity stub for custom scene code.

public retake(mixed ...$kwargs) : mixed

No direct upstream equivalent — added for the PHP port's "retake" concept used in wizard-style multi-step scenes. Default: returns null.

Parameters
$kwargs : mixed

sceneConfig()

Return the `SceneConfig` for this scene class.

public static sceneConfig() : SceneConfig

On first call the config is built via reflection (reading #[SceneState] from the class and #[On*] attributes from public methods) and cached in self::$cachedSceneConfig[static::class]. Subsequent calls return the cached instance without re-reflecting.

Subclasses that override this method explicitly (e.g. test fixtures that hand-build a SceneConfig) bypass the reflection path entirely — the override is called instead.

Mirrors the __scene_config__ class attribute populated in Scene.__init_subclass__ (aiogram/fsm/scene.py:316-325).

Return values
SceneConfig

sceneState()

Return the FSM state string declared by the `#[SceneState]` attribute on this class (or a subclass), or `null` when no attribute is present.

public static sceneState() : null|string

Resolution order:

  1. The #[SceneState('explicit_state')] attribute value (non-null).
  2. If the attribute is absent, or present with $state = null, return null. Upstream Scene.__init_subclass__ defaults state to None when the state= kwarg is omitted; this port mirrors that behaviour. Users who want a named state must supply #[SceneState('mystate')].

Mirrors the state-name resolution in Scene.__init_subclass__ (aiogram/fsm/scene.py:318-322).

Return values
null|string

The resolved FSM state string, or null when no explicit state has been declared.

buildSceneConfig()

Build a `SceneConfig` for this class by reflecting on `#[SceneState]` (class) and `#[On*]` (method) attributes.

private static buildSceneConfig() : SceneConfig

Algorithm:

  1. Read #[SceneState] from the class → $stateName.
  2. For each public method, read all #[On*] attributes:
    • Attribute with $action === nullHandlerContainer entry in $handlers (ordinary event handler).
    • Attribute with $action !== null → entry in $actions keyed by $action->name (lifecycle action handler).
  3. Construct and return the SceneConfig.

Mirrors Scene.__init_subclass__ (aiogram/fsm/scene.py:321-377).

Return values
SceneConfig

prepareSceneMethodArguments()

Bind the event and dispatcher kwargs to a reflected scene method.

private static prepareSceneMethodArguments(ReflectionMethod $method, object $event, array<int|string, mixed> $kwargs) : array<int|string, mixed>

Scene methods are user handlers, so they should receive the same kwarg filtering ergonomics as normal dispatcher handlers: strict signatures get only declared parameter names, while a variadic tail opts in to the full workflow-data bag.

Parameters
$method : ReflectionMethod
$event : object
$kwargs : array<int|string, mixed>
Return values
array<int|string, mixed>

sceneParameterIsPositionalEvent()

private static sceneParameterIsPositionalEvent(ReflectionParameter $parameter, object $event) : bool
Parameters
$parameter : ReflectionParameter
$event : object
Return values
bool

sceneParameterNameLooksLikeEvent()

private static sceneParameterNameLooksLikeEvent(ReflectionParameter $parameter) : bool
Parameters
$parameter : ReflectionParameter
Return values
bool
On this page

Search results