【问题标题】:Calculate unique alias before flushing entity在刷新实体之前计算唯一别名
【发布时间】:2016-05-23 19:32:26
【问题描述】:

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

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\PrePersist
 * @ORM\PreUpdate
 */
public function prePersist() {...}

我希望这个值在 DB 表列的范围内保持唯一,并在保存之前对其进行修改,直到它是唯一的一个。

  • 我尝试使用UniqueEntity,但在创建实体对象时,该字段的值为 NULL(未知)。所以它会在表单提交后,在验证时保留。当prePersist() 被实际调用时,该值会出现并在没有验证的情况下进入数据库。

  • 我可能会尝试获取EntityRepository 实例,并尝试将检查作为来自prePersist() 的SQL 查询,但它看起来非常难看。

  • 我可能会尝试使用一种散列函数,如 md5 或 sha1,它们主要保证值的唯一性,但散列函数存在冲突,我希望保持该值“人类可读”。

请给我一个“Symfony”风格的解决方案来解决这个问题。

【问题讨论】:

  • 我不太明白你的需求是什么。您是否想要一种生成自动创建并分配给每个新条目的唯一且可读的标识符的好方法?
  • “人类可读”是什么意思?你喜欢哪种格式?
  • 是的,我需要一种基于用户输入生成唯一可读标识符的方法。如果可能,它应该在数据库记录编辑时更新,并且在任何情况下仍然是唯一的。如果需要,“人类可读”意味着易于阅读和记忆(可能部分记忆)。

标签: php symfony doctrine entity


【解决方案1】:

我的第一个想法是:使用doctrine GUID/UUID generator

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

另外,我的建议有点复杂,有点需要,我理解你不想写很多代码和复杂的架构。

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

/**
 * @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;

【讨论】:

  • 这是一个有趣的方法,谢谢。很遗憾,但它不允许包含从请求到生成的 UUID 的用户数据(我称之为“人类可读性”,并用于手动事件调查 - 如果别名包含除哈希之外的一些单词或其他内容,则很容易阅读否则)。
【解决方案2】:

在实例创建期间避免空值:(不保证唯一的 id)

md5(uniqid(rand(), true))

为了始终保持唯一的价值:

md5(uniqid($your_user_login, true))

md5(uniqid($entity_id, true))

【讨论】:

  • 我同意这种做法。 time() . rand() 也提供唯一 ID。但是这个别名太无意义了——很难手动搜索和调查一些案例。
  • 别名是什么意思? entity_id ?
  • Alias for me 是 entity_id 的替代品,用于在使用整数 id 无效或不安全时使用。
  • 您的解决方案启发了我对我的问题的回答,谢谢。
【解决方案3】:

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

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

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

use Doctrine\ORM\Mapping as ORM;

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

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

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

【讨论】:

  • 您应该接受您的回答,这是一种符合您需要的干净方法。
猜你喜欢
  • 2014-08-16
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-26
  • 2015-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多