103 lines
3.3 KiB
Markdown
103 lines
3.3 KiB
Markdown
# 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.
|
|
}
|
|
```
|