violines/rest-bundle
A Symfony bundle for building REST APIs with less boilerplate. It offers practical helpers and conventions for controllers, request handling, responses, serialization, validation, and pagination, helping teams ship consistent JSON APIs faster.
This release (v0.8.1) is a compatibility widening, not a feature release: the package now accepts psr/log ^2 and ^3 alongside its previous constraint. That matters most at install/upgrade time, because psr/log is the interface package every PSR-3 logger implements — a narrow constraint here is what usually blocks a Laravel 10/11 upgrade (Monolog 3 ships psr/log ^3, older stacks ship ^1/^2).
Minimal steps:
composer require the package and let Laravel's package discovery register the service provider. If the package ships config, publish it (php artisan vendor:publish --tag=...) and review the defaults before touching anything.config/logging.php). Those two files tell you almost everything about how it is meant to be wired.Psr\Log\LoggerInterface out of the container — not a concrete class — and confirm you get the package's logger. That single check validates the whole integration.LoggerInterface into one service or job, log a message with structured context, and verify it lands in the expected channel/handler.Because this release only relaxes a dependency constraint, the upgrade path is low-risk: run composer update and then re-check the container binding, since a changed psr/log major can pull in a different Monolog major underneath.
Depend on the interface, not the implementation. Type-hint Psr\Log\LoggerInterface in constructors and resolve it from the container. This keeps your code portable and means the package's binding (or a later swap to a different driver) doesn't ripple through your codebase. Avoid injecting the package's concrete logger class unless you need package-specific methods.
Channel-per-concern. If the package registers a logging driver, define dedicated channels in config/logging.php (e.g. billing, audit, integrations) rather than reusing stack. Route each to the appropriate handler and level, then bind named loggers in a small service provider so callers get the right channel by type rather than by string lookup.
Structured context over string interpolation. Use the PSR-3 placeholder/context form ($logger->info('Order {id} failed', ['id' => $order->id, 'exception' => $e])) so handlers and processors can index fields. Pass the exception under the exception key — most PSR-3 implementations, including Monolog-backed ones, render the stack trace from it automatically.
Wrap the Log facade at the boundary. In an existing Laravel app you'll have Log:: calls scattered around. Rather than rewriting everything, introduce the PSR-3 logger in new code and adapt legacy call sites behind a thin service, so both paths converge on the same channel config and you avoid two divergent logging setups.
Use it in jobs and middleware deliberately. Injecting a logger into a queued job is fine, but be aware the logger travels with the serialized job — log context added at dispatch time will still be present at run time. For request-scoped correlation, push an ID via a middleware processor or withContext() and pop it afterward.
Test with a spy, not a mock of the concrete class. Bind a Psr\Log\LoggerInterface test double (a simple in-memory recorder) into the container and assert on recorded level/message/context. This tests your intent without coupling tests to the package's internals.
Integration tips. Register the binding in a dedicated service provider rather than AppServiceProvider for anything non-trivial; use singleton for the logger, bind for anything that carries per-request state; and if the package exposes processors/formatters, add them via config rather than subclassing.
The psr/log constraint is the whole story of this release. If you pin psr/log yourself in composer.json, or another dependency requires ^1, you can still hit a conflict even with v0.8.1. Check with composer why psr/log / composer why-not psr/log ^3 before assuming the upgrade will resolve cleanly. Widening a constraint is backward-compatible for consumers, but it does not guarantee the underlying Monolog major matches what your handlers expect.
^2 and ^3 are not identical in practice. psr/log v3 added types (notably Stringable|string on message parameters and array $context return types). If you have custom loggers, handlers, or test doubles implementing LoggerInterface, they may need signature updates to satisfy v3 — the package accepting both doesn't mean your implementations do.
Don't mix facade and PSR-3 logging on the same channel without thinking. Log::info() and an injected LoggerInterface can resolve to the same handler, which is usually fine, but differing context/processor stacks produce confusing output. Pick one path per module.
Config caching bites. New channels or driver registrations added in a service provider won't appear until php artisan config:clear if you've cached config. Same for composer dump-autoload after a provider change.
Logging in a loop is a performance trap. The PSR-3 API hides handler cost; a debug-level log in a hot loop over thousands of records can dominate a request. Guard expensive context construction (serializing models, computing diffs) behind a isDebugEnabled()-style check or lazy context.
Extension points to prefer. Use the tap array in channel config to attach processors, and configure formatters/handlers in config/logging.php rather than subclassing the driver. If the package exposes a manager or driver factory, resolve that from the container when you need to build channels dynamically — it will honour the same config.
Debugging a "log went nowhere" report. In order: confirm the binding resolves (app(LoggerInterface::class)), confirm the channel name actually exists in config/logging.php, check storage/logs permissions and the configured minimum level, then verify no null/noop handler is active in the current environment. Nine times out of ten it's the level threshold or a cached config.
Pin and test on upgrade. Since this is a pre-1.0 package, treat minor versions as potentially behaviour-changing and add a smoke test that exercises one real log emission end-to-end. That test is what will catch a future change that isn't purely a constraint bump.
How can I help you explore Laravel packages today?