在刷新实体之前计算唯一别名


Calculate unique alias before flushing entity

我有一个带有字段的实体,该字段未包含在表单中,而是根据输入附带的其他字段值进行计算。当前该值在生命周期回调中设置:

use Doctrine'ORM'Mapping as ORM;
/**
 * @ORM'PrePersist
 * @ORM'PreUpdate
 */
public function prePersist() {...}

我想在数据库表列的范围内保持此值唯一,并在保存之前对其进行修改,直到它只有一个。

  • 我尝试使用 UniqueEntity ,但在实体的对象创建时,字段的值为 NULL(未知(。因此,它在表单提交后,在验证时会保留。实际调用 prePersist() 时,将显示该值并转到数据库,而无需验证。

  • 我可能会尝试获取一个EntityRepository实例,并尝试从prePersist()进行 SQL 查询检查,但它看起来非常丑陋。

  • 我可能会尝试使用一种哈希函数,例如 md5 或 sha1,它们主要保证值的唯一性,但哈希函数有冲突,我希望保持该值"人类可读"。

请向我提出一个"Symfony"式的解决方案。

我的第一个想法是:使用原则GUID/UUID生成器。

但是,它只能用作标识符,出,你想要一个简单的字段。

另外,我建议的有点复杂,有点需要,我知道你不想写很多代码并且有一个复杂的模式。

使用自定义标识符创建特定实体:

/**
 * @ORM'Entity
 */ 
class UniqIdentifier
{
    /**
     * @ORM'Column(type="guid")
     * @ORM'Id
     * @ORM'GeneratedValue(strategy="UUID")
     */
    private $id;
}  

并在您的实体中添加以下内容:

/**
 * @ORM'OneToOne(targetEntity="UniqIdentifier", cascade={"persist", "remove"}, orphanRemoval=true)
 */
protected $uniqId;

避免在实例创建过程中出现空值:(不保证唯一 ID(

md5(uniqid(rand(), true))

并且为了始终保持唯一值:

md5(uniqid($your_user_login, true))

md5(uniqid($entity_id, true))

感谢本主题中的回答和评论,我能够意识到我正在解决与Symfony2架构冲突的任务:

  • 从表单获取用户输入
  • 验证输入
  • 计算自动字段
  • 再次验证

可接受的解决方案看起来像是建议的方法的组合,包括一些"人类可读性"的技巧:别名是在通过此类方案进行输入验证后从表单参数的子集连接起来的:

use Doctrine'ORM'Mapping as ORM;
/**
 * @ORM'PrePersist
 * @ORM'PreUpdate
 */
public function prePersist()
{
   ...
   $alias = "{$param1}-{$param2}-...-{$paramN}-" . md5(time() . rand(0, 9));
   ...
}

因此,它是独一无二的,因为md5()连接到末端,串联的参数显着降低了碰撞的风险。即使我们从列表中更改参数(例如,在用户使用编辑表单更新实体的情况下(,该值仍然是唯一的。此外,我们进行了消毒,但可读且在别名开始时具有感知参数,这有助于在手动调查的情况下记忆。

该解决方案的缺点是长度可变,这取决于参数。但它们可能会缩短到固定长度。