Skip to content

Rip out most of the magic and replace it with ->to() and ->toStatic(). For manager classes the magic remains. Rip out magic from View.php for dynamic with{Word}. ->with('{word}', $param) should be used instead.

Choose a tag to compare

@macropay-solutions macropay-solutions released this 11 Sep 14:24
· 92 commits to production since this release
e78d926

Release Notes: Architectural Strictness & Magic Removal

Overview

This release introduces a massive architectural shift focused on strict typing, static analysis compliance, and the eradication of runtime "magic." By removing dynamic method interception and higher-order proxies, the framework provides more transparency to IDEs and static analysis tools (like PHPStan and Psalm).

💥 Breaking Changes

  • Higher-Order Proxies Eliminated:
    • All Higher-Order proxy classes (HigherOrderBuilderProxy, HigherOrderCollectionProxy, HigherOrderTapProxy, and HigherOrderWhenProxy) have been permanently deleted.
    • You can no longer omit closures on collection/conditionable methods. Calls like $collection->each->update(...), tap($user)->update(...), or $query->when($condition)->active() must now be written with explicit closures: $collection->each(fn($item) => $item->update(...)).
    • The tap(), when(), and unless() methods now strictly require a callable argument.
  • Dynamic View Bindings Removed:
    • The __call magic inside View.php that handled dynamic variable binding has been removed.
    • You can no longer use $view->withTitle('foo'). You must use the explicit syntax: $view->with('title', 'foo').
  • Decorator & Wrapper Strictness:
    • Wrapper classes no longer silently forward missing methods via __call.
    • Classes including Cache\Repository, FilesystemAdapter, ViewErrorBag, SentMessage, Optional, InvokableComponentVariable, AbstractPaginator, and AbstractCursorPaginator will now throw a BadMethodCallException if you attempt to call underlying driver methods directly on them. You must now explicitly unwrap them using the ->to() method.
  • Global str() Helper Removed:
    • The dynamic str() global helper has been completely removed to enforce strict typing. All string manipulations must now use Str::of().
  • Obvious Model Relation Execution:
    • Dynamic relation execution via the model's __call method is now disabled and throws an exception. You must use $model->r->relationName() or $model->callSegregatedRelation('relationName').
  • Obvious Builder Proxies Removed:
    • Magic __get intercepts for orWhere, whereNot, and orWhereNot have been removed from the Database Builder.

✨ New Features & Enhancements

  • Explicit Unwrapping (->to()) on Managers:
    • Added a strict ->to() method across all core Manager classes (AuthManager, CacheManager, DatabaseManager, LogManager, MailManager, QueueManager, RedisManager, FilesystemManager, BroadcastManager, PasswordBrokerManager, MultipleInstanceManager, and Process\Factory).
    • Calling ->to() explicitly returns the underlying active driver/connection, allowing for perfect static analysis.
    • Note: Manager classes retain their __call fallback logic to prevent widespread application breakage, but ->to() is the recommended standard.
  • Static Unwrapping (::toStatic()) on Capsules:
    • Added ::toStatic() to Database\Capsule\Manager and Queue\Capsule\Manager to explicitly retrieve the underlying default connection in static contexts.
  • New Forwarding Trait:
    • Introduced ExplicitForwardable trait. This trait standardize the new strict architecture by intercepting __call to throw a clear BadMethodCallException directing developers to use ->to() or ::toStatic() instead.