我阅读了很多帖子,我发现了很多关于如何保存插入vs更新的变体,但找不到对我有用的东西。
我猜想如果preSave()由save()自动执行(如果存在的话),那么preSave就是你的选择。
columns:
email:
type: string(255)
unique: true
email: true
我需要save()来检查字段是否设置为唯一 如果是这样,检查这种情况下的电子邮件地址的字段数据是否唯一。 根据该信息决定插入或更新已更改的已发布字段。
答案 0 :(得分:1)
只需添加更多逻辑,就可以有更好的方法,但这对我有用。
public function preInsert($event) {
if ($this->state() == Doctrine_Record::STATE_TDIRTY) {
$r == findRecordInDatabaseUsingThis();
$this->assignIdentifier($r->id);
$this->refresh();
$this->state(Doctrine_Record::STATE_CLEAN); // STATE_DIRTY to do an update, this will just use the existing record without updating
$event->skipOperation();
}
}
}
答案 1 :(得分:0)
public function preSave($event)
{
if (!$this->isUniqueEmail()) {
$event->skipOperation();
}
}
但我建议您使用验证器。
答案 2 :(得分:0)
我猜Vladimir的答案是正确的,你只需要在skipOperation之前添加更新逻辑。
public function preSave($event)
{
if (!$this->isUniqueEmail()) {
// update logic
$event->skipOperation();
}
}
很抱歉,但我无法评论弗拉基米尔的回答。
答案 3 :(得分:0)
replace()
可能会有效。
答案 4 :(得分:0)
在遇到类似的情况后,我刚刚挖出了这个问题。 @Peter的答案几乎就是我要找的,但我添加了一些变化。
/**
* Check if identical record exists before (re)inserting
* @param \Doctrine_Event $event
* @return void
*/
public function preInsert(\Doctrine_Event $event)
{
$existing = $this->getTable()->findOneBy('email', $this->email);
if ($existing) {
$this->assignIdentifier($existing->id);
$this->hydrate($existing->toArray());
$this->state(self::STATE_CLEAN);
$event->skipOperation();
}
}
使用hydrate()
代替refresh()
意味着您执行少于1个SELECT查询。
我知道你可能会对这个问题有一个答案(至少我希望你有),但我想我会为同样的问题为其他人添加我的解决方案。
我还删除了if ($this->state() === self::STATE_TDIRTY)
,preInsert()
仅适用于TDIRTY记录
答案 5 :(得分:0)
我知道我在这里有点晚了,但是当我试图更新preInsert钩子中的字段时,我在Google上发现了这篇文章。 我不能按照你所做的那样去做,因为你的目标只是刷新Doctrine-Record,而不是在DB中更新它(从我理解的^^)
要在DB中执行更新,我不得不使用lollowing代码(我很惊讶我不得不再次调用“save”)
public function preInsert(Doctrine_Event $event)
{
/* @var $weighSameDate Doctrine_Collection */
$weighSameDate = Doctrine::getTable('BiometryWeightData')
->createQuery()
->where('user_id=?', $this->getUserId())
->where('date=?', $this->getDate())
->execute();
if (count($weighSameDate)) {
/* @var $weight BiometryWeightData */
$weight = $weighSameDate->getFirst();
if ($weight->getWeight() != $this->getWeight()) {
$previous = clone $this;
$this->assignIdentifier($weight->getId());
$this->hydrate($weight->toArray());
$this->setWeight($previous->getWeight());
$this->state(Doctrine_Record::STATE_DIRTY); // STATE_DIRTY to do an update
$this->save();
}
$event->skipOperation();
return;
}
parent::preInsert($event);
}