A backend service built as part of a microservice architecture that contains task management business logic.
- Environment in Docker
- Command Bus, Event Bus
- Event Store
- Read Model
- Async Event subscribers
- PHP 8.4
- PostgreSQL 17
- Docker
The Task Tracker service follows a clean architecture pattern with a multi-layered approach that provides clear separation of responsibilities.
- Responsibility: Handle HTTP requests, format responses, validate input data
- Components:
- Controllers for commands (task creation, status updates, assignments)
- Controllers for queries (retrieving tasks and users)
- Responsibility: Coordinate business logic execution, translate requests and responses
- Components:
- Command Handlers (process domain commands)
- Query Handlers (retrieve and format data)
- DTOs (data transfer objects for API interaction)
- Projectors (update read models based on events)
- Responsibility: Contains business logic and domain rules
- Components:
- Entities (TaskEntity, UserEntity)
- Value Objects (Task, User, Status, etc.)
- Repository Interfaces
- Domain Events (TaskCreatedEvent, TaskAssignedEvent, etc.)
- Commands and Queries
- Responsibility: Implement interactions with external systems (DB, messaging)
- Components:
- Repository Implementations
- Data Mappers
- Storage implementations
- Migrations
HTTP Request → Controller → Command/Query Bus → Handler → Repository → Entity/Read Model → Database
↓
Event Bus → Projector → Read Model Storage
-
Command Pattern / CQRS
- Separation of operations into commands and queries
- Allows for optimizing read and write operations independently
-
Repository Pattern
- Abstracts data access with interfaces
- Hides storage implementation details
-
Factory Pattern
- Creates complex objects consistently
- Used for commands, queries, entities, and read models
-
DTO Pattern
- Simplifies data transfer between layers
- Provides a clear API contract
-
Event Sourcing
- Uses events as the source of truth
- Enables rebuilding state and audit capabilities
-
Value Objects
- Encapsulates domain concepts (Title, Description, Status)
- Ensures immutability and validation
-
Projection Pattern
- Creates optimized read models from events
- Improves query performance
The service implements a comprehensive API versioning approach:
-
URL-based versioning:
- All API endpoints are prefixed with the version:
/api/v1/...or/api/v2/... - This ensures clear separation between API versions
- All API endpoints are prefixed with the version:
-
Feature differences between versions:
- V1: Base functionality (create/read/update tasks and users)
- V2: Enhanced features (priorities, due dates, advanced filtering, improved response format with HATEOAS)
-
Version-specific documentation:
- Each API version has its own documentation endpoint
- V1:
/api/v1/doc - V2:
/api/v2/doc - Latest version:
/api/doc
For backward compatibility, we maintain support for both versions.
├── .docker/ # Docker configuration files
├── bootstrap/ # Application bootstrap files
├── config/ # Configuration files and services
│ ├── domains/ # Domain-specific configurations
│ ├── packages/ # Package configurations
│ └── services/ # Service definitions
├── public/ # Public entry point
├── src/ # Application source code
│ ├── Kernel.php # Application kernel
│ └── Task/ # Task domain
│ ├── Application/ # Application layer components
│ │ ├── CommandHandler/
│ │ ├── Dto/
│ │ ├── Factory/
│ │ ├── Processor/
│ │ ├── Projector/
│ │ ├── QueryHandler/
│ │ └── Saga/
│ ├── Domain/ # Domain layer components
│ │ ├── Command/
│ │ ├── Entity/
│ │ ├── Event/
│ │ ├── Factory/
│ │ ├── Query/
│ │ ├── ReadModel/
│ │ ├── Repository/
│ │ └── ValueObject/
│ ├── Infrastructure/ # Infrastructure layer components
│ │ ├── Migrations/
│ │ ├── Repository/
│ │ └── Service/
│ └── Presentation/ # Presentation layer components
│ ├── Cli/
│ └── Rest/
│ ├── V1/ # API Version 1 controllers
│ └── V2/ # API Version 2 controllers
└── tests/ # Test files
The architecture supports future extensions:
- Create new entities and value objects for comments
- Define commands, events, and handlers for comment operations
- Extend API controllers and create appropriate repositories
- Extend the user entity with role information
- Implement access control mechanisms
- Update APIs to consider roles during operations
The architecture already supports this through:
- Repository abstractions with interfaces
- Ready-to-use DBAL configurations and migrations
- Switching from in-memory to persistent storage requires minimal changes
Get documentation in Swagger format (open in browser):
http://localhost/api/doc/
Get documentation for a specific API version:
http://localhost/api/v1/doc/ (API v1)
http://localhost/api/v2/doc/ (API v2)
Get documentation in a user-friendly format (open in browser):
http://localhost/api/docs/
Get API documentation in JSON format:
http://localhost/api/doc.json
Get API documentation in YAML format:
http://localhost/api/doc.yaml
Create a task:
curl --location --request POST 'http://localhost/api/v1/tasks' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--form 'title="task 1"' \
--form 'description="task description 1"' \
--form 'status="todo"'Update task status:
curl --location --request PUT 'http://localhost/api/v1/tasks/{uuid}/status' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data '{
"status": "in_progress"
}'Assign task to user:
curl --location --request PUT 'http://localhost/api/v1/tasks/{uuid}/assign' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data '{
"assigneeId": "{userUuid}"
}'Get all tasks:
curl --location 'http://localhost/api/v1/tasks'Get task by ID:
curl --location 'http://localhost/api/v1/tasks/{uuid}'Get tasks with filters:
curl --location 'http://localhost/api/v1/tasks?assigneeId=1f01bca9-7e99-68ae-a1c2-decba94b787f&status=todo'Create a user:
curl --location --request POST 'http://localhost/api/v1/users' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--form 'name=\"user 1\"' \
--form 'email=\"user1@email.com\"'Get users with filters:
curl --location 'http://localhost/api/v1/users?name=user%201&email=user1@email.com'Up new environment:
make installSee all make commands:
make helpEnter in PHP container:
make php-shellWatch containers logs:
make logs