Eindeutige universelle IDs (UUID) in Doctrine verwenden

Bei Verwendung von Doctrine als ORM-Framework ist es ein leichtes, Primärschlüssel als Auto-Increment-Werte zu definieren. Der Nachteil ist, dass diese ID-Werte den Besuchern z.B. einer Webseite, falls sie auch nach Außen hin verwendet werden (z.B. in URLs), Informationen über z.B. die Größe der Datenbank, Anzahl der Kunden oder ähnliches geben können.

Um dieses Problem zu lösen, empfiehlt es sich, systemweit eindeutige IDs, sogenannte UUIDs zu verwenden.

Vorteile davon sind:

  • UUIDs sind weltweit einzigartig, oder besser gesagt praktisch einzigartig, denn theoretisch kann es trotzdem vorkommen, dass dieselbe ID zweimal vergeben wird.
  • Beim Zusammenführen zweier Tabellen muß man sich um die Eindeutigkeit der IDs keine Gedanken machen
  • Die UUIDs können auch nach Außen gegeben werden, ohne etwas über die Größe der Tabelle zu verraten oder weitere IDs durch Erhöhen der ID erratbar zu machen

Die Verwendung von UUIDs ist dank des Projektes ramsey/uuid-doctrine eigentlich recht einfach (siehe https://github.com/ramsey/uuid-doctrine):

Die Installation geschieht über Composer:

composer require ramsey/uuid-doctrine

Dann müssen wir irgendwo vor der Doctrine-Initialisierung (z.B. bei der Initialisierung des PHP-Frameworks) noch den UUID-Generator an Doctrine bekanntgeben:

\Doctrine\DBAL\Types\Type::addType('uuid', 'Ramsey\Uuid\Doctrine\UuidType');

Danach können wir den Generator in jedem beliebigen Doctrine-Entity verwenden:

<?php
namespace MyProject\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table("user")
 * @ORM\Entity  
 */
class User {
    
    /**
     * @var \Ramsey\Uuid\Uuid
     *
     * @ORM\Id
     * @ORM\Column(type="uuid")
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
     */
    protected $id;

    public function getId()
    {
        return $this->id;
    }
}

Damit kümmert sich Doctrine automatisch um die Erstellung der UUIDs.

Verwendung der UUIDs

Hat man eine UUID-String als Parameter und möchte ein Entity suchen, kann man diesen String nicht direkt verwenden, sondern muß eine UUID daraus generieren:

$uuid = \Ramsey\Uuid\Uuid::fromString($uuidAsString);
$user = $this->findOneById($uuid);