{"id":30716975,"url":"https://github.com/dlzer/php-slim-4-api-boilerplate","last_synced_at":"2025-09-03T08:30:01.674Z","repository":{"id":38110420,"uuid":"248314026","full_name":"DLzer/php-slim-4-api-boilerplate","owner":"DLzer","description":"Slim 4 Example Application","archived":false,"fork":false,"pushed_at":"2023-02-17T16:39:57.000Z","size":320,"stargazers_count":0,"open_issues_count":4,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-03-05T21:03:29.496Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DLzer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-18T18:39:21.000Z","updated_at":"2022-08-19T14:31:52.000Z","dependencies_parsed_at":"2023-02-14T10:00:33.584Z","dependency_job_id":null,"html_url":"https://github.com/DLzer/php-slim-4-api-boilerplate","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"purl":"pkg:github/DLzer/php-slim-4-api-boilerplate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DLzer%2Fphp-slim-4-api-boilerplate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DLzer%2Fphp-slim-4-api-boilerplate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DLzer%2Fphp-slim-4-api-boilerplate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DLzer%2Fphp-slim-4-api-boilerplate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DLzer","download_url":"https://codeload.github.com/DLzer/php-slim-4-api-boilerplate/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DLzer%2Fphp-slim-4-api-boilerplate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273413547,"owners_count":25101223,"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-09-03T02:00:09.631Z","response_time":76,"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":[],"created_at":"2025-09-03T08:29:56.680Z","updated_at":"2025-09-03T08:30:01.653Z","avatar_url":"https://github.com/DLzer.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PHP Slim 4 Skeleton\n\n[![CI](https://github.com/DLzer/slim4skeleton/actions/workflows/ci.yml/badge.svg)](https://github.com/DLzer/slim4skeleton/actions/workflows/ci.yml)[![CI-coverage](https://github.com/DLzer/slim4skeleton/actions/workflows/ci-coverage.yml/badge.svg?branch=master)](https://github.com/DLzer/slim4skeleton/actions/workflows/ci-coverage.yml)\n\nUsing the [Slim 4](https://www.slimframework.com/docs/v4/) framework\n\n## Requirements\n* PHP 7.4+ or 8.0+\n\n## Table of contents\n* [Dependencies](#dependencies)\n* [Installation](#installation)\n    * [Installing with Docker](#setup-with-docker)\n    * [Insatlling without Docker](#setup-without-docker)\n* [App Environment](#app-environment)\n* [External Documentation](#external-documentation)\n* [Database Migrations](#database-migrations)\n* [App](#app-entry-point)\n    * [App Instance](#app-instance)\n    * [Container](#container-dependencies-and-services)\n    * [App Lifecycle](#request-response-cycle)\n    * [Routes](#routes)\n    * [Actions](#actions)\n    * [Domains](#domains)\n* [Security](#cors)\n    * [CORS](#cors)\n    * [JWT](#jwt)\n* [Testing](#testing)\n\n## Dependencies \n\n**List of Dependencies**\n- [Slim 4](https://github.com/slimphp/Slim) as the core framework \n- [nyholm/psr7](https://github.com/Nyholm/psr7) for the PSR-7 implementation \n- [php-di/php-di](http://php-di.org/) to manage dependency injection    \n- [tuupola/slim-jwt-auth](https://appelsiini.net/projects/slim-jwt-auth/) To manage the api authentication using JWT.\n- [vlucas/phpdotenv](https://github.com/vlucas/phpdotenv) To load environment variables from `.env` file.\n- [selective](https://github.com/selective-php) We use multiple packages from selective for testing, validating, and hydrating.\n- [phpunit/phpunit](https://phpunit.de/) for testing.\n- [Monolog](https://github.com/Seldaek/monolog) for logging   \n- [Phinx](https://phinx.org/) for database migrations  \n- [Selective/Config](https://github.com/selective-php/config) to manage config settings  \n- [Slim/Twig-View](https://github.com/slimphp/Twig-View) for templates  \n\n## Installation\n\nStart by cloning the repository\n\n```bash\ngit clone https://github.com/DLzer/php-slim-4-api-boilerplate.git\n```\n\nCreate a `.env` file and set your environment variables\n\n```bash\ncp .env-example .env\n```\n\n## Setup with Docker\n\n```bash\n$ docker-compose build\n$ docker-compose-up -d # -d to run in daemon mode\n$ composer migrate # Run the database migrations\n$ composer seed # Insert seed data into the database\n```\n\n## Setup without Docker\n\n\u003e To install for production run composer install with the --no-dev option\n```bash\n$ composer install           # install all dependenciess\n$ composer migrate           # import database\n$ composer seed              # insert seed data\n$ composer test              # test the build\n```\n \n## App Environment\n\nAll environment variables are stored in the `.env` file. When the application is bootstrapped the settings and container will load the variables into their respective locations. The global environment for the app is under the `App` namespace.\n\n## External Documentation\n\nThe app follows the structure of [Slim skeleton application](https://github.com/slimphp/Slim-Skeleton) with minor changes.\nThe skeleton is a good starting point when developing with Slim framework.\nA detailed overview of the directory structure can be found at [this page](docs/directory.md).  \n\nThe api is designed according to the [RealWorld](https://github.com/gothinkster/realworld-example-apps) specifications. \nMake sure to familiarized yourself with all endpoints specified in the [Full API Spec](https://github.com/gothinkster/realworld/tree/master/api)\n\n## Database Migrations\n\n***Schema***\n\nThe schema is generated using the tool [Phinx Migrations Generator](https://github.com/odan/phinx-migrations-generator). This utility will generate a new schema if one does not exist. Otherwise it will run a comparison against the existing schema and modify with any changes.\n\nTo run the utility:\n```bash\n$ composer generate-migration\n```\n\n***Migrations***\n\nMigrations are a way of describing the table structure for the application, and also provide an easy interface for creating tables, tracking changes, and rolling back changes.\n\nThe app database migrations can be found in the [migration directory](database/migrations).\nMigrations are performed using [Phinx](https://phinx.org/).\n\nTo run the migrations:\n```bash\n$ composer migrate\n```\n\n***Seeds***\n\nSeeds are mock data that we can use to inject into the database tables. The seed files can be found in the [seeds directory](database/seeds)\n\nTo run the seeds:\n```bash\n$ composer seed\n```\n\n## App Entry Point:\nThe server will direct all requests to [index.php](public/index.php). \nThere, we boot the app by creating an instance of Slim\\App and with the container established.\n\n## The App Instance\nThe instance of Slim\\App (`$app`) holds the app settings, routes, and dependencies.\n\nWe register routes and methods by calling methods on the `$app` instance. \n\nMore importantly, the `$app` instance has the `Container` which registers the app dependencies to be passed later to the controllers.\n\n## Container Dependencies and Services\nIn different parts of the application we need to use other classes and services. These classes and services also depends on other classes.\nManaging these dependencies becomes easier when we have a container to hold them. Basically, we configure these classes and store them in the container.\nLater, when we need a service or a class we ask the container, and it will instantiate the class based on our configuration and return it.\n\nThe container is configured in the `container.php`.\nWe start be retrieving the container from the `$app` instance and configure the required services: \n\n```php\n    Configuration::class =\u003e function() {\n        return new Configuration(require __DIR__ . '/settings.php');\n    },\n    DatabaseFactory::class =\u003e function (ContainerInterface $container) {\n        return new DatabaseFactory($container-\u003eget(Configuration::class)-\u003egetArray('db'));\n    },\n```\n\nThe above code registers a configured instance of the `DatabaseFactory` in the container. Later we can ask for the `DatabaseFactory` using autowiring and dependency injection.\n\n```php\n    final class SomeService\n    {\n        private DatabaseFactory $db;\n\n        public function __construct(DatabaseFactory $connection)\n        {\n            $this-\u003edb = $connection;\n        }\n\n        public function get(int $ID): object\n        {\n            $this-\u003edb-\u003equery(\"...\");\n            return $this-\u003edb-\u003esingle(true);\n        }\n    }\n```\n\n## Request-Response Cycle\nAll requests go through the same cycle:  \n`routing \u003e middleware \u003e conroller \u003e response`\n\n## Routes:\n\u003e Check the list of endpoints defined by the [RealWorld API Spec](https://github.com/gothinkster/realworld/tree/master/api#endpoints)\n\nAll the app routes are defined in the [routes.php](src/routes.php) file.\n\nThe Slim `$app` variable is responsible for registering the routes. \nYou will notice that all routes are enclosed in the `group` method which gives the prefix api to all routes: `http::/localhost/api`. Any groups need to utilize the `RouterCollectorProxy` so no routes are overwritten.\n\nEvery route is defined by a method corresponds to the HTTP verb. For example, a post request to register a user is defined by:\n```php\n    $app-\u003epost('/member', \\App\\Controllers\\Member\\MemberController:get')-\u003esetName('member.get');\n``` \nThe method, `post()`, defines `/api/member` endpoint and direct the request to method `register` on `MemberController` class.\n\n## Actions\nAfter passing through all assigned middleware, the request will be processed by a action.\n\nThe action's job is to validate the request data, check for authorization, process the request by calling a domain service or do other jobs, \nand eventually return a response in the form of JSON response. \n\n## Domains\n\nDomains store the separated namespaces for the business logic section of the application. Domains will contain Data Types, Services, Repositories, and any helpers relative to the specific domain.\n\nFor example, we'll take the *User* Domain locatied [here](src/Domain/User). The User domain contains:\n- `UserData` Which is the described model type for an individual user.\n- `UserRepository` Which is the storage/retrieval layer for sending and requesting `UserData`.\n- `User{Action}Service` The services are the primary business logic section for manipulating data.\n- `UserRoleType` Which is a set of constants describing the available roles a user can have.\n\nWe separate the services into specific tasks for better control, and less overflow.\n\n## CORS\n[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) is used when the request is coming from a different host.\nBy default, web browsers will prevent such requests.\nThe browser will start by sending an `OPTION` request to the server to get the approval and then send the actual request.\n\nTherefor, we handle cross-origin HTTP requests by making two changes to our app:\n- Allow `OPTIONS` requests.  \n- Return the approval in the response. \n\nThis is done in the by adding two middleware in the [middleware.php](https://github.com/alhoqbani/slim-php-realworld-example-app/blob/b852c69e40271054b5fa9ccbf36667807b71f286/src/middleware.php) file\nThe first middleware will add the required headers for CORS approval.\nAnd the second, deals with issue of redirect when the route ends with a slash.\n\nFor more information check Slim documentations:\n- [Setting up CORS](https://www.slimframework.com/docs/cookbook/enable-cors.html)\n- [Trailing / in route patterns](https://www.slimframework.com/docs/cookbook/route-patterns.html)\n\n## JWT\n\nJWT's are generated using the [Firebase JWT](https://github.com/firebase/php-jwt) package. When a user is authenticated a new JWT is generated with only relative data to retreiving the user information. We don't pack to much into the JWT in order to follow the general rule of *Only pack what you're willing to lose*. Meaning if we were to send the entire user profile we would be storing personally-identifiable information on the client, which is a huge no-no.\n\n## Testing\n\nTests are found in the `tests` directory and follow the same namespace convention as the application. We use the `AppTestTrait` to extend the test suite with our own mock routing, database setup, and HTTP Requests.\n\nTests are run using *PHP-Unit 9.5*\n\nRunning the tests:\n\n```bash\n$ composer test\n```\n\nRunning the tests with the coverage module:\n\n```bash\n$ composer test:coverage\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdlzer%2Fphp-slim-4-api-boilerplate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdlzer%2Fphp-slim-4-api-boilerplate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdlzer%2Fphp-slim-4-api-boilerplate/lists"}