学说中的两个生成价值观

ick*_*sde 16 php mysql doctrine symfony doctrine-orm

我想在我的Doctrine-Entity中实现一个人类可读的ID.我想保持DB-ID工作并添加类似"PRE12-00005"(带有前缀和年份,并且每年新的0开始).我尝试添加一个Custom-ID-Generator,但似乎Doctrine无法在一个实体中使用两个生成的值.

/**
 * @var integer
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
protected $id;

/**
 * @var string
 * @ORM\Column(name="name", type="string", length=25, unique=true)
 * @ORM\GeneratedValue(strategy="CUSTOM")
 * @ORM\CustomIdGenerator(class="NameGenerator")
 */
protected $name;
Run Code Online (Sandbox Code Playgroud)

Doctrine总是尝试将生成器的返回值保存到"id"-Field中,并将null保存为"name".有没有其他方法来实现它?

Sgo*_*kes 18

据我所知,GeneratedValue策略是为主键保留的,这意味着每个实体只能使用一次.

根据您的需要,您有几个选择:

  • 您始终可以拥有prePersist生命周期事件,在您第一次保留之前设置您喜欢的任何值.

  • 如果你依赖id来从中生成另一个唯一的id,你可以实现一个postPersist事件,在那里设置你的名字,并确保你刷两次(第一次生成主键,第二次保存名称).

  • 如果您可以在数据库中将该名称清空一段时间,则可以实现postLoad事件,如果该名称为空,则填充该名称.这样,您的应用程序始终可以看到名称(因为它是从数据库加载或由postLoad事件填充),当您在初始保存后第一次添加或编辑信息时,您的名称也将被保存

  • 可以不保存名称并让它由某些cronjob/deamon/queue生成,这样您的应用程序就不必处理它了.您唯一需要做的就是确保缺少名称不会搞砸某些东西.

  • 也许可以生成一个不依赖于主键的键,因此可以由全局事件处理程序生成.你当然有一个缺点,就是这样一个事件处理程序,因为他是全局的,会为你持久化的每个对象调用,无论它是否是正确的实体.

  • 最后,但并非最不重要的是,可以回退到Stored Procedures/Triggers以让数据库处理这个问题.这样您就不必在应用程序中弄乱这个.但要注意,路上可能存在陷阱(比如开发人员忘记了这一点,因为它不在代码中而是在数据库中!).

可能还有其他方式.我想说的是:不要将generatedValue用于非主键属性!