How to configure Symfony OneToMany relationship to use eager fetching with ULID as a primary key?

Как можно исправить результат стандартной выборки из репозитория при использовании Symfony\Component\Uid\Ulid в качестве первичного ключа для данных сущностей?
  • 15 марта 2024 г. 11:09
Ответы на вопрос 3
To configure a Symfony OneToMany relationship with eager fetching using ULID as the primary key, you can follow these steps:

1. Define your entities with ULID as the primary key.
```php
// Your parent entity
class ParentEntity 
{
    /**
     * @ORM\Id
     * @ORM\Column(type="ulid")
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity="ChildEntity", mappedBy="parent")
     */
    private $children;
}

// Your child entity
class ChildEntity 
{
    /**
     * @ORM\Id
     * @ORM\Column(type="ulid")
     */
    private $id;
    
    /**
     * @ORM\ManyToOne(targetEntity="ParentEntity", inversedBy="children")
     */
    private $parent;
}
```

2. Configure the relationship in your repository or directly in your Symfony controller.
```php
// In your repository
class ParentEntityRepository extends EntityRepository
{
    public function findParentWithChildren($id)
    {
        return $this->createQueryBuilder('p')
            ->select('p', 'c')
            ->leftJoin('p.children', 'c')
            ->where('p.id = :id')
            ->setParameter('id', $id)
            ->getQuery()
            ->getOneOrNullResult();
    }
}
```

3. Fetch the data with eager loading in your controller.
```php
// In your controller
$parent = $this->getDoctrine()->getRepository(ParentEntity::class)->findParentWithChildren($parentId);
```

By configuring your entities and repository as shown above, you can retrieve data with eager loading and use ULID as the primary key for your Symfony OneToMany relationship.
Если я ничего не путаю, то у Доктрины постоянно что-то не так с кастомными типами. Попробуйте, может быть, заменить строкой в PHP, а в атрибуте указать тип 'guid', который и база и доктрина хорошо кушают. 

<?php
declare(strict_types=1);

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Uid\Ulid;

#[ORM\Entity]
#[UniqueEntity(fields: ['identifier'])]
class Foo
{
    #[ORM\Id]
    #[ORM\Column(type: 'guid', length: 16, unique: true)]
    private string $identifier;

    public function __construct()
    {
        $this->identifier = (new Ulid())->toRfc4122();
    }

    public function getIdentifier(): string
    {
        return $this->identifier;
    }
}
Стоило бы посмотреть как sql запрос в итоге формируется и где происходит несоответствие форматов. 

При передаче в качестве параметра запроса можно явно сконвертировать Ulid в нужный формат:
$entity->getUlid()->toBase32()
Похожие вопросы