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

Slim Base Laravel Package

awurth/slim-base

A Composer-ready Slim Framework skeleton with routing, dependency injection, Twig views, authentication, validation, and database support, giving PHP developers a clean starting point for building web apps and APIs without boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

awurth/slim-base is not a library you composer require — it is a create-project skeleton for Slim 3. Treat it the way you'd treat laravel/laravel: you own the code the moment it's generated, and upstream changes do not flow into your app.

composer create-project awurth/slim-base my-app
cd my-app && php -S localhost:8080 -t public

The first five files to read, in order:

  1. public/index.php — the bootstrap; shows how the Slim\App is constructed and which config files are loaded.
  2. app/settings.php — the settings array (debug flags, view paths, logger, DB credentials). This is your config/ directory.
  3. app/dependencies.php — the Pimple container. This is where every service lives.
  4. app/middleware.php — global middleware stack.
  5. app/routes.php — route definitions, plus app/src/ for your App\ namespaced code.

Mental mapping from Laravel:

Laravel slim-base
routes/web.php app/routes.php (split per domain as you grow)
app/Http/Controllers app/src/Controllers
Blade Twig (app/templates)
Service container + autowiring Pimple, explicit registration only
Form Requests app/src/Validation (awurth/slim-validation)
Eloquent Not included — wire up Doctrine or Eloquent yourself
php artisan Nothing. No CLI beyond Composer.

First use case: add a route in app/routes.php, a controller in app/src/Controllers/, and a Twig template. That single vertical slice shows you the container, the renderer, and the response flow in about ten minutes.

Implementation Patterns

Routes. Keep routes.php as an include of per-domain files (app/routes/api.php, app/routes/admin.php) as soon as you exceed ~20 routes. Use groups for prefixes and shared middleware, and name routes so you can generate URLs in Twig instead of hardcoding paths.

$app->group('/users', function () {
    $this->get('', UserController::class . ':index')->setName('users.index');
    $this->post('', UserController::class . ':store');
})->add($container->get('csrf'));

Controllers. Resolve dependencies through the container and render through the Twig view service. Prefer injecting the specific services a controller needs over grabbing $this->container everywhere — the latter is the Slim equivalent of app() abuse and makes controllers untestable.

class UserController
{
    public function __construct($view, UserRepository $users) { ... }

    public function index($request, $response)
    {
        return $this->view->render($response, 'users/index.twig', [
            'users' => $this->users->all(),
        ]);
    }
}

Container. Every service is a closure in dependencies.php, keyed by a string. Register repositories, mailers, and clients there. Services are shared by default, which is what you want for a DB connection and usually not what you want for anything holding request state.

Middleware. Two tiers: global in app/middleware.php, per-route via ->add(). Remember Slim 3 middleware is double-pass — function ($request, $response, $next) — not PSR-15. Add your session middleware before CSRF, and error-handling middleware outermost.

Validation. The skeleton's validation layer wraps Respect Validation. Define one validator class per form/endpoint, run it at the top of the controller action, and redirect back with flashed errors on failure. Do not scatter if (empty($request->getParsedBody()['x'])) checks through controllers.

Persistence. This is the biggest gap coming from Laravel. Pick Doctrine ORM, Doctrine DBAL, or illuminate/database and bind it in dependencies.php; then add Phinx or Doctrine Migrations for schema. Decide this before writing models, because the three options produce very different repository code.

Cross-cutting. Monolog is registered — use it instead of error_log. Twig layouts go in app/templates/layout.twig and everything {% extends %} it. Environment config goes through .env plus environment-keyed arrays in settings.php.

Gotchas and Tips

  • The skeleton is a snapshot, not a dependency. composer update will update Slim and your libraries but never the skeleton itself. If you care about upstream fixes, keep a bare create-project of the latest tag in a scratch directory and diff app/ occasionally.
  • Slim 3 is legacy territory. Last release of this skeleton was January 2020, and Slim 3 itself is maintenance-only. Modern PSR-15 middleware packages will not drop in — you'll be writing double-pass adapters. For a new project in 2024+, evaluate Slim 4 (or stay in Laravel) before committing to this.
  • PHP version ceiling. Verify against PHP 8.1+ before you start; several transitive dependencies pinned by a 2020 lockfile will complain or silently misbehave on modern runtimes. Expect a dependency-bump session on day one.
  • No autowiring. Pimple does not reflect on constructor type hints. If UserController type-hints UserRepository, the container will not build it unless you registered UserRepository::class as a key. Symptom: NotFoundException or "Identifier not defined". Fallback: swap Pimple for PHP-DI via the Slim container bridge, or write a small reflection-based resolver.
  • Middleware ordering is LIFO. The last $app->add() runs first. Session → CSRF → routing → error handler is the order you almost always want, which means adding them in reverse.
  • getParsedBody() is null for JSON. It only parses form-encoded and multipart bodies. For a JSON API, add body-parsing middleware or decode (string) $request->getBody() yourself. This is the single most common "why is my request empty" bug.
  • Debug flags leak. displayErrorDetails must be driven off the environment, not left true in settings.php. Pair it with Whoops in dev and a plain 500 handler in prod.
  • Twig cache directory permissions. var/cache must exist and be writable. Cached templates silently serve stale markup in dev — disable the cache in your dev settings block.
  • CSRF is opt-in per route. Applying it globally breaks JSON clients; apply it to the form-driven route group only.
  • Testing. There is no test harness out of the box. Add PHPUnit and exercise the whole Slim\App via $app->process($request, $response) — integration tests catch middleware-ordering and container mistakes far better than unit-testing controllers in isolation.
  • Extension points worth knowing: app/middleware.php (global stack), app/dependencies.php (service overrides), the environment-keyed branches in settings.php, and the Slim\App constructor itself — passing in your own container is the cleanest way to retrofit PHP-DI without touching framework code.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
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