An often overlooked step when updating an entity is reverting invalid changes. While often unnecessary, doing so is borderline good practice.
Here is a typical edit controller which renders a pre-filled form and validates changes to the entity being edited.
/**
* Edit user attributes
*
* @param Request $request HTTP request object
*
* @return Response HTTP response object
*/
public function editUserAction(Request $request)
{
$em = $this->getDoctrine()->getEntityManager();
$user = $em->getRepository('FooDemoBundle:User')
->find($request->get('user_slug'));
$userForm = $this->createForm(new UserType(), $user);
if ('POST' === $request->getMethod()) {
$userForm->bind($request->request->get($userForm->getName()));
$isValid = $userForm->isValid();
if ($isValid) {
$em->flush();
return $this->redirect($this->generateUrl('view_user'));
}
}
return $this->render('FooDemoBundle:User:edit_user.html.twig', array (
'userForm' => $userForm->createView(),
));
}
Since invoking $userForm->bind(...)
also updates $user
with the bound values, lines past $userForm->bind(...)
will only have access to a $user
object having the new attribute values.
// $user->getSlug() >> 'foo'
$userForm->bind($request->request->get($userForm->getName()));
// $user->getSlug() >> 'bar'
While this behavior conveniently saves additional code for updating the entity's attributes, it is especially undesirable when the updated values are invalid, and $user
has to be used later in the controller, or in the template.
Since binding behavior is inherent to the form, the most convenient solution would be to revert the attribute values of the entity. To this end, Doctrine's EntityManager
has refresh()
which removes unpersisted changes to an entity.
$userForm->bind($request->request->get($userForm->getName()));
...
if (!isValid) {
// Revert attribute values
$em->refresh($foo);
}