itsgoingd/slim-facades
Bring Laravel-style facades to Slim Framework. slim-facades adds a lightweight facade layer and service container integration, letting you access container-bound services through clean static interfaces in your routes and controllers, with minimal setup and no framework overhaul.
Install the package and register the container the facades should resolve from:
composer require itsgoingd/slim-facades
require __DIR__ . '/vendor/autoload.php';
$app = new \Slim\App($settings);
// Point the facades at the Slim container. Do this once, before
// any facade call is made.
\SlimFacades\Facade::setFacadeContainer($app->getContainer());
$app->get('/', function ($request, $response) {
return \SlimFacades\Response::write('Hello world');
});
Where to look first:
src/*Facade.php or similar). Each one exposes a getFacadeAccessor()-style method that names the container key it proxies (view, router, logger, request, response, …). That mapping is the real API surface — read it before assuming a method exists.setFacadeContainer) and the list of bundled facades (App, Container, Request, Response, Router, View, Log).First realistic use case: you have a Slim 3 app whose container holds view, router, logger, and you are tired of threading $this->get(...) or $container->get(...) into every helper, template function, and middleware. Replace a single call — e.g. Router::pathFor('user.show', ['id' => 1]) inside a Twig template or a small helper — and confirm it resolves through the container before converting more call sites.
URL generation in templates and helpers. The most common day-one win. Named routes stop needing the router injected everywhere:
// in a Twig function / view helper / middleware
$url = \SlimFacades\Router::pathFor('user.show', ['id' => $user->id]);
Rendering responses. Facades are handy where you do not already have $response in scope, or where a service returns a response-like payload:
return \SlimFacades\Response::withJson($payload);
return \SlimFacades\Response::withRedirect(\SlimFacades\Router::pathFor('login'));
Request access from services. Injecting Request into every small collaborator is noisy. For leaf helpers (formatters, validators, view extensions) Request::getParam(...), Request::getQueryParam(...), Request::getAttribute(...) keeps signatures clean:
class CurrentUser
{
public function id()
{
return \SlimFacades\Request::getAttribute('user_id');
}
}
Logging. If logger (Monolog) is registered in the container, Log::info(...) / Log::error(...) works anywhere without injection — useful in exception handlers and small domain services.
Container access as an escape hatch. Container::get('foo') / Container::has('foo') when you genuinely need lazy resolution, e.g. inside a closure registered before the container is fully built.
Custom facades. The intended extension point is subclassing the base facade and pointing the accessor at your own container key:
class Mailer extends \SlimFacades\Facade
{
protected static function getFacadeAccessor()
{
return 'mailer'; // key in the Slim container
}
}
\SlimFacades\Mailer::send($message);
This is the pattern to prefer over Container::get('mailer') sprinkled through code — it gives you autocompletion, one place to change the key, and a seam for tests.
Wiring order matters. Register your services (view, logger, mailer, …) on the container, then call setFacadeContainer, then define routes/controllers that use facades. Middleware that runs before the facade bootstrap will not have facades available.
App, no getContainer() on the app), so do not assume the same bootstrap works on Slim 4 — verify before planning an upgrade.($request, $response), and those may be different instances from the container's request/response entries after middleware. Mutating via Response::... inside a route will often not affect the response you return. Prefer the $request/$response arguments when they are in scope; use the facade only where you legitimately cannot.View, Log, Router fail if the corresponding key is not registered. Register view/router/logger before touching those facades, and add a smoke test that calls each facade you rely on.setFacadeContainer is set will fail hard. Put the bootstrap immediately after container construction, and mirror it in your test bootstrap so tests exercise the same static state.getFacadeAccessor() on the facade class and then dump the container key directly ($container->get('view')). The facade is almost always a thin proxy; the bug is usually in the container definition.Request::... deep in a domain class is the main maintainability trap with any facade package.Container::get('some-key') in more than one place, promote it to a custom facade subclass so the key lives in one location.How can I help you explore Laravel packages today?