【问题标题】:PHP and Doctrine: how to create unique IDsPHP 和 Doctrine:如何创建唯一 ID
【发布时间】:2016-11-03 11:30:27
【问题描述】:

我想创建唯一 ID,例如 dujUSJue9389sjgjik

我使用了 Doctrine 的 UUID 策略来创建它们,但结果类似于 d9c363ae-a1b7-11e6-a66d-9e9923e30d94:我不喜欢使用破折号,而且我想要更短的 ID。

他们必须识别一些实体来构建像http://example.com/entity/hduicw43tv43bic 这样的 URL。

使用 PHP 的 uniqid() 并不能保证生成值的唯一性。我认为冲突非常罕见,但无论如何,根本不排除它,所以我不认为它是“安全的”(冲突可能会导致异常,并且行的创建可能会导致很多令人头疼的问题)。

所以,使用 Doctrine 和 Symfony,我正在寻找一种方法来生成像 ajybUYBD74883bj8d74NJ 这样的值并检查它的唯一性。如果它已经存在,则必须生成一个新值。一旦实体具有唯一值,它就可以被持久化。生成应该在实体创建时发生。

关于如何实现这一点的任何想法?

【问题讨论】:

  • 没有真正的唯一值生成算法可以保证唯一性,包括 UUID/GUID。
  • 是的,我知道这一点。为此,我正在寻找一个程序来检查唯一性并在失败时(生成的 ID 已经存在)重新生成它。这应该在 Doctrine 实体本身中完成。
  • 这应该在实体本身中完成。检查其他实体(包括调用存储库)不是实体的工作。这应该是 ID 生成器的工作。您可以尝试创建自定义 ID 生成器,但我找不到有关它的文档。无论如何,这是 psylosss 回答中的一个例子:stackoverflow.com/questions/15039665/…
  • UUID 只是一个数字。您可以将其显示为插入连字符的十六进制文本,但它仍然是 128 位值。你可以随心所欲地表示它(例如:base64-encoded)
  • @Federkun,是的,当然可以,但我不希望它太长......也许 UUID 具有技术意义,但我只是打算将其作为唯一值来识别一个实体,不受长度、格式或其他任何限制。就这个问题而言,它的独特属性是它的独特性。

标签: php mysql symfony doctrine-orm doctrine


【解决方案1】:

所以,混合@Jakub Matczak 建议的answer by @Matteoanswer by psyloss 我想出了这个:

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

     ...

然后

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;
    }
}

此生成器还检查具有相同名称的现有实体,如果需要,重新生成 UUID 并保证唯一性。

生成的值正是我想要的:7b165049eb224f548021f68caefc57f6

【讨论】:

    【解决方案2】:

    如果 Doctrine 的 UUID 策略很好,您可以简单地对其进行转换:

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

    短,无破折号,可反转

    【讨论】:

      【解决方案3】:

      我建议你使用ramsey-uuid 库,广告使用如下:

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

      或者,如果您已经有 UUID,您可以这样做:

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

      更多信息in this article

      希望有帮助

      【讨论】:

        【解决方案4】:

        Ramsey uuid lib 是一个很好的起点。还有一个来自 anthony https://github.com/ircmaxell/RandomLib 的图书馆。

        但请注意 uuid,它们会损坏您的数据!此外,如果 id 已经在数据库中,您也无法通过选择进行检查。如果两个用户同时创建 2 条记录,他们可以获得相同的 id。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-11-28
          • 2010-11-07
          • 2022-08-04
          • 1970-01-01
          • 1970-01-01
          • 2016-12-12
          • 1970-01-01
          相关资源
          最近更新 更多