feat(person): initial Person domain with entity, model and DTO
PHP Unit Tests / test (push) Has been cancelled
PHP Unit Tests / test (push) Has been cancelled
- Add PersonEntity in Data layer with Doctrine ORM attributes - Add PersonModel in Logic layer for business logic - Add immutable PersonDto in Shared layer - Configure doctrine/orm dependency in composer.json - Add Doctrine deprecation triggers to phpunit configuration
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
globs: '["**/Data/**/*Repository.php"]'
|
||||||
|
description: Prevents the common error of using invalid Doctrine ORM attributes
|
||||||
|
in Repository classes
|
||||||
|
---
|
||||||
|
|
||||||
|
When creating Doctrine repositories, NEVER use #[ORM\EntityManager] as this is not a valid Doctrine mapping attribute and causes runtime errors. Repositories must only be instantiated via Dependency Injection with EntityManagerInterface in their constructor. Valid ORM attributes for Repositories include: none (standard), or optionally #[ORM\HasEntityListeners] if needed. Mapping attributes like #[ORM\Entity], #[ORM\Table], #[ORM\JoinColumn] are ONLY for Entity classes, not Repository classes.
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
globs: '["src/**/*Repository.php"]'
|
||||||
|
description: Ensures minimal boilerplate by avoiding unnecessary custom
|
||||||
|
Repository classes for standard CRUD operations, while still allowing them for
|
||||||
|
complex queries.
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
In Symfony and Doctrine based applications, avoid creating custom Repository classes for simple CRUD or standard query operations (e.g., findOneBy, findBy). Instead, use Doctrine's native EntityRepository directly via $entityManager->getRepository(Entity::class) within the Provider or Processor implementations.
|
||||||
|
|
||||||
|
Only create a custom repository when:
|
||||||
|
1. Complex queries involving multiple joins, subselects, or specialized search logic are required.
|
||||||
|
2. Query logic is reused across multiple Providers/Processors and warrants encapsulation for DRY compliance.
|
||||||
|
|
||||||
|
When no custom repository is needed, Inject EntityManagerInterface directly into the Provider or Processor and fetch the repository inline as shown below:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$repository = $this->entityManager->getRepository(EntityClass::class);
|
||||||
|
$result = $repository->findOneBy(['id' => $id]);
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not create an empty or wrapper Repository class that only delegates to Doctrine's native methods.
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
"php": ">=8.4",
|
"php": ">=8.4",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-iconv": "*",
|
"ext-iconv": "*",
|
||||||
|
"doctrine/orm": "*",
|
||||||
"symfony/console": "8.1.*",
|
"symfony/console": "8.1.*",
|
||||||
"symfony/dotenv": "8.1.*",
|
"symfony/dotenv": "8.1.*",
|
||||||
"symfony/flex": "^2",
|
"symfony/flex": "^2",
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
</include>
|
</include>
|
||||||
|
|
||||||
<deprecationTrigger>
|
<deprecationTrigger>
|
||||||
|
<method>Doctrine\Deprecations\Deprecation::trigger</method>
|
||||||
|
<method>Doctrine\Deprecations\Deprecation::delegateTriggerToBackend</method>
|
||||||
<function>trigger_deprecation</function>
|
<function>trigger_deprecation</function>
|
||||||
</deprecationTrigger>
|
</deprecationTrigger>
|
||||||
</source>
|
</source>
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Data\Person\Entity;
|
||||||
|
|
||||||
|
use App\Logic\Person\Repository\PersonRepositoryInterface;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
#[ORM\Entity]
|
||||||
|
#[ORM\Table(name: 'person')]
|
||||||
|
class PersonEntity
|
||||||
|
{
|
||||||
|
#[ORM\Id]
|
||||||
|
#[ORM\GeneratedValue]
|
||||||
|
#[ORM\Column(type: 'integer')]
|
||||||
|
private ?int $id = null;
|
||||||
|
|
||||||
|
#[ORM\Column(type: 'string', length: 255)]
|
||||||
|
private string $anrede;
|
||||||
|
|
||||||
|
#[ORM\Column(type: 'string', length: 255)]
|
||||||
|
private string $vorname;
|
||||||
|
|
||||||
|
#[ORM\Column(type: 'string', length: 255)]
|
||||||
|
private string $name;
|
||||||
|
|
||||||
|
#[ORM\Column(type: 'string', length: 10)]
|
||||||
|
private string $geschlecht;
|
||||||
|
|
||||||
|
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||||
|
private ?string $titel = null;
|
||||||
|
|
||||||
|
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||||
|
private ?string $funktionstitel = null;
|
||||||
|
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAnrede(): string
|
||||||
|
{
|
||||||
|
return $this->anrede;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAnrede(string $anrede): void
|
||||||
|
{
|
||||||
|
$this->anrede = $anrede;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVorname(): string
|
||||||
|
{
|
||||||
|
return $this->vorname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setVorname(string $vorname): void
|
||||||
|
{
|
||||||
|
$this->vorname = $vorname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName(string $name): void
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGeschlecht(): string
|
||||||
|
{
|
||||||
|
return $this->geschlecht;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGeschlecht(string $geschlecht): void
|
||||||
|
{
|
||||||
|
$this->geschlecht = $geschlecht;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitel(): ?string
|
||||||
|
{
|
||||||
|
return $this->titel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTitel(?string $titel): void
|
||||||
|
{
|
||||||
|
$this->titel = $titel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFunktionstitel(): ?string
|
||||||
|
{
|
||||||
|
return $this->funktionstitel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFunktionstitel(?string $funktionstitel): void
|
||||||
|
{
|
||||||
|
$this->funktionstitel = $funktionstitel;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Logic\Person\Models;
|
||||||
|
|
||||||
|
final class PersonModel
|
||||||
|
{
|
||||||
|
private ?int $id = null;
|
||||||
|
|
||||||
|
private string $anrede;
|
||||||
|
|
||||||
|
private string $vorname;
|
||||||
|
|
||||||
|
private string $name;
|
||||||
|
|
||||||
|
private string $geschlecht;
|
||||||
|
|
||||||
|
private ?string $titel = null;
|
||||||
|
|
||||||
|
private ?string $funktionstitel = null;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
?int $id,
|
||||||
|
string $anrede,
|
||||||
|
string $vorname,
|
||||||
|
string $name,
|
||||||
|
string $geschlecht,
|
||||||
|
?string $titel,
|
||||||
|
?string $funktionstitel
|
||||||
|
) {
|
||||||
|
$this->id = $id;
|
||||||
|
$this->anrede = $anrede;
|
||||||
|
$this->vorname = $vorname;
|
||||||
|
$this->name = $name;
|
||||||
|
$this->geschlecht = $geschlecht;
|
||||||
|
$this->titel = $titel;
|
||||||
|
$this->funktionstitel = $funktionstitel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAnrede(): string
|
||||||
|
{
|
||||||
|
return $this->anrede;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAnrede(string $anrede): void
|
||||||
|
{
|
||||||
|
$this->anrede = $anrede;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVorname(): string
|
||||||
|
{
|
||||||
|
return $this->vorname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setVorname(string $vorname): void
|
||||||
|
{
|
||||||
|
$this->vorname = $vorname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName(string $name): void
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGeschlecht(): string
|
||||||
|
{
|
||||||
|
return $this->geschlecht;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGeschlecht(string $geschlecht): void
|
||||||
|
{
|
||||||
|
$this->geschlecht = $geschlecht;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitel(): ?string
|
||||||
|
{
|
||||||
|
return $this->titel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTitel(?string $titel): void
|
||||||
|
{
|
||||||
|
$this->titel = $titel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFunktionstitel(): ?string
|
||||||
|
{
|
||||||
|
return $this->funktionstitel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFunktionstitel(?string $funktionstitel): void
|
||||||
|
{
|
||||||
|
$this->funktionstitel = $funktionstitel;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Shared\Person\DTO;
|
||||||
|
|
||||||
|
readonly final class PersonDto
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public int $id,
|
||||||
|
public string $anrede,
|
||||||
|
public string $vorname,
|
||||||
|
public string $name,
|
||||||
|
public string $geschlecht,
|
||||||
|
public ?string $titel = null,
|
||||||
|
public ?string $funktionstitel = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user