Skip to content

Instantly share code, notes, and snippets.

@webdevilopers
Last active March 14, 2022 11:23
Show Gist options
  • Save webdevilopers/1ad09ce341ab81ccfc588841e1d1f223 to your computer and use it in GitHub Desktop.
Save webdevilopers/1ad09ce341ab81ccfc588841e1d1f223 to your computer and use it in GitHub Desktop.
Using Value Objects as Custom Doctrine DBAL Type as Identifier in Symfony
# Doctrine Configuration
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
server_version: 5.1
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
# if using pdo_sqlite as your database driver, add the path in parameters.yml
# e.g. database_path: "%kernel.root_dir%/data/data.db3"
# path: "%database_path%"
types:
guttercolorid: Sps\DormerCalculation\Infrastructure\Persistence\Doctrine\GutterColorIdType
<?php
namespace Sps\DormerCalculation\Infrastructure\Persistence\Doctrine;
use Doctrine\ORM\EntityRepository;
/**
* Class DoctrineGutterColorRepository
* @package Sps\DormerCalculation\Infrastructure\Persistence\Doctrine
*/
final class DoctrineGutterColorRepository
extends EntityRepository
implements GutterColorRepository
{}
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Sps\DormerCalculation\Domain\Model\Gutter\GutterColor" table="gutter_color"
repository-class="Sps\DormerCalculation\Infrastructure\Persistence\Doctrine\DoctrineGutterColorRepository">
<id type="guttercolorid" name="id" />
<field name="name" column="name" length="50" />
</entity>
</doctrine-mapping>
<?php
namespace Sps\DormerCalculation\Domain\Model\Gutter;
use Sps\DormerCalculation\Domain\Model\Gutter\GutterColorId;
/**
* Class GutterColor
* @package Sps\DormerCalculation\Domain\Model\Gutter
*/
final class GutterColor
{
/** @var GutterColorId $id */
private $id;
/** @var string $name */
private $name;
}
<?php
namespace Sps\DormerCalculation\Infrastructure\Persistence\Doctrine;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\GuidType;
use Doctrine\DBAL\Types\Type;
use Sps\DormerCalculation\Domain\Model\Gutter\GutterColorId;
/**
* Class GutterColorIdType
* @package Sps\DormerCalculation\Infrastructure\Persistence\Doctrine
*/
#final class GutterColorIdType extends Type
final class GutterColorIdType extends GuidType
{
const GUTTER_COLOR_ID = 'guttercolorid';
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getGuidTypeDeclarationSQL($fieldDeclaration);
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if (empty($value)) {
return null;
}
if ($value instanceof GutterColorId) {
return $value;
}
return GutterColorId::fromInteger($value);
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if (empty($value)) {
return null;
}
return $value->toInteger();
}
public function getName()
{
return self::GUTTER_COLOR_ID;
}
/**
* {@inheritdoc}
*
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
* @return boolean
*/
public function requiresSQLCommentHint(AbstractPlatform $platform)
{
return true;
}
}
@webdevilopers
Copy link
Author

Hi @Kwadz ,

wow, this gist is almost 3 years old. I currently don't maintain the related code any more.
Regarding Doctrine ORM I converted most of my Models to event-sourced Aggregate Roots (A+ES).

All I can offer is the last commit I did on that class. but I can not confirm that it works.

<?php

namespace Sps\DormerConstruction\Infrastructure\Persistence\Doctrine;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;
use Sps\DormerConstruction\Domain\Model\GutterColor\GutterColorId;

final class GutterColorIdType extends Type
{
    const GUTTER_COLOR_ID = 'gutter_color_id';

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
    {
        return $platform->getGuidTypeDeclarationSQL($fieldDeclaration);
    }

    public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        if (empty($value)) {
            return null;
        }

        if ($value instanceof GutterColorId) {
            return $value;
        }

        return GutterColorId::fromInteger($value);
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform)
    {
        if (empty($value)) {
            return null;
        }

        return $value->toInteger();
    }

    public function getName()
    {
        return self::GUTTER_COLOR_ID;
    }

    /**
     * {@inheritdoc}
     *
     * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
     * @return boolean
     */
    public function requiresSQLCommentHint(AbstractPlatform $platform)
    {
        return true;
    }
}

In this example the value object uses a simple integer.

<?php

namespace Sps\DormerConstruction\Domain\Model\GutterColor;

final class GutterColorId
{
    private int $id;

    private function __construct(int $id)
    {
        $this->id = $id;
    }

    public function __toString(): string
    {
        return (string)$this->id;
    }

    public static function fromInteger(int $id) : GutterColorId
    {
        return new self($id);
    }

    public function toInteger(): int
    {
        return $this->id;
    }
}

Since we switched to event sourcing we are indeed using Ramsey UUID exclusively.

Hope it helps!

@webdevilopers
Copy link
Author

PS.: Are you on twitter?!

@Kwadz
Copy link

Kwadz commented Mar 13, 2022

It's much simpler than I expected :)

Actually I found this article about the conversion that uses preg_replace. But yes of course a simple cast should be enough. Thanks for opening my eyes!

Yes I have twitter, I've just subscribed to your page ;)

@webdevilopers
Copy link
Author

I favorited that page some years ago too. 😇

Yes, actually it is pretty easier. I think it work out-of-the-box with this @ramsey library extension:
https://github.com/ramsey/uuid-doctrine

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment