更新域模型,除了 TYPO3 6.2 中的一个 属性
Update Domain Model except for one property in TYPO3 6.2
我维护了一个在后端管理前端用户的 TYPO3 扩展。因此,我用自己的模型扩展了 FrontendUserRepository。我的扩展提供了 CRUD 操作,我在更新现有人员的密码时遇到了问题。这个想法是只更新密码,如果编辑表单中的密码字段被填充,否则(如果它留空)旧密码值保留在数据库中。
现在使用 TYPO3 4.5 一切正常,但现在我升级到 6.2 后,当提交带有空密码字段的编辑表单时,一个空字符串被保存到数据库中...
这是我的 updateAction()
:
/**
* action update
*
* @param \My\Vendor\Domain\Model\Person $person
*
* @return void
*/
public function updateAction(\My\Vendor\Domain\Model\Person $person) {
// only hash and set password if not empty
if ($person->getPassword() == '') {
// if password was left empty, get current password from database
$oldPerson = $this->personRepository->findByUid($person->getUid());
$person->setPassword($oldPerson->getPassword()));
} else {
$person->setPassword(md5($person->getPassword()));
}
// save updated person to repository
$this->personRepository->update($person);
$this->flashMessageContainer->add('The person data was saved.');
$this->redirect('edit', NULL, NULL, array('person' => $person));
}
有谁知道,为什么 $oldPerson->getPassword()
不 return 来自数据库的密码字段的当前值?还是有另一种方法可以在更新所有其他属性的同时 "skip" 域模型的 属性?奇怪的是它在 TYPO3 4.5 中工作...
Does anybody know, why $oldPerson->getPassword()
does not return the current value for the password field from the database?
这是因为 Extbase 有一种一级缓存:如果对象从持久化中获取一次,则不会在同一请求中第二次从数据库中获取,而是直接 returned 形成内存.
因此,在您的情况下,$person
对象是第一次从数据库中获取,当发生 属性 映射时(内部 Extbase 操作将您的 POST 数据转换为 \My\Vendor\Domain\Model\Person
).
当您调用 $this->personRepository->findByUid($person->getUid());
时,Extbase 不会进行数据库查找,而是直接从内存中获取对象,从而导致 $oldPerson === $person
。由于 $person
已经更改了密码(通过 POST 数据),$oldPerson->getPassword()
return 也更改了密码。
可能的解决方法是清理干净属性
如果模型的 属性 已更改但尚未保存,则 几乎 总是有可能获取原始值(例如,存在于 db 中) .您可以为此使用模型的 _getCleanProperty($propertyName)
方法:
$person->setPassword($oldPerson->_getCleanProperty('password')));
可选 如果您甚至不想更新 password
字段的数据库,您甚至可以 记住干净的 属性 状态,这将告诉 Extbase:不要更新 db:
中的 属性
$person->_memorizePropertyCleanState('password');
注意:记住属性状态后,_getCleanProperty()
会return这个值,这个值是set*()
设置的方法 - 不是数据库中的原始方法(以防您设置不同的值)。
我维护了一个在后端管理前端用户的 TYPO3 扩展。因此,我用自己的模型扩展了 FrontendUserRepository。我的扩展提供了 CRUD 操作,我在更新现有人员的密码时遇到了问题。这个想法是只更新密码,如果编辑表单中的密码字段被填充,否则(如果它留空)旧密码值保留在数据库中。
现在使用 TYPO3 4.5 一切正常,但现在我升级到 6.2 后,当提交带有空密码字段的编辑表单时,一个空字符串被保存到数据库中...
这是我的 updateAction()
:
/**
* action update
*
* @param \My\Vendor\Domain\Model\Person $person
*
* @return void
*/
public function updateAction(\My\Vendor\Domain\Model\Person $person) {
// only hash and set password if not empty
if ($person->getPassword() == '') {
// if password was left empty, get current password from database
$oldPerson = $this->personRepository->findByUid($person->getUid());
$person->setPassword($oldPerson->getPassword()));
} else {
$person->setPassword(md5($person->getPassword()));
}
// save updated person to repository
$this->personRepository->update($person);
$this->flashMessageContainer->add('The person data was saved.');
$this->redirect('edit', NULL, NULL, array('person' => $person));
}
有谁知道,为什么 $oldPerson->getPassword()
不 return 来自数据库的密码字段的当前值?还是有另一种方法可以在更新所有其他属性的同时 "skip" 域模型的 属性?奇怪的是它在 TYPO3 4.5 中工作...
Does anybody know, why
$oldPerson->getPassword()
does not return the current value for the password field from the database?
这是因为 Extbase 有一种一级缓存:如果对象从持久化中获取一次,则不会在同一请求中第二次从数据库中获取,而是直接 returned 形成内存.
因此,在您的情况下,$person
对象是第一次从数据库中获取,当发生 属性 映射时(内部 Extbase 操作将您的 POST 数据转换为 \My\Vendor\Domain\Model\Person
).
当您调用 $this->personRepository->findByUid($person->getUid());
时,Extbase 不会进行数据库查找,而是直接从内存中获取对象,从而导致 $oldPerson === $person
。由于 $person
已经更改了密码(通过 POST 数据),$oldPerson->getPassword()
return 也更改了密码。
可能的解决方法是清理干净属性
如果模型的 属性 已更改但尚未保存,则 几乎 总是有可能获取原始值(例如,存在于 db 中) .您可以为此使用模型的 _getCleanProperty($propertyName)
方法:
$person->setPassword($oldPerson->_getCleanProperty('password')));
可选 如果您甚至不想更新 password
字段的数据库,您甚至可以 记住干净的 属性 状态,这将告诉 Extbase:不要更新 db:
$person->_memorizePropertyCleanState('password');
注意:记住属性状态后,_getCleanProperty()
会return这个值,这个值是set*()
设置的方法 - 不是数据库中的原始方法(以防您设置不同的值)。