Skip to content

Fix fatal error with statemachine v3.0.0#5

Merged
Metabor merged 2 commits into
masterfrom
fix/php82-compatibility
Jul 15, 2026
Merged

Fix fatal error with statemachine v3.0.0#5
Metabor merged 2 commits into
masterfrom
fix/php82-compatibility

Conversation

@Metabor

@Metabor Metabor commented Jul 15, 2026

Copy link
Copy Markdown
Owner

The example has not run since the v3.0.0 upgrade on 8 April: index.php dies with a fatal error before printing a single line of output.

PHP Fatal error: Declaration of Example\Order\Command\Authorize::__invoke(Order $order, ArrayAccess $context)
must be compatible with Metabor\Statemachine\Command::__invoke(mixed ...$args): void

Why

v3.0.0 changed two signatures:

Command::__invoke(mixed ...$args): void
ConditionInterface::checkCondition(object $subject, ArrayAccess $context): bool

The example classes still implement their 2015 form. PHP rejects the narrower child declarations (contravariance). The v3.0.0 upgrade (#4) touched composer.json, composer.lock and phpunit.xml.dist — no PHP file.

What changes

Authorize::__invoke mixed ...$args): void, arguments unpacked
Authorize::__toString : string
both Conditions object $subject … : bool, getName(): string
Order::triggerEvent ?ArrayAccess — implicit nullable is deprecated since 8.4

The variadic signature is forced by the parent class, so the type check the old signature used to perform is gone. Authorize now guards for it in the body, the same way ShippingDateGreater14Days already does — without it, calling it with the wrong type fails later and less clearly (Call to undefined method stdClass::getNumber() instead of a named exception).

Verification

Fresh clone, PHP 8.5.4:

without this PR:  fatal error, no example output
with this PR:     all four orders run through — 9 state transitions,
                  26 status lines, 10 events (one of them intentionally rejected)

The full example runs again, including the deliberate failure at the end (Current state "payment failed" doesn't have event "returned").

Note: running the example still emits 21 deprecations per run coming from the library itself, visible under error_reporting=E_ALLStatemachine#29 addresses those.

The example has not run since the v3.0.0 upgrade in April: index.php
dies with a fatal error before printing a single line.

v3.0.0 changed two signatures that the example classes still implement
in their 2015 form:

  Command::__invoke(mixed ...$args): void
  ConditionInterface::checkCondition(object $subject, ArrayAccess $context): bool

PHP rejects the narrower child declarations (contravariance).

  Authorize::__invoke   -> mixed ...$args): void, arguments unpacked
  Authorize::__toString -> : string
  both Conditions       -> object $subject ... : bool, getName(): string
  Order::triggerEvent   -> ?ArrayAccess (implicit nullable is deprecated since 8.4)

Verified on PHP 8.5.4:
  before: 1 fatal error, no output
  after:  runs through all four orders, 26 state transitions
The example has not run since the v3.0.0 upgrade in April: index.php
dies with a fatal error before printing a single line of output.

v3.0.0 changed two signatures that the example classes still implement
in their 2015 form:

  Command::__invoke(mixed ...$args): void
  ConditionInterface::checkCondition(object $subject, ArrayAccess $context): bool

PHP rejects the narrower child declarations (contravariance).

  Authorize::__invoke   -> mixed ...$args): void, arguments unpacked
  Authorize::__toString -> : string
  both Conditions       -> object $subject ... : bool, getName(): string
  Order::triggerEvent   -> ?ArrayAccess (implicit nullable is deprecated since 8.4)

The variadic signature is forced by the parent class, so the type check
the old signature performed is gone. Authorize now guards for it in the
body, the same way ShippingDateGreater14Days already does.

Verified on PHP 8.5.4:
  before: fatal error, no example output
  after:  all four orders run through, 9 state transitions
@Metabor
Metabor merged commit c4d9535 into master Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant