Summary
Enhance the current Hook package and boot pipeline so optional integrations can subscribe to stage lifecycle events during bootstrap.
The goal is to support stage-owned BEFORE / AFTER hook points, allowing optional integrations such as debugbar to initialize at precise boot boundaries without being hardcoded into the core pipeline.
Why
The current Hook package is close to usable for this direction, but it still needs framework-level support for bootstrap-time stage events.
Current needs:
- optional integrations should be able to initialize during boot without hardcoded stages in core
- boot lifecycle points should be attached to meaningful stage boundaries
- the framework should not need special-purpose stages such as
InitDebuggerStage for optional tooling
- the current Hook mechanism should be strengthened rather than replaced
A better model is:
- each boot stage can define
BEFORE and AFTER hook names
BootPipeline dispatches those hook points automatically around stage execution
- optional integrations subscribe to the stage boundary they care about
For example, debugbar should be able to initialize at:
instead of requiring a dedicated hardcoded debugger stage in core.
Goals
- keep the current Hook-style mechanism and evolve it
- make hook registration available during bootstrap
- allow boot stages to define
BEFORE / AFTER hook names
- make
BootPipeline dispatch those hook points automatically
- support optional integrations without hardcoded core dependencies
- keep the mechanism usable for user-defined application and module events, not only framework lifecycle hooks
Proposed Changes
- enhance the Hook package so listener registration is safe early in bootstrap
- introduce clearer API naming:
listen() instead of on()
dispatch() instead of fire()
- keep
on() / fire() as compatibility aliases if needed
- avoid positional payload arrays for framework-defined hook payloads and use stable named payloads
- allow boot stages to define lifecycle hook names such as
BEFORE and AFTER
- update
BootPipeline to dispatch those hooks automatically around stage execution when present
Architectural Constraint
The mechanism introduced here must remain extensible for future event sources beyond boot stages, including:
- route-level events
- request/response events
- console lifecycle events
- user-defined business/domain events
Stage lifecycle hooks are the first concrete use case for this mechanism, but they must not lock the design into a stage-only event model.
Example Direction
Stage definition:
final class LoadModulesStage implements BootStageInterface
{
public const BEFORE = 'boot.modules.before';
public const AFTER = 'boot.modules.after';
public function process(AppContext $context): void
{
// existing stage logic
}
}
Pipeline behavior:
foreach ($this->stages as $stage) {
if (defined(get_class($stage) . '::BEFORE')) {
event()->dispatch($stage::BEFORE, [
'context' => $context,
]);
}
$stage->process($context);
if (defined(get_class($stage) . '::AFTER')) {
event()->dispatch($stage::AFTER, [
'context' => $context,
]);
}
}
Optional integration subscription:
event()->listen(LoadModulesStage::BEFORE, function (array $payload): void {
$context = $payload['context'];
debugbar()->boot($context);
});
Acceptance Criteria
- hook/event listener registration is safe during bootstrap
- boot stages can define
BEFORE / AFTER lifecycle hook names
BootPipeline dispatches those lifecycle hooks automatically when defined
- framework-defined hook payloads use stable named payloads rather than positional arrays
- clearer method names such as
listen() and dispatch() are introduced
- existing
on() / fire() usage remains compatible if aliasing is chosen
- optional integrations can subscribe to boot stage boundaries without hardcoded core stages
- the design remains extensible for non-stage framework events and user-defined business events
- tests cover bootstrap-time registration and stage lifecycle hook dispatch
- docs are updated as needed
Notes
Relevant code:
src/Hook/HookManager.php
src/Hook/Helpers/hook.php
src/App/BootPipeline.php
src/App/Stages/InitHttpStage.php
src/App/Stages/LoadModulesStage.php
tests/Unit/Hook/HookManagerTest.php
tests/Unit/Hook/Helpers/HookHelperTest.php
This ticket should be treated as the foundation for:
- lifecycle hooks
- debugbar via lifecycle hooks
Summary
Enhance the current Hook package and boot pipeline so optional integrations can subscribe to stage lifecycle events during bootstrap.
The goal is to support stage-owned
BEFORE/AFTERhook points, allowing optional integrations such as debugbar to initialize at precise boot boundaries without being hardcoded into the core pipeline.Why
The current Hook package is close to usable for this direction, but it still needs framework-level support for bootstrap-time stage events.
Current needs:
InitDebuggerStagefor optional toolingA better model is:
BEFOREandAFTERhook namesBootPipelinedispatches those hook points automatically around stage executionFor example, debugbar should be able to initialize at:
LoadModulesStage::BEFOREinstead of requiring a dedicated hardcoded debugger stage in core.
Goals
BEFORE/AFTERhook namesBootPipelinedispatch those hook points automaticallyProposed Changes
listen()instead ofon()dispatch()instead offire()on()/fire()as compatibility aliases if neededBEFOREandAFTERBootPipelineto dispatch those hooks automatically around stage execution when presentArchitectural Constraint
The mechanism introduced here must remain extensible for future event sources beyond boot stages, including:
Stage lifecycle hooks are the first concrete use case for this mechanism, but they must not lock the design into a stage-only event model.
Example Direction
Stage definition:
Pipeline behavior:
Optional integration subscription:
Acceptance Criteria
BEFORE/AFTERlifecycle hook namesBootPipelinedispatches those lifecycle hooks automatically when definedlisten()anddispatch()are introducedon()/fire()usage remains compatible if aliasing is chosenNotes
Relevant code:
src/Hook/HookManager.phpsrc/Hook/Helpers/hook.phpsrc/App/BootPipeline.phpsrc/App/Stages/InitHttpStage.phpsrc/App/Stages/LoadModulesStage.phptests/Unit/Hook/HookManagerTest.phptests/Unit/Hook/Helpers/HookHelperTest.phpThis ticket should be treated as the foundation for: