Bootstrapping.
composer create-project symfony/skeleton:"7.0.*" symfony-api-test
# install dev dependencies
composer require --dev doctrine/doctrine-fixtures-bundle phpunit/phpunit symfony/browser-kit symfony/css-selector symfony/debug-bundle symfony/maker-bundle symfony/phpunit-bridge symfony/stopwatch symfony/web-profiler-bundle zenstruck/foundry
# add doctrine migrations
composer require doctrine/doctrine-migrations-bundle
# add symfony messenger for async
composer require symfony/messenger symfony/doctrine-messenger
# add security recipe
composer require security
# add UUID for public IDs
composer require symfony/uid
# add JWT Auth
composer require lexik/jwt-authentication-bundle
# add Nelmio Docs
composer require nelmio/api-doc-bundle
phpstan analyse -l 8 src/
12/12 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
[OK] No errors
# Run the application on Docker ([http://localhost](localhost))
docker compose up
# fixtures
php bin/console doctrine:fixtures:load --no-interaction
src/
├── Controller
│ ├── UserAdminController.php
│ └── UserController.php
├── DataFixtures
│ └── AppFixtures.php
├── Entity
│ ├── Trait
│ └── User.php
├── Error
│ └── Normalizer.php
├── Factory
│ └── UserFactory.php
├── Kernel.php
├── Repository
│ └── UserRepository.php
├── Response
│ └── UserResponse.php
└── Service
└── UserService.php
For Authentication I'm used lexik/jwt-authentication-bundle
which also provides the login route /api/login_check
.
Users are created with different roles using fixtures and will be created during container launch.
I've decided to differentiate admin
routes to user
routes, so access control are simplified.
I've added Nelmio Docs, mapped only one response as an example: http://localhost/api/doc.json
{
"data": {
"id": "b0393b4c-d213-40fa-8a7c-ab30f5a3eb99",
"email": "sjunior.admin@gmail.com",
"roles": [
"ROLE_ADMIN",
"ROLE_USER"
]
}
}
# run migration for test environment
docker compose exec app-default php bin/console --env=test do:mi:mi
# run phpunit
docker compose exec app-default php vendor/bin/phpunit
# run any other command
docker compose exec app-default <command>
# log into the container
docker compose exec app-default /bin/sh
Host: 127.0.0.1
Port: 3306
Database: app_core_db
User: app_admin
Pass: 1cgMx56faAD8v2343Adf433x1ppW
- Filters
- Pagination
- Easy extensibility (add new endpoints)
- Normalization of Response Codes
- Normalization of Validations Errors
- Required
- Exists
- Types
- Nelmio Configuration and Mapping (OpenAPI Specs)
- Global Error Handling
- Database optmization - queries
- Cache
- Tests
- Logs
- Montitoring / Observability
POST http://localhost/api/login_check
curl -X POST http://localhost/api/login_check \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"email": "sjunior.admin@gmail.com", "password": "test123"}'
GET http://localhost/api/admin/v1/users
curl -X GET http://localhost/api/admin/v1/users \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token_from_previous_request>"
Response
{
"data": [
{
"id": "27e21e47-9256-4e57-aa4c-aa33f6da7b97",
"email": "sjunior.admin@gmail.com",
"roles": [
"ROLE_ADMIN",
"ROLE_USER"
]
},
{
"id": "e975d5ed-dcf8-4fe8-8f52-d8384bc2558a",
"email": "sjunior.user@gmail.com",
"roles": [
"ROLE_USER"
]
}
]
}
From here is just change the ENDPOINT and METHOD and you can test all All Endpoints: Host: http://localhost
Method | Endpoint | Description | Role |
---|---|---|---|
POST | /api/login_check | Login | User |
GET | /api/admin/v1/users | List Users | Admin |
POST | /api/admin/v1/<:id>/user | Create User | Admin |
GET | /api/admin/v1/<:id>/user | Read User | Admin |
PUT | /api/admin/v1/<:id>/user | Update User | Admin |
DELETE | /api/admin/v1/<:id>/user | Delete User | Admin |
GET | /api/v1/user | Read User | User |
POST | /api/v1/user | Update User | User |
Add it here Configuration files are:
- user-admin.http
- user.http