«A repository behaves like an collection of unique domain object without taking care about the storage»
namespace BouchonnoisCorp\Domain\Write;
interface Repository
{
/**
* @throws \LogicException
*/
public function add(Object $object): void;
/**
* @throws UnknownObject | \LogicException
*/
public function get(Identifier $identifier): Object;
/**
* @throws \LogicException
*/
public function remove(Identifier $identifier): void;
/**
* @throws \LogicException
*/
public function nextIdentity(): Identifier;
}
Dédé, Business Expert @BouchonnoisCorp
namespace BouchonnoisCorp\Domain\Write;
/**final*/ class Galinette
{
// constructor ...
public static function born(
Identifier $identifier,
Birthday $birthday,
Gender $gender
): Galinette {
return new self($identifier, $birthday, new Name(''), $gender);
}
public function name(Name $name): void
{
$this->name = $name;
}
public function goToHeaven(): void
{
$this->goToHeavenAt = new \DateTimeImmutable('NOW');
}
}
namespace BouchonnoisCorp\Domain\Write;
interface GalinetteRepository
{
public function find(int $id): Galinette;
public function findGalinetteArray(): array;
public function findGalinetteForARelease(): Galinette[];
public function findGalinetteIdentifierForAReleaseAsString(): string[];
public function findGalinetteNameByIdentifier(int $id): string;
public function getQueryBuilder(): QueryBuilder;
// etc ...
}
These are more SQL query repositories
Gérard, CTO @BouchonnoisCorp
namespace BouchonnoisCorp\Infrastructure\Storage\Doctrine;
use BouchonnoisCorp\Domain\Write\GalinetteRepository;
final class GalinetteRepository implements GalinetteRepository
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
// ...
}
namespace BouchonnoisCorp\Infrastructure\Storage\Doctrine;
final class GalinetteRepository implements GalinetteRepository
{
// ...
public function nextIdentity(): Identifier
{
try {
return new Identifier(Uuid::uuid4()->toString());
} catch (\Exception $e) {
throw new \LogicException('It is not possible to build the next identity');
}
}
}
namespace BouchonnoisCorp\Infrastructure\Storage\Doctrine;
final class GalinetteRepository implements GalinetteRepository
{
// ...
public function add(Galinette $galinette)
{
try {
$this->entityManager->persist($galinette);
$this->entityManager->flush($galinette);
} catch (ORMInvalidArgumentException | ORMException $e) {
throw new \LogicException('It is not possible to add this galinette');
}
}
// ...
}
namespace BouchonnoisCorp\Infrastructure\Storage\Doctrine;
final class GalinetteRepository implements GalinetteRepository
{
// ...
public function get(Identifier $identifier): Galinette
{
try {
$galinette = $this->entityManager->find(Galinette::class, $identifier);
} catch (ORMInvalidArgumentException | ORMException $e) {
throw new \LogicException('It is not possible to retrieve this galinette');
} finally {
if (null === $galinette) {
throw new Exception\UnknownGalinette(
(string) $identifier,
Galinette::class
);
}
return $galinette;
}
}
// ...
}
namespace BouchonnoisCorp\Infrastructure\Storage\Doctrine;
final class ObjectRepository
{
// ...
public function remove(Identifier $identifier)
{
try {
$galinette = $this->entityManager->getReference(
Object::class,
(string) $identifier
);
$this->entityManager->remove($galinette);
$this->entityManager->flush($galinette);
} catch (ORMInvalidArgumentException | ORMException $e) {
throw new \LogicException('It is not possible to remove this object');
}
}
// ...
}
«A query function is a class which represents a SQL query.»
namespace BouchonnoisCorp\Infrastructure\Storage\Doctrine\Query;
final class ReleaseOfGalinettes
{
private $connection;
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
public function findGalinettes(): array
{
$query = 'SELECT g.* FROM galinette
INNER JOIN g.censored_table_name ...'
$statement = $this->connection->query($query);
$galinettes = [];
while ($galinette = $statement->fetch()) {
$galinettes[] = new ReleasedGalinette(
$galinette['identifier'],
$galinette['name'],
$galinette['birthday']
);
}
return $galinettes;
}
}
namespace BouchonnoisCorp\Domain\Read;
final class ReleasedGalinette
{
private $identifier;
private $name;
private $birthday;
public function __construct(
string $identifier,
string $name,
string $birthday
) {
$this->identifier = $identifier;
$this->name = $name;
$this->birthday = $birthday;
}
public function normalize(): array
{
return [
'id' => $this->identifier,
'name' => $this->name,
'birthday' => $this->birthday,
];
}
}