PHPackages                             robiningelbrecht/php-slim-skeleton - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. robiningelbrecht/php-slim-skeleton

ActiveLibrary[Framework](/categories/framework)

robiningelbrecht/php-slim-skeleton
==================================

47884PHP

Since May 5Pushed 2y ago2 watchersCompare

[ Source](https://github.com/robiningelbrecht/php-slim-skeleton)[ Packagist](https://packagist.org/packages/robiningelbrecht/php-slim-skeleton)[ RSS](/packages/robiningelbrecht-php-slim-skeleton/feed)WikiDiscussions master Synced 3w ago

READMEChangelogDependenciesVersions (2)Used By (0)

Event-driven Slim 4 Framework skeleton
======================================

[](#event-driven-slim-4-framework-skeleton)

 [![Slim](https://github.com/robiningelbrecht/slim-skeleton-ddd-amqp/raw/master/readme/slim-new.webp)](https://github.com/robiningelbrecht/slim-skeleton-ddd-amqp/raw/master/readme/slim-new.webp)

[![CI](https://github.com/robiningelbrecht/slim-skeleton-ddd-amqp/actions/workflows/ci.yml/badge.svg)](https://github.com/robiningelbrecht/slim-skeleton-ddd-amqp/actions/workflows/ci.yml)[![Codecov.io](https://camo.githubusercontent.com/b1de7df9aba0e4f021ab78bcc4733aeff881873ecd91d50b0524abbeec170840/68747470733a2f2f636f6465636f762e696f2f67682f726f62696e696e67656c6272656368742f7068702d736c696d2d736b656c65746f6e2f6272616e63682f6d61737465722f67726170682f62616467652e7376673f746f6b656e3d68676e6c465776577677)](https://codecov.io/gh/robiningelbrecht/php-slim-skeleton)[![License](https://camo.githubusercontent.com/74b24a8a75b5cd79623aefdbf3b3e3886a41930e7c1847ccaaab31a12f0d3dfb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f726f62696e696e67656c6272656368742f736c696d2d736b656c65746f6e2d6464642d616d71703f636f6c6f723d343238663765266c6f676f3d6f70656e253230736f75726365253230696e6974696174697665266c6f676f436f6c6f723d7768697465)](https://github.com/robiningelbrecht/slim-skeleton-ddd-amqp/blob/master/LICENSE)[![PHPStan Enabled](https://camo.githubusercontent.com/f75e5846caa6d666bbb02e8b2f540ae1c7248cabda194ff1ce3591afc40fd213/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230382d7375636365732e7376673f6c6f676f3d706870266c6f676f436f6c6f723d776869746526636f6c6f723d333143363532)](https://phpstan.org/)[![PHP](https://camo.githubusercontent.com/aee8f6f03bbdea94a8f2c5ce8308fc9371acd6b15ae046b8f7c74935f06677cc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f726f62696e696e67656c6272656368742f7068702d736c696d2d736b656c65746f6e2f6465762d6d61737465723f636f6c6f723d253233373737626233266c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://php.net/)

---

 An event-driven Slim 4 Framework skeleton using AMQP and CQRS

Installation
------------

[](#installation)

### Default installation profile

[](#default-installation-profile)

The default installation profile has no examples. You should be using this profile if you know what's up and want to start with a clean slate.

```
> composer create-project robiningelbrecht/php-slim-skeleton [app-name] --no-install --ignore-platform-reqs --stability=dev
# Build docker containers
> docker-compose up -d --build
# Install dependencies
> docker-compose run --rm php-cli composer install
```

### Full installation profile

[](#full-installation-profile)

The full installation profile has a complete working example.

```
> composer create-project robiningelbrecht/php-slim-skeleton:dev-master-with-examples [app-name] --no-install --ignore-platform-reqs --stability=dev
# Build docker containers
> docker-compose up -d --build
# Install dependencies
> docker-compose run --rm php-cli composer install
# Initialize example
> docker-compose run --rm php-cli composer example:init
# Start consuming the voting example queue
> docker-compose run --rm php-cli bin/console app:amqp:consume add-vote-command-queue
```

Some examples
-------------

[](#some-examples)

### Registering a new route

[](#registering-a-new-route)

```
namespace App\Controller;

class UserOverviewRequestHandler
{
    public function __construct(
        private readonly UserOverviewRepository $userOverviewRepository,
    ) {
    }

    public function handle(
        ServerRequestInterface $request,
        ResponseInterface $response): ResponseInterface
    {
        $users = $this->userOverviewRepository->findonyBy(/*...*/);
        $response->getBody()->write(/*...*/);

        return $response;
    }
}
```

Head over to `config/routes.php` and add a route for your RequestHandler:

```
return function (App $app) {
    // Set default route strategy.
    $routeCollector = $app->getRouteCollector();
    $routeCollector->setDefaultInvocationStrategy(new RequestResponseArgs());

    $app->get('/user/overview', UserOverviewRequestHandler::class.':handle');
};
```

[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/request-handlers)

### Console commands

[](#console-commands)

The console application uses the Symfony console component to leverage CLI functionality.

```
#[AsCommand(name: 'app:user:create')]
class CreateUserConsoleCommand extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        // ...
        return Command::SUCCESS;
    }
}
```

[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/console-commands)

### Domain commands and command handlers

[](#domain-commands-and-command-handlers)

The skeleton allows you to use commands and command handlers to perform actions. These 2 always come in pairs, when creating a new command in the write model, a corresponding command handler has to be created as well.

#### Creating a new command

[](#creating-a-new-command)

```
namespace App\Domain\WriteModel\User\CreateUser;

class CreateUser extends DomainCommand
{

}
```

#### Creating the corresponding command handler

[](#creating-the-corresponding-command-handler)

```
namespace App\Domain\WriteModel\User\CreateUser;

#[AsCommandHandler]
class CreateUserCommandHandler implements CommandHandler
{
    public function __construct(
    ) {
    }

    public function handle(DomainCommand $command): void
    {
        assert($command instanceof CreateUser);

        // Do stuff.
    }
}
```

[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/cqrs)

### Eventing

[](#eventing)

The idea of this project is that everything is, or can be, event-driven. Event sourcing is not provided by default.

#### Create a new event

[](#create-a-new-event)

```
class UserWasCreated extends DomainEvent
{
    public function __construct(
        private UserId $userId,
    ) {
    }

    public function getUserId(): UserId
    {
        return $this->userId;
    }
}
```

#### Record the event

[](#record-the-event)

```
class User extends AggregateRoot
{
    private function __construct(
       private UserId $userId,
    ) {
    }

    public static function create(
        UserId $userId,
    ): self {
        $user = new self($userId);
        $user->recordThat(new UserWasCreated($userId));

        return $user;
    }
}
```

#### Publish the event

[](#publish-the-event)

```
class UserRepository extends DbalAggregateRootRepository
{
    public function add(User $user): void
    {
        $this->connection->insert(/*...*/);
        $this->publishEvents($user->getRecordedEvents());
    }
}
```

#### Listen to the event

[](#listen-to-the-event)

```
#[AsEventListener(type: EventListenerType::PROCESS_MANAGER)]
class UserNotificationManager extends ConventionBasedEventListener
{

    public function reactToUserWasCreated(UserWasCreated $event): void
    {
        // Send out some notifications.
    }
}
```

[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/eventing)

### Async processing of commands with RabbitMQ

[](#async-processing-of-commands-with-rabbitmq)

The chosen AMQP implementation for this project is RabbitMQ, but it can be easily switched to for example Amazon's AMQP solution.

#### Registering new queues

[](#registering-new-queues)

```
#[AsEventListener(type: EventListenerType::PROCESS_MANAGER)]
class UserCommandQueue extends CommandQueue
{
}
```

#### Queueing commands

[](#queueing-commands)

```
class YourService
{
    public function __construct(
        private readonly UserCommandQueue $userCommandQueue
    ) {
    }

    public function aMethod(): void
    {
        $this->userCommandQueue->queue(new CreateUser(/*...*/));
    }
}
```

#### Consuming your queue

[](#consuming-your-queue)

```
> docker-compose run --rm php-cli bin/console app:amqp:consume user-command-queue
```

[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/amqp)

### Database migrations

[](#database-migrations)

To manage database migrations, the doctrine/migrations package is used.

```
#[Entity]
class User extends AggregateRoot
{
    private function __construct(
        #[Id, Column(type: 'string', unique: true, nullable: false)]
        private readonly UserId $userId,
        #[Column(type: 'string', nullable: false)]
        private readonly Name $name,
    ) {
    }

    // ...
}
```

You can have Doctrine generate a migration for you by comparing the current state of your database schema to the mapping information that is defined by using the ORM and then execute that migration.

```
> docker-compose run --rm php-cli vendor/bin/doctrine-migrations diff
> docker-compose run --rm php-cli vendor/bin/doctrine-migrations migrate
```

[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/migrations)

### Templating engine

[](#templating-engine)

The template engine of choice for this project is Twig and can be used to render anything HTML related.

#### Create a template

[](#create-a-template)

```
Users

    {% for user in users %}
        {{ user.username|e }}
    {% endfor %}

```

#### Render the template

[](#render-the-template)

```
class UserOverviewRequestHandler
{
    public function __construct(
        private readonly Environment $twig,
    ) {
    }

    public function handle(
        ServerRequestInterface $request,
        ResponseInterface $response): ResponseInterface
    {
        $template = $this->twig->load('users.html.twig');
        $response->getBody()->write($template->render(/*...*/));

        return $response;
    }
}
```

[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/templating)

Documentation
-------------

[](#documentation)

Learn more at these links:

- [Skeleton Documentation](https://php-slim-skeleton.robiningelbrecht.be/)
- [Slim framework](https://www.slimframework.com)
- [PHP-DI](https://php-di.org/)
- [Symfony Console Commands](https://symfony.com/doc/current/console.html)
- [Doctrine migrations](https://www.doctrine-project.org/projects/doctrine-migrations/en/3.6/)
- [Twig](https://twig.symfony.com/)

Projects using this skeleton
----------------------------

[](#projects-using-this-skeleton)

- [Unofficial World Cube Association (WCA) Public API](https://github.com/robiningelbrecht/wca-rest-api)
- [Database of newly generated Pokemon cards using GPT and Stable Diffusion](https://github.com/robiningelbrecht/gotta-generate-em-all)
- [A PHP app that generates Pokemon cards by using GPT and Stable Diffusion](https://github.com/robiningelbrecht/pokemon-card-generator)
- [Generate Full 3D pictures of a Rubiks cube](https://github.com/robiningelbrecht/puzzle-generator)

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](https://php-slim-skeleton.robiningelbrecht.be/contribute) for details.

###  Health Score

20

—

LowBetter than 13% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity21

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity24

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/203894?v=4)[Robin Ingelbrecht](/maintainers/robiningelbrecht)[@robiningelbrecht](https://github.com/robiningelbrecht)

---

Top Contributors

[![robiningelbrecht](https://avatars.githubusercontent.com/u/203894?v=4)](https://github.com/robiningelbrecht "robiningelbrecht (151 commits)")

---

Tags

amqpcqrsdddslim-frameworkslim4

### Embed Badge

![Health badge](/badges/robiningelbrecht-php-slim-skeleton/health.svg)

```
[![Health](https://phpackages.com/badges/robiningelbrecht-php-slim-skeleton/health.svg)](https://phpackages.com/packages/robiningelbrecht-php-slim-skeleton)
```

###  Alternatives

[laravel/socialite

Laravel wrapper around OAuth 1 &amp; OAuth 2 libraries.

5.7k104.3M829](/packages/laravel-socialite)[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k38.6M289](/packages/laravel-dusk)[pinguo/php-msf

Pinguo Micro Service Framework For PHP

1.7k4.2k](/packages/pinguo-php-msf)[nineinchnick/edatatables

Grid widget for the Yii Framework, wrapper for the DataTables jQuery plugin

173.2k](/packages/nineinchnick-edatatables)[link-cloud/fast-hyperf

LinkCloud Fast Hyperf

241.2k1](/packages/link-cloud-fast-hyperf)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
