{"id":20613224,"url":"https://github.com/robiningelbrecht/php-slim-skeleton","last_synced_at":"2025-12-12T19:59:38.521Z","repository":{"id":50490644,"uuid":"519100735","full_name":"robiningelbrecht/php-slim-skeleton","owner":"robiningelbrecht","description":"An event-driven Slim 4 Framework skeleton using AMQP and CQRS","archived":false,"fork":false,"pushed_at":"2023-08-29T13:12:05.000Z","size":4307,"stargazers_count":45,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-15T07:13:36.269Z","etag":null,"topics":["amqp","cqrs","ddd","slim-framework","slim4"],"latest_commit_sha":null,"homepage":"https://php-slim-skeleton.robiningelbrecht.be/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robiningelbrecht.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-07-29T06:11:21.000Z","updated_at":"2025-04-12T15:12:29.000Z","dependencies_parsed_at":"2025-04-15T07:10:48.564Z","dependency_job_id":"c431b244-b417-4a94-8498-48169d3e850f","html_url":"https://github.com/robiningelbrecht/php-slim-skeleton","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/robiningelbrecht/php-slim-skeleton","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robiningelbrecht%2Fphp-slim-skeleton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robiningelbrecht%2Fphp-slim-skeleton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robiningelbrecht%2Fphp-slim-skeleton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robiningelbrecht%2Fphp-slim-skeleton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robiningelbrecht","download_url":"https://codeload.github.com/robiningelbrecht/php-slim-skeleton/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robiningelbrecht%2Fphp-slim-skeleton/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27690472,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-12T02:00:06.775Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amqp","cqrs","ddd","slim-framework","slim4"],"created_at":"2024-11-16T11:09:10.075Z","updated_at":"2025-12-12T19:59:38.503Z","avatar_url":"https://github.com/robiningelbrecht.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eEvent-driven Slim 4 Framework skeleton\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"https://github.com/robiningelbrecht/slim-skeleton-ddd-amqp/raw/master/readme/slim-new.webp\" alt=\"Slim\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/robiningelbrecht/slim-skeleton-ddd-amqp/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/robiningelbrecht/slim-skeleton-ddd-amqp/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n\u003ca href=\"https://codecov.io/gh/robiningelbrecht/php-slim-skeleton\" \u003e\u003cimg src=\"https://codecov.io/gh/robiningelbrecht/php-slim-skeleton/branch/master/graph/badge.svg?token=hgnlFWvWvw\" alt=\"Codecov.io\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/robiningelbrecht/slim-skeleton-ddd-amqp/blob/master/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/robiningelbrecht/slim-skeleton-ddd-amqp?color=428f7e\u0026logo=open%20source%20initiative\u0026logoColor=white\" alt=\"License\"\u003e\u003c/a\u003e\n\u003ca href=\"https://phpstan.org/\"\u003e\u003cimg src=\"https://img.shields.io/badge/PHPStan-level%208-succes.svg?logo=php\u0026logoColor=white\u0026color=31C652\" alt=\"PHPStan Enabled\"\u003e\u003c/a\u003e\n\u003ca href=\"https://php.net/\"\u003e\u003cimg src=\"https://img.shields.io/packagist/php-v/robiningelbrecht/php-slim-skeleton/dev-master?color=%23777bb3\u0026logo=php\u0026logoColor=white\" alt=\"PHP\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n\u003cp align=\"center\"\u003e\n    An event-driven Slim 4 Framework skeleton using AMQP and CQRS\n\u003c/p\u003e\n\n## Installation\n\n### Default installation profile\n\nThe 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.\n\n```bash\n\u003e composer create-project robiningelbrecht/php-slim-skeleton [app-name] --no-install --ignore-platform-reqs --stability=dev\n# Build docker containers\n\u003e docker-compose up -d --build\n# Install dependencies\n\u003e docker-compose run --rm php-cli composer install\n```\n\n### Full installation profile\n\nThe full installation profile has a complete working example.\n\n```bash\n\u003e composer create-project robiningelbrecht/php-slim-skeleton:dev-master-with-examples [app-name] --no-install --ignore-platform-reqs --stability=dev\n# Build docker containers\n\u003e docker-compose up -d --build\n# Install dependencies\n\u003e docker-compose run --rm php-cli composer install\n# Initialize example\n\u003e docker-compose run --rm php-cli composer example:init\n# Start consuming the voting example queue\n\u003e docker-compose run --rm php-cli bin/console app:amqp:consume add-vote-command-queue\n```\n\n## Some examples\n\n### Registering a new route\n\n```php\nnamespace App\\Controller;\n\nclass UserOverviewRequestHandler\n{\n    public function __construct(\n        private readonly UserOverviewRepository $userOverviewRepository,\n    ) {\n    }\n\n    public function handle(\n        ServerRequestInterface $request,\n        ResponseInterface $response): ResponseInterface\n    {\n        $users = $this-\u003euserOverviewRepository-\u003efindonyBy(/*...*/);\n        $response-\u003egetBody()-\u003ewrite(/*...*/);\n\n        return $response;\n    }\n}\n```\n\nHead over to `config/routes.php` and add a route for your RequestHandler:\n\n```php\nreturn function (App $app) {\n    // Set default route strategy.\n    $routeCollector = $app-\u003egetRouteCollector();\n    $routeCollector-\u003esetDefaultInvocationStrategy(new RequestResponseArgs());\n    \n    $app-\u003eget('/user/overview', UserOverviewRequestHandler::class.':handle');\n};\n```\n[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/request-handlers)\n\n### Console commands\n\nThe console application uses the Symfony console component to leverage CLI functionality.\n\n```php\n#[AsCommand(name: 'app:user:create')]\nclass CreateUserConsoleCommand extends Command\n{\n    protected function execute(InputInterface $input, OutputInterface $output): int\n    {\n        // ...\n        return Command::SUCCESS;\n    }\n}\n```\n\n[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/console-commands)\n\n### Domain commands and command handlers\n\nThe skeleton allows you to use commands and command handlers to perform actions. \nThese 2 always come in pairs, when creating a new command in the write model, a corresponding command handler has to be created as well.\n\n#### Creating a new command\n\n```php\nnamespace App\\Domain\\WriteModel\\User\\CreateUser;\n\nclass CreateUser extends DomainCommand\n{\n \n}\n```\n\n#### Creating the corresponding command handler\n\n```php\nnamespace App\\Domain\\WriteModel\\User\\CreateUser;\n\n#[AsCommandHandler]\nclass CreateUserCommandHandler implements CommandHandler\n{\n    public function __construct(\n    ) {\n    }\n\n    public function handle(DomainCommand $command): void\n    {\n        assert($command instanceof CreateUser);\n\n        // Do stuff.\n    }\n}\n```\n\n[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/cqrs)\n\n### Eventing\n\nThe idea of this project is that everything is, or can be, event-driven. Event sourcing is not provided by default.\n\n#### Create a new event\n\n```php\nclass UserWasCreated extends DomainEvent\n{\n    public function __construct(\n        private UserId $userId,\n    ) {\n    }\n\n    public function getUserId(): UserId\n    {\n        return $this-\u003euserId;\n    }\n}\n```\n\n#### Record the event\n\n```php\nclass User extends AggregateRoot\n{\n    private function __construct(\n       private UserId $userId,\n    ) {\n    }\n\n    public static function create(\n        UserId $userId,\n    ): self {\n        $user = new self($userId);\n        $user-\u003erecordThat(new UserWasCreated($userId));\n\n        return $user;\n    }\n}\n```\n\n#### Publish the event\n\n```php\nclass UserRepository extends DbalAggregateRootRepository\n{\n    public function add(User $user): void\n    {\n        $this-\u003econnection-\u003einsert(/*...*/);\n        $this-\u003epublishEvents($user-\u003egetRecordedEvents());\n    }\n}\n```\n\n#### Listen to the event\n\n```php\n#[AsEventListener(type: EventListenerType::PROCESS_MANAGER)]\nclass UserNotificationManager extends ConventionBasedEventListener\n{\n   \n    public function reactToUserWasCreated(UserWasCreated $event): void\n    {\n        // Send out some notifications.\n    }\n}\n```\n\n[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/eventing)\n\n### Async processing of commands with RabbitMQ\n\nThe chosen AMQP implementation for this project is RabbitMQ, but it can be easily switched to for example Amazon's AMQP solution.\n\n#### Registering new queues\n\n```php\n#[AsEventListener(type: EventListenerType::PROCESS_MANAGER)]\nclass UserCommandQueue extends CommandQueue\n{\n}\n```\n\n#### Queueing commands\n\n```php\nclass YourService\n{\n    public function __construct(\n        private readonly UserCommandQueue $userCommandQueue\n    ) {\n    }\n\n    public function aMethod(): void\n    {\n        $this-\u003euserCommandQueue-\u003equeue(new CreateUser(/*...*/));\n    }\n}\n```\n\n#### Consuming your queue\n\n```bash\n\u003e docker-compose run --rm php-cli bin/console app:amqp:consume user-command-queue\n```\n\n[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/amqp)\n\n### Database migrations\n\nTo manage database migrations, the doctrine/migrations package is used.\n\n```php\n#[Entity]\nclass User extends AggregateRoot\n{\n    private function __construct(\n        #[Id, Column(type: 'string', unique: true, nullable: false)]\n        private readonly UserId $userId,\n        #[Column(type: 'string', nullable: false)]\n        private readonly Name $name,\n    ) {\n    }\n\n    // ...\n}\n```\n\nYou can have Doctrine generate a migration for you by comparing the current state of your database schema \nto the mapping information that is defined by using the ORM and then execute that migration.\n\n```bash\n\u003e docker-compose run --rm php-cli vendor/bin/doctrine-migrations diff\n\u003e docker-compose run --rm php-cli vendor/bin/doctrine-migrations migrate\n```\n\n[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/migrations)\n\n### Templating engine\n\nThe template engine of choice for this project is Twig and can be used to render anything HTML related.\n\n#### Create a template\n\n```twig\n\u003ch1\u003eUsers\u003c/h1\u003e\n\u003cul\u003e\n    {% for user in users %}\n        \u003cli\u003e{{ user.username|e }}\u003c/li\u003e\n    {% endfor %}\n\u003c/ul\u003e\n```\n#### Render the template\n\n```php\nclass UserOverviewRequestHandler\n{\n    public function __construct(\n        private readonly Environment $twig,\n    ) {\n    }\n\n    public function handle(\n        ServerRequestInterface $request,\n        ResponseInterface $response): ResponseInterface\n    {\n        $template = $this-\u003etwig-\u003eload('users.html.twig');\n        $response-\u003egetBody()-\u003ewrite($template-\u003erender(/*...*/));\n\n        return $response;\n    }\n}\n```\n\n[Full documentation](https://php-slim-skeleton.robiningelbrecht.be/development-guide/templating)\n\n## Documentation\n\nLearn more at these links:\n\n- [Skeleton Documentation](https://php-slim-skeleton.robiningelbrecht.be/)\n- [Slim framework](https://www.slimframework.com)\n- [PHP-DI](https://php-di.org/)\n- [Symfony Console Commands](https://symfony.com/doc/current/console.html)\n- [Doctrine migrations](https://www.doctrine-project.org/projects/doctrine-migrations/en/3.6/)\n- [Twig](https://twig.symfony.com/)\n\n## Projects using this skeleton\n\n- [Unofficial World Cube Association (WCA) Public API](https://github.com/robiningelbrecht/wca-rest-api)\n- [Database of newly generated Pokemon cards using GPT and Stable Diffusion](https://github.com/robiningelbrecht/gotta-generate-em-all)\n- [A PHP app that generates Pokemon cards by using GPT and Stable Diffusion](https://github.com/robiningelbrecht/pokemon-card-generator)\n- [Generate Full 3D pictures of a Rubiks cube](https://github.com/robiningelbrecht/puzzle-generator)\n\n## Contributing\n\nPlease see [CONTRIBUTING](https://php-slim-skeleton.robiningelbrecht.be/contribute) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobiningelbrecht%2Fphp-slim-skeleton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobiningelbrecht%2Fphp-slim-skeleton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobiningelbrecht%2Fphp-slim-skeleton/lists"}