Обновить модель домена, за исключением одного свойства в TYPO3 6.2

#php #typo3 #extbase #typo3-6.2.x #domain-model

#php #typo3 #extbase #typo3-6.2.x #domain-model

Вопрос:

Я поддерживаю расширение TYPO3, которое управляет внешними пользователями в серверной части. Поэтому я расширяю FrontendUserRepository своей собственной моделью. Мое расширение обеспечивает операции CRUD, и у меня проблема с обновлением пароля существующих пользователей. Идея состоит в том, чтобы обновлять пароль только в том случае, если поле пароля в форме редактирования заполнено, в противном случае (если оно оставлено пустым) старое значение пароля остается в базе данных.

Теперь все работало нормально с TYPO3 4.5, но теперь, после обновления до версии 6.2, пустая строка сохраняется в базе данных при отправке формы редактирования с пустым полем пароля…

Это мой updateAction() :

 /**
 * action update
 *
 * @param MyVendorDomainModelPerson $person
 *
 * @return void
 */
public function updateAction(MyVendorDomainModelPerson $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() почему не возвращает текущее значение для поля пароля из базы данных? Или есть другой способ «пропустить» свойство модели домена при обновлении всех других свойств? Странно то, что оно работало в TYPO3 4.5 …

Ответ №1:

Кто-нибудь знает, $oldPerson->getPassword() почему не возвращает текущее значение для поля пароля из базы данных?

Это связано с тем, что Extbase имеет своего рода кэш 1-го уровня: если объект был извлечен из формы сохранения один раз, он не будет извлечен во второй раз из базы данных во время того же запроса, а будет возвращен непосредственно из памяти.

Итак, в вашем случае $person объект извлекается из базы данных 1-й раз, когда происходит сопоставление свойств (внутренняя операция Extbase, которая преобразует ваши данные POST в экземпляр MyVendorDomainModelPerson ).

Когда вы вызываете $this->personRepository->findByUid($person->getUid()); Extbase, он не выполняет поиск в базе данных, а извлекает объект непосредственно из памяти, что приводит к $oldPerson === $person . И поскольку $person пароль уже изменен (через данные POST), $oldPerson->getPassword() возвращает также измененное значение.

Возможное решение для этого — получить чистое свойство

Если свойство модели было изменено, но еще не сохранено, почти всегда есть возможность получить исходное значение (например, то, которое существует в БД). Для этого вы можете использовать _getCleanProperty($propertyName) метод model:

 $person->setPassword($oldPerson->_getCleanProperty('password')));
  

При желании, если вы даже не хотите обновлять password поле в БД, вы можете даже запомнить состояние чистого свойства, которое сообщит Extbase: не обновлять свойство в БД:

 $person->_memorizePropertyCleanState('password');
  

Примечание: после того, как вы запомните состояние свойства, _getCleanProperty() будет возвращено значение, которое было установлено set*() методом, а не исходное, присутствующее в БД (в случае, если вы установили другое значение).

Комментарии:

1. Спасибо за этот подробный ответ! _getCleanProperty() Функция работает