sjster@gmail.com
Machine Learning/ Data Science
Mathias Arlaud
mtarld
@matarld
les-tilleuls.coop
@matarld
@chalas_r
// src/Domain/Forest/Model/Panda.php
#[ORM\Entity]
#[ApiResource]
final class Panda
{
public function __construct(
private UuidInterface $uuid,
// ...
#[ORM\Column(type: 'int')]
private int $hungerAmount,
) {
}
// ...
public function isHungry(): bool
{
return $this->hungerAmount > self::HUNGERNESS_THRESHOLD;
}
public function feed(Bamboo $bamboo): void
{
$this->hungerAmount = min(0, $this->hunger - $bamboo->getSize());
}
}
@matarld
@chalas_r
#[ORM\Entity]
#[ApiResource]
final class Panda
{
public function __construct(
private UuidInterface $uuid,
// ...
#[ORM\Column(type: 'int')]
private int $hunger,
) {
}
// ...
}
<!-- src/Infrastructure/Forest/Doctrine/Mapping/Panda.xml -->
<entity name="Acme\Domain\Forest\Model\Panda" table="panda">
<field name="uuid" type="uuid" unique="true" />
<!-- ... -->
<field name="hungry" type="integer" />
</entity>
@matarld
@chalas_r
#[ApiResource]
final class Panda
{
public function __construct(
private UuidInterface $uuid,
// ...
private int $hunger,
) {
}
// ...
}
<!-- src/Infrastructure/Forest/ApiPlatform/Resource/Panda.xml -->
<resource class="Acme\Domain\Forest\Model\Panda">
<itemOperations><!-- ... --></itemOperations>
<collectionOperations><!-- ... --></collectionOperations>
</resource>
> curl /api/pandas/{uuid}
@matarld
@chalas_r
[resourceClass, operationName, context]
> curl /api/pandas/{uuid}
[resourceClass, operationName, context]
@matarld
@chalas_r
@matarld
@chalas_r
// src/Application/Forest/Query/FindPandaByUuidQuery.php
final class FindPandaByUuidQuery extends FindByUuidQuery
{
}
@matarld
@chalas_r
// src/Application/Forest/Query/FindPandaByUuidQueryHandler.php
use Acme\Domain\Forest\Repository\PandaRepository;
final class FindPandaByUuidQueryHandler implements QueryHandler
{
public function __construct(private PandaRepository $repository) {}
final public function __invoke(FindPandaByUuidQuery $query): ?Panda
{
return $this->repository->searchByUuid($query->uuid);
}
}
FindPandaByUuidQuery
Panda
@matarld
@chalas_r
<itemOperation name="get">
<attribute name="query">FindPandaByUuidQuery</attribute>
</itemOperation>
// src/Infrastructure/Shared/ApiPlatform/DataProvider/ItemQueryDataProvider.php
final class ItemQueryDataProvider implements DataProviderInterface
{
public function getItem(...): ?object
{
$queryClass = $this->resourceMetadataFactory
->create($resourceClass)
->getItemOperationAttribute($operationName, 'query');
return $this->queryBus->ask(new $queryClass($identifiers['uuid']));
}
public function supports(...): bool { /* ... */}
}
FindByUuidQuery
@matarld
@chalas_r
// src/Infrastructure/Shared/ApiPlatform/DataProvider/CollectionQueryDataProvider.php
final class CollectionQueryDataProvider implements DataProviderInterface
{
public function getCollection(...): iterable
{
$queryClass = $this->resourceMetadataFactory
->create($resourceClass)
->getCollectionOperationAttribute($operationName, 'query');
return $this->queryBus->ask($queryClass::fromContext($context));
}
}
<collectionOperation name="get">
<attribute name="query">FindPandasQuery</attribute>
</collectionOperation>
FindPandasQuery
Pandas
FindByCriteriaQuery
@matarld
@chalas_r
FindExtraterrialPandasQuery
FindPandaByUuidQuery
// src/Infrastructure/Shared/ApiPlatform/DataPersister/DataPersister.php
final class DataPersister implements DataPersisterInterface
{
public function persist(...): ?object
{
$commandClass = $this->resourceMetadataFactory->create($resourceClass)
->getOperationAttribute($context, 'command');
return $this->commandBus->dispatch($commandClass::fromModel($data));
}
public function remove(...): void
{
$commandClass = $this->resourceMetadataFactory->create($resourceClass)
->getOperationAttribute($context, 'command');
return $this->commandBus->dispatch($commandClass::fromModel($data));
}
}
@matarld
@chalas_r
PersistCommand
RemoveCommand
// src/Application/Forest/Command/RemovePandaCommandHandler.php
final class RemovePandaCommandHandler implements CommandHandler
{
public function __construct(private PandaRepository $repository) {}
public function __invoke(RemovePandaCommand $command): void
{
$this->repository->remove($command->id());
}
}
@matarld
@chalas_r
// src/Application/Forest/Command/RemovePandaCommand.php
final class RemovePandaCommand implements RemoveCommand
{
public function __construct(private int $id) {}
public static function fromModel(object $panda): self
{
return new self($panda->id());
}
}
@matarld
@chalas_r
<itemOperation name="remove">
<attribute name="query">FindPandaByUuidQuery</attribute>
<attribute name="command">RemovePandaCommand</attribute>
</itemOperation>
@matarld
@chalas_r
final class Panda
{
public function __construct(private string $name)
{
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
}
{"name": "Pedro Panda"}
PATCH
final class Panda
{
public function __construct(private string $name)
{
}
public function name(): string
{
return $this->name;
}
public function rename(string $firstname, string $lastname): void
{
$this->name = sprintf('%s %s', $firstname, $lastname);
}
}
@matarld
@chalas_r
@matarld
@chalas_r
{
"uuid": "...",
"name": "Pedro Panda",
"hungry": true
}
{
"firstname": "Pedro",
"lastname": "Panda"
}
final class Panda
{
public function __construct(
private UuidInterface $uuid,
private string $name,
private int $hunger,
) {
}
// ...
}
@matarld
@chalas_r
<itemOperation name="get">
<attribute name="input">Acme\Application\Forest\Payload\PandaPayload</attribute>
<attribute name="output">Acme\Application\Forest\View\PandaView</attribute>
</itemOperation>
@matarld
@chalas_r
// src/Application/Forest/Payload/PandaPayload.php
final class PandaPayload
{
public function __construct(
public readonly ?string $firstname = null,
public readonly ?string $lastname = null,
) {
}
}
// src/Domain/Forest/Model/Panda.php
final class Panda
{
public function __construct(private string $name)
{
}
public function rename(
string $firstname,
string $lastname,
): void {
$this->name = sprintf('%s %s', $firstname, $lastname);
}
}
@matarld
@chalas_r
// src/Infrastructure/Forest/ApiPlatform/DataTransformer/PandaPayloadDataTransformer.php
final class PandaPayloadDataTransformer implements DataTransformerInterface
{
public function transform($payload, string $to, array $context = []) {
$panda = $context['object_to_populate'] ?? new Panda();
$panda->rename($payload->firstname, $payload->lastname);
return $panda;
}
public function supportsTransformation($data, string $to, array $context = []): bool {
return PandaPayload::class === ($context['input']['class'] ?? null)
&& Panda::class === $to;
}
}
@matarld
@chalas_r
// src/Domain/Forest/Model/Panda.php
final class Panda
{
public function __construct(
private UuidInterface $uuid
private string $name,
private int $hunger,
) {
}
public function isHungry(): bool
{
return $this->hunger > self::HUNGERNESS_THRESHOLD;
}
}
// src/Application/Forest/View/PandaView.php
final class PandaView
{
public function __construct(
public readonly string $uuid,
public readonly string $name,
public readonly bool $hungry,
) {
}
}
@matarld
@chalas_r
// src/Infrastructure/Forest/ApiPlatform/DataTransformer/PandaViewDataTransformer.php
final class PandaViewDataTransformer implements DataTransformer
{
public function transform($panda, string $to, array $context = [])
{
return PandaView((string) $panda->uuid(), $panda->name(), $panda->isHungry());
}
public function supportsTransformation($data, string $to, array $context = []): bool
{
return PandaView::class === $to && $data instanceof Panda;
}
}
@matarld
@chalas_r
@matarld
@chalas_r
@matarld
@chalas_r