Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Presenter Laravel Package

robclancy/presenter

RobClancy Presenter is a Laravel package for decorating models and other objects with presentation logic, keeping views clean and models focused. Define reusable presenter classes to format output, handle HTML, and separate display concerns from domain code.

View on GitHub
Deep Wiki
Context7

Getting Started

Verify the PHP floor before anything else. 3.0.0 requires PHP 8.1, so the first step is confirming your runtime and your composer.json allow it:

php -v
composer why-not php "8.1.*"   # surfaces packages pinning you below the new floor

Check config.platform.php in composer.json — a hardcoded "php": "8.0" there will block the upgrade even if the server runs 8.1. Same for CI images and Docker bases.

Where to look first:

  1. composer.json of the package — the php constraint and the illuminate/* version ranges tell you which Laravel versions 3.0.0 still supports. A PHP 8.1 floor usually signals the package has moved to Laravel 9/10-era internals.
  2. CHANGELOG.md / UPGRADING.md — confirm whether the ArrayAccess deprecation fix changed any public signatures (see Gotchas).
  3. The package's main object — since 3.0.0 is specifically about ArrayAccess, that object is the API surface most worth reading.

First use case: install, publish any config (php artisan vendor:publish --provider="...\ServiceProvider"), then exercise the ArrayAccess surface directly, because that is what this release touched:

$thing = app(SomePackageClass::class);

$thing['key'] = 'value';
isset($thing['key']);      // must agree with offsetExists
$thing['key'] ?? null;     // must not emit a deprecation
unset($thing['key']);

Run this with error_reporting(E_ALL) locally — the whole point of the release is that these calls are now clean on 8.1.

Implementation Patterns

Treat the upgrade as a platform bump, not a feature adoption. 3.0.0 adds no new behaviour; it moves a floor and silences deprecations. The work is in dependency alignment, not in rewriting call sites.

CI matrix first, code second. Add 8.1 explicitly so the fix is actually proven:

php: ['8.1', '8.2', '8.3']

Run composer update --prefer-lowest on 8.1 as a separate job — that combination is where implicit ArrayAccess signature mismatches surface.

ArrayAccess objects through Laravel plumbing. If the package exposes an ArrayAccess-backed object, the common integration points are data_get()/Arr::get() fallbacks, Blade {{ $thing['key'] }}, and collect($thing). Laravel's data_get uses Arr::accessible() which checks instanceof ArrayAccess, so these work — but only if offsetExists/offsetGet are consistent. Add a small feature test asserting the object survives a json_encode/collect round-trip; that catches inconsistent offsets fast.

Container + facade usage. Resolve from the container rather than new, so config and any shared state apply:

$this->app->make(PackageClass::class);
// or via its facade if one is documented

Static analysis as the migration gate. Annotate generics on the ArrayAccess implementer in your own extending classes:

/** @implements \ArrayAccess<string, mixed> */

Then run PHPStan at your existing level — the 8.1 mixed return on offsetGet mismatches are exactly the class of bug this release fixes, and PHPStan will find any subclass in your code that still declares the old signature.

Extension points. Subclasses and decorators of the package's ArrayAccess type are the highest-risk integration. Grep your codebase for extends on the package namespace before bumping:

grep -rn "extends .*PackageNamespace" app/ tests/

Gotchas and Tips

The offsetGet return type is the real gotcha. PHP 8.1 deprecates ArrayAccess::offsetGet() without a mixed return type (and the same for ReturnTypeWillChange on the other three). The package fixed its implementations, but any class in your app extending it must be updated too — otherwise you swap one deprecation for another.

Deprecations are logged, not thrown — until tests. Laravel's exception handler logs E_DEPRECATED rather than throwing, so this upgrade can look clean in the app and still fail in CI. PHPUnit's convertDeprecationsToExceptions (default on in PHPUnit 10+) will fail on them. That is a feature: it is your verification that the fix works. If you run an older PHPUnit, enable it explicitly.

$obj['k'] ?? null calls two methods. It invokes offsetExists then offsetGet. If the package's offsetExists returns true for keys whose offsetGet returns null, ?? silently behaves differently than array_key_exists did. Test both idioms.

Debugging deprecations that survive the bump:

php -d error_reporting=E_ALL -d display_errors=1 artisan tinker
# or capture the trace:
php -d error_reporting=E_ALL vendor/bin/phpunit --display-deprecations

--display-deprecations on PHPUnit 10 is the fastest way to attribute a notice to a specific test.

Composer platform pin. The single most common failure: composer update refuses to install 3.0.0 because config.platform.php says 8.0. Fix the platform config first, then update, or you will misdiagnose it as a version conflict.

Laravel version coupling. Dropping PHP 8.0 generally means the package has also dropped Laravel versions that only ran below 8.1. Check the package's illuminate/support constraint against your app's Laravel version before bumping — a 3.0.0 install on Laravel 8 is likely no longer supported even if Composer allows it.

Lockfile hygiene. Bump the package explicitly (composer require vendor/package:^3.0) rather than a blanket composer update, so unrelated transitive changes don't get blamed on this release during debugging.

Extension point to revisit: if the deprecation fix involved an #[\ReturnTypeWillChange] attribute rather than a real mixed return type, inherited signatures in your code may still need the same attribute. Check the actual diff on the implementing class rather than assuming a native mixed return.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager