I have a problem that i was searching on the interwebz but no solution found!
My problem is: i want to override registration and show fosuserbundle's registration form in my view (or in overrided view). Not working...
Always telling the same story;
Copy to:
app/Resources/FOSUserBundle/views/......
I have already did it!
I have override a controller that works for registration:
<?php
namespace CS\UserBundle\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
use Symfony\Component\HttpFoundation\Request;
class RegistrationController extends BaseController
{
public function registerAction(Request $request)
{
$form = $this->container->get('fos_user.registration.form');
$formHandler = $this->container->get('fos_user.registration.form.handler');
$confirmationEnabled = $this->container->getParameter('fos_user.registration.confirmation.enabled');
$process = $formHandler->process($confirmationEnabled);
if ($process) {
$user = $form->getData();
if ($confirmationEnabled) {
$this->container->get('session')->set('fos_user_send_confirmation_email/email', $user->getEmail());
$route = 'fos_user_registration_check_email';
} else {
$this->authenticateUser($user);
$route = 'fos_user_registration_confirmed';
}
$this->setFlash('fos_user_success', 'registration.flash.user_created');
$url = $this->container->get('router')->generate($route);
return new RedirectResponse($url);
}
return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.'.$this->getEngine(), array(
'form' => $form->createView(),
));
}
}
Routing:
register:
pattern: /register
defaults: { _controller: CSUserBundle:Registration:register }
Here is my override directory:
If you only want to make the registration form within your template, you could simply override Resources/views/layout.html.twig. It is simpler than the override controller, routes, etc.
It is the general layout for FOSUserBundle. Here you can find a detailed description on how to do.
Related
I'm having problems getting a redirect after login to work in Symfony.
It works for some pages but for others, the last_route session variable is being set to a users profile picture that uses the liip_imagine_filter:
"last_route" => [
"name" => "liip_imagine_filter",
"params" => [
"filter" => "profile_picture"
"path" => "frederick-jacobson/5ba60fc93056b.png"
]
]
LoginFormAuthenticator:
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
/*...*/
protected function getDefaultSuccessRedirectURL()
{
/** #var Session $session */
$session = $this->container->get('session');
$priorPage = $session->get('last_route');
return $this->router->generate($priorPage['name'], $priorPage['params']);
// return $this->router->generate('poll_index');
}
}
This means that it tries to redirect to an image URL.
services.yml:
poll.last_route_event_listener:
class: PollBundle\Services\LastRouteListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 30 }
LastRouteListener:
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernel;
class LastRouteListener
{
public function onKernelRequest(GetResponseEvent $event)
{
// Do not save subrequests
if ($event->getRequestType() !== HttpKernel::MASTER_REQUEST) {
return;
}
$request = $event->getRequest();
$session = $request->getSession();
$routeName = $request->get('_route');
$routeParams = $request->get('_route_params');
if ($routeName[0] == '_') {
return;
}
$routeData = ['name' => $routeName, 'params' => $routeParams];
// Do not save same matched route twice
$thisRoute = $session->get('this_route', []);
if ($thisRoute == $routeData) {
return;
}
$session->set('last_route', $thisRoute);
$session->set('this_route', $routeData);
}
}
Can someone please help me work out what I'm doing wrong and/or tell me the correct way to handle redirecting to the page prior to login?
As pointed out in the comments below my question. I was using a custom listener that was picking up the liip_imagine_filter route and setting it to the last_route session variable.
I could just add a check in to the listener, like this:
if ($routeName[0] == '_' || $routeName == 'liip_imagine_filter') {
return;
}
But a better way to handle it is to use the built in Symfony\Component\Security\Http\Util\TargetPathTrait
It is usually set automatically when a user hits a restricted page, but it can be set manually with $this->saveTargetPath($request->getSession(), $providerKey, $request->getUri());
Then you can use $targetPath to find the route to redirect to in LoginFormAuthenticator:
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
/*...*/
use TargetPathTrait;
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
$targetPath = $this->getTargetPath($request->getSession(), $providerKey);
if (!$targetPath || $request->getBaseUrl() && !strpos($targetPath, $request->getBaseUrl())) {
$targetPath = $this->container->get('router')
->generate('poll_index');
}
return new RedirectResponse($targetPath);
}
}
Im trying to override FOSUser RegistrationController. In SF2 I used to copy the controller in my AppBundle\Controller and add bundle inheritance
class AppBundle extends Bundle
{
public function getParent()
{
return 'FOSUserBundle';
}
}
In symfony 3 the bundle inheritance is not supported anymore, and when I do the same as above, I end up with errors saying that symfony cannot find the services used in this controller (cannot autowire..)
Does anyone has an idea how to override FOSUser in SF3 please ?
<?php
// src/Acme/UserBundle/Controller/RegistrationController.php
namespace Acme\UserBundle\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
class RegistrationController extends BaseController
{
public function registerAction()
{
$form = $this->container->get('fos_user.registration.form');
$formHandler = $this->container->get('fos_user.registration.form.handler');
$confirmationEnabled = $this->container->getParameter('fos_user.registration.confirmation.enabled');
$process = $formHandler->process($confirmationEnabled);
if ($process) {
$user = $form->getData();
/*****************************************************
* Add new functionality (e.g. log the registration) *
*****************************************************/
$this->container->get('logger')->info(
sprintf('New user registration: %s', $user)
);
if ($confirmationEnabled) {
$this->container->get('session')->set('fos_user_send_confirmation_email/email', $user->getEmail());
$route = 'fos_user_registration_check_email';
} else {
$this->authenticateUser($user);
$route = 'fos_user_registration_confirmed';
}
$this->setFlash('fos_user_success', 'registration.flash.user_created');
$url = $this->container->get('router')->generate($route);
return new RedirectResponse($url);
}
return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.twig', array(
'form' => $form->createView(),
));
}
}
from the official documentation
I'm not truly sure of my answer because i didnt override the FOS User Bundle but the Easy Admin Bundle in sf4. Here's what i did : create a new controller in src/Controller/MyCustomController. Next i extended MyCustomController with the Controller i wanted to overide :
<?php
namespace App\Controller;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
class MyCustomController extends BaseAdminController {}
?>
I guess you can do the same in sf3 with the FosUserBundle.
Hope i'm right !
I'm using FosUserBundle 1.3 and Symfo 2.6.
I need to add addresses (collection type) when I register a new User. Is it possible ?
Address entity has the owner side so when I want to register (create) the user, it returns me an error (contraint integrity userID cannot be null).
I see that I can do something like that into the Controller before the flush :
if($entity->getAddresses() !== null){
foreach($entity->getAddresses() as $address){
$address->setUser($entity);
}
}
Is it best practice ?
Now, where can I do that with Fos ? I think that here seems to be the right place but I'm not sure and can I override it ?
RegistrationFormHandler
...
public function process($confirmation = false)
{
$user = $this->createUser();
$this->form->setData($user);
if ('POST' === $this->request->getMethod()) {
$this->form->bind($this->request);
if ($this->form->isValid()) {
// I WOULD LIKE TO COPY MY CODE HERE
//
$this->onSuccess($user, $confirmation);
return true;
}
}
return false;
}
...
This will work since 2.0 version.
I think you should register you own EventListener that will listen to FOSUserEvents::REGISTRATION_SUCCESS or FOSUserEvents::REGISTRATION_COMPLETED and then you can add there your custom logic without controller overriding. Something like:
RegistrationListener class:
namespace AppBundle\EventListener;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class RegistrationListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_COMPLETED => 'completed'
);
}
public function completed(FilterUserResponseEvent $event)
{
$user = $event->getUser();
// add your custom logic here
}
}
and services.yml:
app_listener.registration:
class: AppBundle\EventListener\RegistrationListener
tags:
- { name: kernel.event_subscriber }
Remember to add proper dependencies to your listener class if needed.
For 1.3 version
You need to create a child bundle whose parent is FOSUserBundle and ovveride: RegistraionController::registerAction in your case:
<?php
namespace Acme\UserBundle\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
class RegistrationController extends BaseController
{
public function registerAction()
{
$form = $this->container->get('fos_user.registration.form');
$formHandler = $this->container->get('fos_user.registration.form.handler');
$confirmationEnabled = $this->container->getParameter('fos_user.registration.confirmation.enabled');
$process = $formHandler->process($confirmationEnabled);
if ($process) {
$user = $form->getData();
// you custom logic
if ($confirmationEnabled) {
$this->container->get('session')->set('fos_user_send_confirmation_email/email', $user->getEmail());
$route = 'fos_user_registration_check_email';
} else {
$this->authenticateUser($user);
$route = 'fos_user_registration_confirmed';
}
$this->setFlash('fos_user_success', 'registration.flash.user_created');
$url = $this->container->get('router')->generate($route);
return new RedirectResponse($url);
}
return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.'.$this->getEngine(), array(
'form' => $form->createView(),
));
}
}
I need to override the regitration contrller by 1 in my bundle.
I made the file inside userbundle, but it gives that error that I saw a lot at stackoverflow but no reply.
Error is
ContextErrorException: Runtime Notice: Declaration of TA\UserBundle\Controller\RegistrationController::registerAction() should be compatible with FOS\UserBundle\Controller\RegistrationController::registerAction(Symfony\Component\HttpFoundation\Request $request) in E:\php\xampp\htdocs\platform\src\TA\UserBundle\Controller\RegistrationController.php line 9
Controller
<?php
//src\TA\UserBundle\Controller\RegistrationController.php
namespace TA\UserBundle\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
class RegistrationController extends BaseController
{
public function registerAction()
{
$form = $this->container->get('fos_user.registration.form');
$formHandler = $this->container->get('fos_user.registration.form.handler');
$confirmationEnabled = $this->container->getParameter('fos_user.registration.confirmation.enabled');
$process = $formHandler->process($confirmationEnabled);
if ($process) {
$user = $form->getData();
/*****************************************************
* Add new functionality (e.g. log the registration) *
*****************************************************/
$this->container->get('logger')->info(
sprintf('New user registration: %s', $user)
);
if ($confirmationEnabled) {
$this->container->get('session')->set('fos_user_send_confirmation_email/email', $user->getEmail());
$route = 'fos_user_registration_check_email';
} else {
$this->authenticateUser($user);
$route = 'fos_user_registration_confirmed';
}
$this->setFlash('fos_user_success', 'registration.flash.user_created');
$url = $this->container->get('router')->generate($route);
return new RedirectResponse($url);
}
return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.'.$this->getEngine(), array(
'form' => $form->createView(),
));
}
}
even when I changed
public function registerAction()
to
public function registerAction(Request $request)
error became
ContextErrorException: Runtime Notice: Declaration of TA\UserBundle\Controller\RegistrationController::registerAction() should be compatible with FOS\UserBundle\Controller\RegistrationController::registerAction(Symfony\Component\HttpFoundation\Request $request) in E:\php\xampp\htdocs\platform\src\TA\UserBundle\Controller\RegistrationController.php line 9
This one worked for me. My Example:
<?php
namespace FRMKS\FoodR\FoodApp\Controller;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
use Symfony\Component\HttpFoundation\Request;
class RegistrationController extends BaseController
{
public function registerAction(Request $request)
{
$response = parent::registerAction($request);
// ... do custom stuff
return $response;
}
}
Basically you need to add use of request, parameter 'Request $request' to 'registerAction' function and pass 'request' param to parent 'registerAction' function
Did you try to put the full 'Symfony\Component\HttpFoundation\Request $request' into your method definition?
public function registerAction(Symfony\Component\HttpFoundation\Request $request) {}
I would like to override the ProfileController's edit action of FosUserBundle. I've created the controller in my own UserBundle, copied the edit action into it and made some changes. In this controller there is a check if the logged in user is an instanceOf UserInterFace. Apparently it's not because it throws an access denied exception when I go to /profile/edit
Why isn't the logged in user an instanceOf UserInterFace anymore?
Controller:
namespace Tennisconnect\UserBundle\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use FOS\UserBundle\Controller\ProfileController as BaseController;
class ProfileController extends BaseController
{
/**
* Edit the user
*/
public function editAction()
{
$user = $this->container->get('security.context')->getToken()->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}
$form = $this->container->get('fos_user.profile.form');
$formHandler = $this->container->get('fos_user.profile.form.handler');
$process = $formHandler->process($user);
if ($process) {
$user->upload();
$this->setFlash('fos_user_success', 'profile.flash.updated');
return new RedirectResponse($this->container->get('router')->generate('fos_user_profile_show'));
}
return $this->container->get('templating')->renderResponse(
'FOSUserBundle:Profile:edit.html.'.$this->container->getParameter('fos_user.template.engine'),
array('form' => $form->createView(), 'theme' => $this->container->getParameter('fos_user.template.theme'))
);
}
}
Reading your code snippet, I would say it's simply because you don't match the full qualified namespace of UserInterface.
Either import the class with:
use Symfony\Component\Security\Core\User\UserInterface;
or modify your code like this:
if (!is_object($user) || !$user instanceof Symfony\Component\Security\Core\User\UserInterface) {
The cleaner solution is to create a new Bundle "MyFOSBundle", in the bundle class :
getParent()
{
return "FosBundle";
}
Then you write the file you want override on the same location.
http://symfony.com/doc/master/cookbook/bundles/inheritance.html