I’d like to show a login and a registration form on the same page. However it seems that we cannot render the same template with different form variables in different two actions in a controller.
Here is what I mean;
class SecurityController extends Controller { /** * @Route("/", name="login") */ public function loginAction(Request $request) { //Check if the user is already authenticated if($this->container->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { return $this->redirect($this->generateUrl('dashboard')); } $authenticationUtils = $this->get('security.authentication_utils'); // get the error if there is one $error = $authenticationUtils->getLastAuthenticationError(); // last username entered by the user $lastUsername = $authenticationUtils->getLastUsername(); $this->addFlash( 'welcome', 'Welcome back!' ); return $this->render( '::landing.html.twig', array( // last username entered by the user 'last_username' => $lastUsername, 'error' => $error, ) ); $registrationform = $this->get('form.factory')->createNamedBuilder('registrationform', UserType::class); } /** * @Route("/register", name="register") */ public function registerAction(Request $request) { //Check authentication if($this->container->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { return $this->redirect($this->generateUrl('dashboard')); } // get the authentication utils $authenticationUtils = $this->get('security.authentication_utils'); // get the login error if there is one $error = $authenticationUtils->getLastAuthenticationError(); // last username entered by the user $lastUsername = $authenticationUtils->getLastUsername(); // build the form $user = new User(); $form = $this->createForm(UserType::class, $user); // handle the submit (will only happen on POST) $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $user->setRoles(array('ROLE_USER')); // Encode the password (you could also do this via Doctrine listener) $password = $this->get('security.password_encoder') ->encodePassword($user, $user->getPlainPassword()); $user->setPassword($password); // save the User! $em = $this->getDoctrine()->getManager(); $em->persist($user); $em->flush(); $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles()); $this->get('security.token_storage')->setToken($token); $this->get('session')->set('_security_main', serialize($token)); // ... do any other work - like sending them an email, etc // maybe set a "flash" success message for the user $this->addFlash( 'success', 'Please complete your profile now.' ); $message = Swift_Message::newInstance() ->setSubject('You have successfully signed up!') ->setFrom('no-reply@kampweb.com') ->setTo($user->getUsername()) ->setBody($this->renderView( ':emails:registration.html.twig'),'text/html'); $this->get('mailer')->send($message); return $this->redirectToRoute('update'); } else{ $errors = $this->get('validator')->validate( $user ); } return $this->render( '::landing.html.twig', array( 'form' => $form->createView(), 'last_username' => $lastUsername, 'error' => $error, ) ); }
}
Above I have my login and registration action. I’d like to pass the ‘form’ variable to the same twig template that I render with login action. When I try to do that I’m getting the following exception.
Variable "form" does not exist in ::landing.html.twig at line 50 500 Internal Server Error - Twig_Error_Runtime
Advertisement
Answer
I would do it like this
2 twig files –
login.html.twig and register.html.twig – Every file render by himself the action
now the third twig file called baseLogin.html.twig
in this file, I render the two files (login and register) by calling controller
For example
baseLogin.html.twig
<div> {{ render(controller('UserBundle:Security:login')) }} </div> <div> {{ render(controller('UserBundle:Registration:register')) }} </div>