laravelista/picasso
Picasso is a Laravel package for simple, fluent image manipulation. Resize, crop, and cache images stored on any filesystem disk, generate thumbnails, and keep your originals untouched. It fits neatly into Laravel's filesystem and works with local or cloud storage.
Start by reading the package's composer.json and CHANGELOG/release notes before installing — as of 0.8.0 the package relies on typed signatures and named arguments, which means it targets PHP 8.0+ and will not install on older runtimes.
Minimal setup:
composer require <vendor>/<package> (check the constraint — if you were on ^0.7, pin ^0.8 deliberately rather than floating).php artisan about or check bootstrap/cache/packages.php). If discovery is disabled in your app, register the provider manually.php artisan vendor:publish --tag=<package>-config (and -migrations where applicable). Publish first, then edit — do not edit files inside vendor/.php artisan config:clear after publishing so you're not testing against a cached config from a previous version.First use case: resolve the package's main entry point from the container rather than instantiating it (app(SomeClient::class) or the provided facade), then exercise the simplest documented call in php artisan tinker. That confirms bindings, config keys, and credentials are wired before you build anything on top of it.
Where to look first in the source: the service provider (what's bound, singleton vs. scoped, what's published), the config file (every key with its default), and tests/ (the package's own usage examples are the most accurate documentation of the 0.8.0 signatures).
Constructor injection over facades. With typed properties now enforced, type-hinting the package's interfaces in your own constructors is both safer and better supported by static analysis. Bind the package's interface to your preferred implementation in a service provider if you need to swap behaviour, and let Laravel resolve the rest.
Use named arguments when calling package APIs. Since 0.8.0 internally uses named parameters, the maintainers clearly treat parameter names as meaningful. Mirror that in your own call sites — $client->send(payload: $data, timeout: 10) — which makes you resilient to positional reshuffles and self-documenting at the call site. This is especially valuable for methods with several optional arguments.
Wrap the package behind a thin adapter. Put a small application-level class between your domain code and the package. When a minor release changes a signature (as 0.8.0 does), you edit one file instead of grepping the codebase. This also gives you a seam for tests.
Test with the package's fakes or a bound stub. If the package ships a fake, use it in feature tests; otherwise bind a mock of its interface in the container inside setUp(). Because the package now has real type declarations, your test doubles must satisfy them exactly — return the declared type, not a loosely-shaped array.
Configuration-driven workflows. Read tunables from config/<package>.php via config('package.key') and reference env vars only in the config file. When queueing package jobs, remember config is read at worker boot — restart workers after changing it.
Integration touchpoints. Register package events/listeners in your EventServiceProvider, and if the package exposes extension points (custom resolvers, drivers, formatters), prefer registering them in a dedicated service provider over subclassing internals.
Unknown named parameter error. Pin minor versions and read the changelog. Conversely, never mix positional and named arguments after a spread.TypeErrors where coercion used to happen. Values that previously slipped through @param string (ints, nullables, Stringable objects) are now rejected at runtime. Audit any call site that passed loosely-typed data — request input, JSON-decoded arrays, env values that are strings.void in particular: a child method with no return type where the parent declares void is fine, but the inverse is not. Grep your app for extends on package classes before upgrading.strict_types. Typed signatures plus declare(strict_types=1) turns silent coercions into exceptions. If the package added strict types, test with production-like data, not just fixtures.php artisan optimize:clear (or config:clear, route:clear, view:clear). Stale caches masking new bindings is the single most common "the upgrade broke everything" false alarm.queue:work and reload Octane workers after upgrading — long-lived processes hold the old class definitions and old typed property declarations in memory.TypeError from deep inside vendor/, read the stack trace bottom-up to find your call site; the package frame is usually just where the type check was declared. dd(get_debug_type($value)) before the call is faster than stepping through a debugger.UPGRADING.md if present) rather than trusting the summary alone.How can I help you explore Laravel packages today?