3

I'd like to create unique IDs, something like dujUSJue9389sjgjik.

I've used the Doctrine's UUID strategy to create them, but the result is something like d9c363ae-a1b7-11e6-a66d-9e9923e30d94: I don't like the use of dashes and also I'd like to have shorter IDs.

They have to identify some entities to build an URL like http://example.com/entity/hduicw43tv43bic.

Using PHP's uniqid() doesn't guarantee the uniqueness of the generated value. I think a conflict is very rare, but, anyway, not excluded at all, so I'm not considering it "secure" (a conflict may cause an exception and the rows creation may cause a lot of headache to fix).

So, using Doctrine and Symfony, I'm looking for a way to generate a value like ajybUYBD74883bj8d74NJ and check for its uniqueness. If it is already present, a new value has to be generated. Once the entity has a unique value, it can be persisted. The generation should happen when the entity is created.

Any ideas on how to implement this?

Aerendir
  • 6,152
  • 9
  • 55
  • 108
  • There's no real unique value generation algorithm that guarantees uniqueness, including UUID/GUID. – Jakub Matczak Nov 03 '16 at 11:46
  • Yes, I'm aware of this. For this I'm looking for a procedure to check the uniqueness and on fail (the generated ID already exists) regenerate it. This should be done in Doctrine entity itself. – Aerendir Nov 03 '16 at 11:47
  • 1
    This should be done in entity itself. It's not entity's job to check other entities (inclufing calling repository). It should be ID generator's job. You can try to create a custom ID generator, but I can't find documentation about it. Anyway here's an example in psylosss's answer: http://stackoverflow.com/questions/15039665/generate-unique-id-doctrine-symfony2 – Jakub Matczak Nov 03 '16 at 11:52
  • 1
    UUID is just a number. You can display it as hexadecimal text with inserted hyphen characters, but it's still a 128-bit value. You can represent it as you want (e.g: base64-encoded) – Federkun Nov 03 '16 at 11:54
  • @Federkun, yes, for sure, but I don't want it be too much long... Maybe UUID has a technical meaning, but I'm intending it simply as a unique value to identify an entity, without constraints on length, format or anything else. Its unique property, for the purpose of this question, is its uniqueness. – Aerendir Nov 03 '16 at 11:57

4 Answers4

4

So, mixing the answer by @Matteo and the answer by psyloss suggested by @Jakub Matczak I came up with this:

class Company
{
    /**
     * @var string
     *
     * @ORM\Column(name="id", type="string")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class="AppBundle\Doctrine\IdGenerator")
     */
     private $id;

     ...

and then

namespace AppBundle\Doctrine;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Id\AbstractIdGenerator;
use Ramsey\Uuid\Uuid;

/**
 * {@inheritdoc}
 */
class IdGenerator extends AbstractIdGenerator
{
    /**
     * {@inheritdoc}
     */
    public function generate(EntityManager $em, $entity)
    {
        $uuid = Uuid::uuid4()->getHex();

        if (null !== $em->getRepository(get_class($entity))->findOneBy(['id' => $uuid])) {
            $uuid = $this->generate($em, $entity);
        }

        return $uuid;
    }
}

This generator also checks for an existing entity with the same name, regenerating the UUID if required and guaranteeing the uniqueness.

The generated value is exactly what I want: 7b165049eb224f548021f68caefc57f6.

Community
  • 1
  • 1
Aerendir
  • 6,152
  • 9
  • 55
  • 108
1

If Doctrine's UUID strategy is good you can simply transform that:

$in = 'd9c363ae-a1b7-11e6-a66d-9e9923e30d94';
$out = base_convert(strtr($in,'-',''),16,36);
print_r($out);

short, no dash, reverseable

cske
  • 2,233
  • 4
  • 26
  • 24
1

I suggest you to use the ramsey-uuid library, ad Use As Follow:

$uuid = \Ramsey\Uuid\Uuid::uuid4();
echo $uuid->getHex();

Alternately, if you already have a UUID, you may do this:

$uuid = \Ramsey\Uuid\Uuid::fromString('f6a1fd62-1445-42fc-9e7b-d8c6e9da33a1');
echo $uuid->getHex();

More info in this article

Hope this help

Matteo
  • 37,680
  • 11
  • 100
  • 115
0

Ramsey uuid lib is auch good start point. There is also an library from anthony https://github.com/ircmaxell/RandomLib.

But take care about uuid, they can corrupt your data! Also you can't check with a select if the id is already in the DB. If two users will create 2 records at the same time they can get the same id.

Markus
  • 440
  • 2
  • 10