Extending FOSUserBundles Registration to have different fields stored in different tables? - php

I am new with Symfony2 and FOSUserBundle. I am using Symfony2 version 2.4.1. I would like to extend FOSUserBundle in a few ways. I want to add fields to the registration form, some fields i would like to add to the user table which contains username and password but i would like to add fields that get added to a different table. (I think i have to rewrite the registerController??)
Currently i have inherited FOSUserBundle into my own UserBundle. I have tried to simply add fields to the current registration form by following the documentation but i keep returning this error.
Could not load type "acme_user_registration"
// src/Fixie/UserBundle/Entity/User.php
<?php
namespace Fixie\UserBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*
* #Assert\NotBlank(message="Please enter your name.", groups={"Registration", "Profile"})
* #Assert\Length(
* min=3,
* max="255",
* minMessage="The name is too short.",
* maxMessage="The name is too long.",
* groups={"Registration", "Profile"}
* )
*/
protected $name;
public function __construct()
{
parent::__construct();
// your own logic
}
}
I then add the name field to the form builder
// src/Fixie/UserBundle/Form/Type/RegistrationFormType.php
<?php
namespace Fixie\UserBundle\Form\Type;
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
class RegistrationFormType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
// add your custom field
$builder->add('name');
}
public function getName()
{
return 'acme_user_registration';
}
}
I then go on to declare the custom form type:
// src/Fixie/UserBundle/Resources/config/services.yml
services:
acme_user.registration.form.type:
class: Fixie\UserBundle\Form\Type\RegistrationFormType
arguments: [%fos_user.model.user.class%]
tags:
- { name: form.type, alias: acme_user_registration }
Then updated config:
fos_user:
db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
firewall_name: main
user_class: Fixie\UserBundle\Entity\User
registration:
form:
type: acme_user_registration
//AppKernel.php
<?php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = array(
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new Fixie\WelcomeBundle\WelcomeBundle(),
new Fixie\UserBundle\UserBundle(),
new FOS\UserBundle\FOSUserBundle(),
);
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
}
return $bundles;
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}
}
// Fixie/UserBundle/UserBundle.php
<?php
namespace Fixie\UserBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class UserBundle extends Bundle
{
public function getParent()
{
return 'FOSUserBundle';
}
}
My main questions are:
Can anyone see an error with my current code?
In relation to extending the form to have multiple fields being stored in multiple tables. What are the step i have to take? Do i rewrite the logic of the controller and the form???
Any help would be very much appreciated.

Ok.
In appKerenl.php you have
new Fixie\UserBundle\UserBundle(),
But in service.yml
class: Acme\UserBundle\Form\Type\RegistrationFormType
Maybe it should be:
class: Fixie\UserBundle\Form\Type\RegistrationFormType
If in result of command app/console container:debug you can't see acme_user.registration.form.type it means that your service don't register and fos_user can't see you service, and can't find your form type.
My UserBundle store in Webmil/Joint/UserBundle. In UserBundle folder I have file WebmilJointUserBundle.php
My file:
<?php
namespace Webmil\Joint\UserBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class WebmilJointUserBundle extends Bundle
{
public function getParent()
{
return 'FOSUserBundle';
}
}
So I think that your problem in this file. Can you compare file and your file, and maybe you will find error.

With me it was that i had already a services.yml in app/config, so the one in my bundle was ignored. In the end I added the registry to this file
# app/config/services.yml
services:
# [other already existing services]
acme_user.registration.form.type:
class: Acme\UserBundle\Form\Type\RegistrationFormType
tags:
- { name: form.type, alias: acme_user_registration }

Related

InvalidArgumentException Symfony4

I have a problem with my application after I moved it to docker container. I newbie with Symfony and I cannot understand where the problem is.
After I want to call my UserController index action my browser throws an error:
Controller "App\Controller\UserController" has required constructor arguments and does not exist in the container. Did you forget to define such a service?
Too few arguments to function App\Controller\UserController::__construct(), 0 passed in /projekty/taskit/vendor/symfony/http-kernel/Controller/ControllerResolver.php on line 133 and exactly 1 expected
My services.yaml file:
parameters:
locale: 'en'
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
App\Entity\UserRepositoryInterface: '#App\DTO\UserAssembler'
UserController.php file
<?php
namespace App\Controller;
use App\Service\UserService;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
/**
* Class UserController
* #package App\Controller
*/
class UserController extends AbstractController
{
/**
* #var UserService
*/
private $userService;
/**
* #param UserService $userService
*/
public function __construct(UserService $userService)
{
$this->userService = $userService;
}
/**
* #Route("/users/", name="users_index")
*/
public function index()
{
$users = $this->userService->findAll();
return $this->render('user/index.html.twig', array('users' => $users));
}
}
And my UserService.php file code
<?php
namespace App\Service;
use App\Entity\UserRepositoryInterface;
use Doctrine\ORM\EntityNotFoundException;
/**
* Class UserService
* #package App\Service
*/
class UserService
{
/**
* #var UserRepositoryInterface
*/
private $userRepository;
/**
* #param UserRepositoryInterface $userRepository
*/
public function __construct(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
/**
* #return array
* #throws EntityNotFoundException
*/
public function findAll() : array
{
$users = $this->userRepository->findAll();
if (is_null($users)) {
throw new EntityNotFoundException('Table users is empty');
}
return $users;
}
}
It seems to me you are doing a lot of unnecessary things, which are already part of the framework. Like your service, what does it do? You can call your repositories directly from your controller. And in your controller, you are declaring variables and constructing which is also unnecessary. Just use dependency injection in your function in the controller. This little bit of code should work and replace both your controller and your service (which again, you can get rid of).
<?php
namespace App\Controller;
use App\Repository\UserRepository;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
/**
* Class UserController
* #package App\Controller
*/
class UserController extends AbstractController
{
/**
* #Route("/users/", name="users_index")
*/
public function index(UserRepository $userRepository)
{
$users = $this->userRepository->findAll();
return $this->render('user/index.html.twig', array('users' => $users));
}
}

FOSUserBundle event REGISTRATION_INITIALIZE not triggered

I wanted to set password automatically when one register the form. So I use REGISTRATION_INITIALIZE to trigger the event. Unfortunately it's not working.
Listener:
<?php
namespace Acme\UserBundle\EventListener;
use Doctrine\ORM\EntityManager;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class RegistrationListener implements EventSubscriberInterface
{
/**
* #var EntityManager
*/
private $em;
/**
* #param \Doctrine\ORM\EntityManager $entityManager
*/
public function __construct(EntityManager $entityManager)
{
$this->em = $entityManager;
}
/**
* {#inheritdoc}
*/
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_INITIALIZE => 'onRegistrationInit',
);
}
public function onRegistrationInit(UserEvent $userEvent)
{
$user = $userEvent->getUser();
$user->setPassword('abcdeffffff');
}
Services:
#src/Acme/UserBundle/Resources/config/services.yml
services:
acme_user.registration:
class: Acme\UserBundle\EventListener\RegistrationListener
arguments:
entityManager: "#doctrine.orm.entity_manager"
tags:
- { name: kernel.event_subscriber}
So the password is not setting and it shows the password should not be blank.
What am I doing wrong? Any help!
EDIT:
The problem was I was defining service at the wrong place.
Instead of src/Acme/UserBundle/Resources/config/services.yml, It should be app/config/services.yml.
I saw src/Acme/UserBundle/Resources/config/services.ymlin http://symfony.com/doc/master/bundles/FOSUserBundle/controller_events.html, But was not working for me!
Maybe I am wrong, but I think your service definition uses features from Symfony 3.3 but you are using Symfony 3.2.8, e.g.
New in version 3.3: The ability to configure an argument by its name ($adminEmail) was added in Symfony 3.3. Previously, you could configure it only by its index (2 in this case) or by using empty quotes for the other arguments.
Try updating your service definition to:
#src/Acme/UserBundle/Resources/config/services.yml
services:
acme_user.registration:
class: Acme\UserBundle\EventListener\RegistrationListener
arguments: ["#doctrine.orm.entity_manager"]
tags:
- { name: kernel.event_subscriber}
And a remark: as you are actually using a subscriber you should rename the class RegistrationListener to RegistrationSubscriber.

Symfony FOSUserBundle cannot override form, no effect

with this article I'm trying to override RegisterFormType.php, and do not see the result, but Symfony Profiler shows in Forms fos_user_registration is overwritten by app_user_registration.
Firstly, I have in AppKernel.php:
new FOS\UserBundle\FOSUserBundle(),
new Sonata\UserBundle\SonataUserBundle('FOSUserBundle'),
new Application\Sonata\UserBundle\ApplicationSonataUserBundle(),
services.yml
app.form.registration:
class: Application\Sonata\UserBundle\Form\RegistrationFormType
tags:
- { name: form.type, alias: app_user_registration }
config.yml:
fos_user:
db_driver: orm # can be orm or odm
firewall_name: main
user_class: Application\Sonata\UserBundle\Entity\User
use_listener: true
group:
group_class: Application\Sonata\UserBundle\Entity\Group
group_manager: sonata.user.orm.group_manager # If you're using doctrine orm (use sonata.user.mongodb.group_manager for mongodb)
service:
user_manager: sonata.user.orm.user_manager # If you're using doctrine orm (use sonata.user.mongodb.user_manager for mongodb)
registration:
form:
type: app_user_registration
#validation_groups: [AppRegistration]
profile:
form:
name: app_user_profile
src/Application/Sonata/UserBundle/Form/RegistrationForm.php:
namespace Application\Sonata\UserBundle\Form;
use ...
class RegistrationFormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('fullName')
;
}
public function getParent() {
return "fos_user_registration";
}
public function getName() {
return 'app_user_registration';
}
}
src/Application/Sonata/UserBundle/Entity/User.php:
namespace Application\Sonata\UserBundle\Entity;
use Sonata\UserBundle\Entity\BaseUser as BaseUser;
class User extends BaseUser
{
/**
* #var int $id
*/
protected $id;
/**
* #var string
*/
protected $fullName;
/**
* #return string
*/
public function getFullName() {
return $this->fullName;
}
/**
* #param string $fullName
*/
public function setFullName($fullName) {
$this->fullName = $fullName;
}
/**
* Get id
*
* #return int $id
*/
public function getId() { return $this->id;}
}
As other way (I think not correct) tried to override RegistrationController.php in my custom directory, changed there $form = $this->container->get('app.form.registration') (alias for my form), but I receive error Attempted to call an undefined method named "createView" of class "Application\Sonata\UserBundle\Form\RegistrationFormType. After this I changed this class' parent extended class from ContentAware to Controller, and can see form and new field, but after submitting receive unknown error, even in Profiler not written about it name.
Symfony 2.8.18, FOSUserBundle 1.3.7. Thank you for your time.
Did you update the configuration of the FOSUserBundle in config.yml ?
fos_user:
# ...
registration:
form:
name: app_user_registration

Symfony2 Update Error.No mapping file

I am using Symfony2 and when i try to append FOSUserBundle, but i got an error
(bin/console doctrine:schema:update --force)
//---------------------------------------------------------------Appkernel.php
public function registerBundles()
{
$bundles = [
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new AppBundle\AppBundle(),
new main\kipeoBundle\kipeoBundle(),
new FOS\UserBundle\FOSUserBundle(),
];
//----------------------------------------------------app/config/config.yml
fos_user:
db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
firewall_name: main
user_class: main\kipeoBundle\Entity\User
//----------------------------------------src-main>kipeoBundle>Entity>User.php
namespace main\kipeoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
public function __construct()
{
parent::__construct();
// your own logic
}
}
//----------------------------------------------------app/config/routing.yml
fos_user:
resource: "#FOSUserBundle/Resources/config/routing/all.xml"
In doctrine config, you need to specify the mapping type. In this case, "annotation"

FOSUserBundle (Symfony2). I have some questions

1) How can I add new fields in table and in registration action (show new fields on reg page)? For example: I want to add new fields last_name, age.
2) I added new listener for REGISTRATION_COMPLETED
/src/Acme/UserBundle/EventListener/RegistrationCompletedListener.php:
<?php
namespace Acme\UserBundle\EventListener;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* Listener
*/
class RegistrationCompletedListener implements EventSubscriberInterface
{
private $router;
public function __construct(UrlGeneratorInterface $router)
{
$this->router = $router;
}
/**
* {#inheritDoc}
*/
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_COMPLETED => 'onRegistrationCompletedSuccess',
);
}
public function onRegistrationCompletedSuccess(FormEvent $event)
{
$url = $this->router->generate('homepage');
$event->setResponse(new RedirectResponse($url));
}
}
/src/Acme/UserBundle/Resources/config/services.yml:
services:
acme_user.registration_completed:
class: Acme\UserBundle\EventListener\RegistrationCompletedListener
arguments: [#router]
tags:
- { name: kernel.event_subscriber }
Why don't work?
1) You should extend Base User class and add there your new fields, like this:
namespace Your\CustomBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* User
*
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #var string
*
* #ORM\Column(name="first_name", type="string", length=255)
*/
private $firstName;
/**
* #var string
*
* #ORM\Column(name="last_name", type="string", length=255)
*/
private $lastName;
}
And update appconfig/config.yml:
#FOSLUserBundle Configuration
fos_user:
user_class: Your\CustomBundle\Entity
Then you need extend and configure new registration form. Here is a link how you can do that.
[Edit]:
2)
Create event listener like this:
namespace Your\Bundle\EventListener;
use FOS\UserBundle\Event\FilterUserResponseEvent;
class UserListener
{
public function onRegistrationCompleted(FilterUserResponseEvent $event){
$user = $event->getUser();
//do sth....
}
}
And register service for that:
services:
some_name.security.registration_listener:
class: Your\Bundle\EventListener\UserListener
tags:
- { name: kernel.event_listener, event: fos_user.registration.completed, method: onRegistrationCompleted }

Categories