我有一个带有字段的实体,不包含在表单中,但是基于其他字段值计算,这些值带有输入。 目前,该值在生命周期回调中设置:
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function prePersist() {...}
我希望在DB表列的范围内保持此值唯一,并在保存之前对其进行修改,直到它只有一个。
我尝试使用UniqueEntity
,但在实体创建对象时,字段的值为NULL(未知)。所以它在表单提交之后保留,在验证时。实际调用prePersist()
时,会显示该值并转到数据库而不进行验证。
我可能会尝试获取EntityRepository
实例,并尝试将检查作为来自prePersist()
的SQL查询,但它看起来非常难看。
我可能会尝试使用一种散列函数,比如md5或sha1,它们主要保证值的唯一性,但散列函数有碰撞,我希望保持该值“人类可读”。
请为我提出针对此案的“Symfony”式解决方案。
答案 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显着降低了碰撞的风险。即使我们从列表中更改参数(例如,在用户更新具有编辑表单的实体的情况下),该值仍然是唯一的。此外,我们已经消毒,但可读并且在别名开始时具有感测参数,这有助于在手动调查的情况下记忆。
解决方案的缺点是可变长度,这取决于参数。但它们可能缩短到固定长度。