# Development Guidelines This document outlines the development workflow and guidelines for the Drinks Inventory System. ## Development Environment Setup ### Requirements - PHP 8.4 or higher - Composer - SQLite - Git ### General - Use classes for entities, repositories, services and controllers - Use Doctrine ORM for database interactions - Use twig for templates - Register services in the container and use dependency injection - Write unit as well as feature tests - Always use DateTimeImmutable unless there is a good reason not to - Leverage modern php features such as enums, property promotion, and property hooks ### PHP Constructor Property Promotion and Readonly Properties - Use constructor property promotion for all properties that are initialized in the constructor - Use readonly properties for properties that should not be modified after initialization - Only use readonly for properties that don't have setter methods - Example: ```php class Example { private ?int $id = null; public function __construct( private string $name, private readonly DateTimeImmutable $createdAt = new DateTimeImmutable(), private DateTimeImmutable $updatedAt = new DateTimeImmutable() ) { } // Getter for readonly property public function getCreatedAt(): DateTimeImmutable { return $this->createdAt; } // Getter and setter for non-readonly property public function getName(): string { return $this->name; } public function setName(string $name): self { $this->name = $name; $this->updateTimestamp(); return $this; } private function updateTimestamp(): void { $this->updatedAt = new DateTimeImmutable(); } } ### Doctrine ORM Guidelines - Use PHP 8 attributes for entity mapping (not annotations or XML) - Place all entity classes in the `src/Entity` directory - Place all repository classes in the `src/Repository` directory - Use the naming convention `EntityNameRepository` for repository classes - Define relationships between entities using appropriate Doctrine annotations (`OneToMany`, `ManyToOne`, etc.) - Use `readonly` for properties that should not change after entity creation (like `createdAt`) - Always include `created_at` and `updated_at` fields in all entities - Implement an `updateTimestamp()` method to update the `updated_at` field when an entity is modified - Use the repository pattern for database operations, not direct entity manager operations in services - Define custom finder methods in repository classes for specific query needs - Use Doctrine's query builder for complex queries - Always validate entity data before persisting to the database Example entity with Doctrine attributes: ```php #[ORM\Entity(repositoryClass: ExampleRepository::class)] #[ORM\Table(name: 'example')] class Example { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private ?int $id = null; #[ORM\Column(type: 'string', length: 255)] private string $name; #[ORM\Column(type: 'datetime_immutable')] private readonly DateTimeImmutable $createdAt; #[ORM\Column(type: 'datetime_immutable')] private DateTimeImmutable $updatedAt; // Constructor, getters, setters, etc. } ```