我想在我的条令实体中实现一个人类可读的ID。我想保留DB-ID,以便工作和添加类似"PRE12-00005"的内容(带有前缀和年份,每年从0开始)。我试图添加一个自定义ID生成器,但Doctrine似乎无法在一个实体中使用两个生成的值。
/**
* @var integer
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* @var string
* @ORMColumn(name="name", type="string", length=25, unique=true)
* @ORMGeneratedValue(strategy="CUSTOM")
* @ORMCustomIdGenerator(class="NameGenerator")
*/
protected $name;
Doctrine总是试图将生成器的返回值保存到"id"-字段中,并将null保存到"name"中。还有其他方法可以实现吗?
据我所知,GeneratedValue策略是为主键保留的,这意味着每个实体只能使用一次。
根据您的需求,您有几个选择:
-
您总是可以有一个prePersist生命周期事件,在第一次持久化之前为名称设置任何您喜欢的值。
-
如果你依赖id从中生成另一个唯一的id,你可以实现一个postPersist事件,在那里设置你的名字,并确保你刷新两次(第一次生成主键,第二次保存名字)。
-
如果数据库中的名称在一段时间内为空是可以的,那么可以实现postLoad事件,如果名称为空,则该事件将填充该名称。通过这种方式,您的应用程序始终可以看到名称(因为它要么是从数据库加载的,要么是由postLoad事件填充的),当您在初次保存后第一次添加或编辑信息时,您的名称也将保存
-
不保存名称并由一些cronjob/deamon/queue生成它是可以的,这样你的应用程序就不必处理它。你唯一需要做的就是确保丢失的名称不会出错。
-
也许可以生成一个不依赖于主键的键,因此可以由全局事件处理程序生成。当然,您有一个缺点,因为这样的事件处理程序是全局的,所以无论它是否是正确的实体,都会为您持久化的每个对象调用。
-
最后,但并非最不重要的是,可以回退到存储过程/触发器,让数据库处理此问题。这样,您就不必在应用程序中搞砸了。但要注意,可能会有陷阱(比如开发人员忘记了这一点,因为它不在代码中,而是在数据库中!)。
可能还有其他方法。我想说的是:不要对非主键属性使用generatedValue!