在刷新实体

时间:2016-02-12 15:24:07

标签: php symfony doctrine entity

我有一个带有字段的实体,不包含在表单中,但是基于其他字段值计算,这些值带有输入。 目前,该值在生命周期回调中设置:

use Doctrine\ORM\Mapping as ORM;

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

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

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

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

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

请为我提出针对此案的“Symfony”式解决方案。

3 个答案:

答案 0 :(得分:2)

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

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

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

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

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

答案 1 :(得分:1)

在实例创建期间避免空值:(确实保证唯一ID)

md5(uniqid(rand(), true))

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

md5(uniqid($your_user_login, true))

md5(uniqid($entity_id, true))

答案 2 :(得分:1)

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

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

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

use Doctrine\ORM\Mapping as ORM;

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

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

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