i installed PUGXMultiUserBundle using this documentation and i follow this, but i have an error
Type error: Argument 1 passed to FOS\UserBundle\Controller\RegistrationController::__construct() must implement interface Symfony\Component\EventDispatcher\EventDispatcherInterface, none given...
fos_user:
db_driver: orm
firewall_name: main
user_class: AppBundle\Entity\User
service:
user_manager: pugx_user_manager
from_email:
address: "%mailer_user%"
sender_name: "%mailer_user%"
pugx_multi_user:
users:
simple_user:
entity:
class: AppBundle\Entity\SimpleUser
registration:
form:
type: AppBundle\Form\SimpleUserType
name: fos_user_registration_form
validation_groups: [Registration, Default]
template: AppBundle:Registration:simple_user.form.html.twig
society_user:
entity:
class: AppBundle\Entity\SocietyUser
registration:
form:
type: AppBundle\Form\SocietyUserType
name: fos_user_registration_form
validation_groups: [Registration, Default]
template: AppBundle:Registration:society_user.form.html.twig
and this is my RegistrationSimpleUserController:
/**
* Class RegistrationSimpleUserController
* #package AppBundle\Controller
*
*/
class RegistrationSimpleUserController extends Controller
{
/**
* #return mixed
*
*
* #Route("/register/simple", name="registration_simple_user")
*/
public function registerAction()
{
return $this->container
->get('pugx_multi_user.registration_manager')
->register('Acme\UserBundle\Entity\UserOne');
}
}
I think this is a bug in the PUGX bundle which is not up to date.
They define the FOSUserBundle Registration controller as a service like this:
pugx_multi_user.registration_controller:
class: FOS\UserBundle\Controller\RegistrationController
But the RegistrationController in the FOSUserBundle has some dependencies:
public function __construct(EventDispatcherInterface $eventDispatcher, FactoryInterface $formFactory, UserManagerInterface $userManager, TokenStorageInterface $tokenStorage)
{
$this->eventDispatcher = $eventDispatcher;
$this->formFactory = $formFactory;
$this->userManager = $userManager;
$this->tokenStorage = $tokenStorage;
}
I think you can solve it by defining an alias like this:
pugx_multi_user.registration_controller:
alias: fos_user.registration.controller
Or overriding the whole definition in your own services.yml:
pugx_multi_user.registration_controller:
class: FOS\UserBundle\Controller\RegistrationController
arguments:
- '#event_dispatcher'
- '#fos_user.registration.form.factory'
- '#fos_user.user_manager'
- '#security.token_storage'
Related
For a new project, I use Symfony 4.3 and FosUserBundle 2.1. I installed with success this bundle but when I try to use it, I've got somes issues.
When I try to access on login page (http://127.0.0.1:8000/login), it works well. But, on register page I've got some errors:
Property "superAdmin" does not exist in class "App\Entity\User"
I try to add the properties superAdmin and group in my User entity (I don't know if it's a good idea). The page is displayed correctly. Now, when I try to submit register form, 4 errors appear (all fields are filled):
This value should not be null. => "data.password"
This value should not be null. => "data.superAdmin"
This value should not be null. => "data.groups"
This value should not be null. => "data.group"
Is FosUserBundle compatible with Symfony 4.3? How to solve these problems? Are there alternatives?
here is the solution :
==> you must add $group and $superAdmin in your entity User, so you can just set $group to nullable=true, and $superAdmin is boolean you can set it to true or false. NB: you must rename the column group because this group is reserved word in mysql , I set these in constructor so you can set these in custom form to like :
<?php
// src/AppBundle/Entity/User.php
namespace App\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #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", nullable=true)
*/
protected $prenom;
/**
* #ORM\Column(type="boolean")
*/
protected $superAdmin;
/**
* #ORM\Column(name="giroupy", type="string", nullable=true)
*/
protected $group;
public function __construct()
{
parent::__construct();
$this->superAdmin = false;
$this->groups = new ArrayCollection();
// your own logic
if (empty($this->registerDate)) {
$this->registerDate = new \DateTime();
}
}
public function getId(): ?int
{
return $this->id;
}
public function getPrenom(): ?string
{
return $this->prenom;
}
public function setPrenom(string $prenom): self
{
$this->prenom = $prenom;
return $this;
}
public function getGroup(): ?string
{
return $this->group;
}
public function setGroup(?string $group): self
{
$this->group = $group;
return $this;
}
public function getSuperAdmin(): ?bool
{
return $this->superAdmin;
}
public function setSuperAdmin($superAdmin): self
{
$this->superAdmin = $superAdmin;
return $this;
}
}
so after to set password you must hook formEvent for event SUBMIT to get the entity User like :
<?php
// src/AppBundle/Form/RegistrationType.php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class RegistrationType extends AbstractType
{
private $userPassWordInterface;
public function __construct(
UserPasswordEncoderInterface $userPassWordInterface
)
{
$this->userPassWordInterface = $userPassWordInterface;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('prenom')
->addEventListener(
FormEvents::SUBMIT,
[$this, 'onSubmit']
)
;
}
public function onSubmit(FormEvent $event)
{
$user = $event->getData();
$form = $event->getForm();
if (!$user) {
return;
}
$passWord = $this->userPassWordInterface->encodePassword($user, $user->getPlainPassword());
$user->setPassWord($passWord);
// checks whether the user has chosen to display their email or not.
// If the data was submitted previously, the additional value that
// is included in the request variables needs to be removed.
}
public function getParent()
{
return 'FOS\UserBundle\Form\Type\RegistrationFormType';
}
public function getBlockPrefix()
{
return 'app_user_registration';
}
// For Symfony 2.x
public function getName()
{
return $this->getBlockPrefix();
}
}
and in security like :
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
App\Entity\User: bcrypt
role_hierarchy:
ROLE_SUPER_ADMIN: ROLE_ADMIN
ROLE_ADMIN: ROLE_USER
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
logout: true
anonymous: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
so after set the form login in your package : config/packages/fos_user.yaml
fos_user:
db_driver: orm # other valid values are 'mongodb' and 'couchdb'
firewall_name: main
user_class: App\Entity\User
registration:
form:
type: App\Form\RegistrationType
from_email:
address: "%mailer_user%"
sender_name: "%mailer_user%"
and don't forget to load routes in : config/routes/fos_user.yaml
fos_user:
resource: "#FOSUserBundle/Resources/config/routing/all.xml"
The problem is much simpler. FOSUserBundle is still compatible with Symfony 4.3, it's just doesn't work with 4.3 validator component automatic validation settings, which is turned on by default:
framework:
validation:
email_validation_mode: html5
# Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
auto_mapping: # <----- REMOVE THIS THIS
App\Entity\: [] # <-------- AND THIS
It solved the problem in my case, but it also means that you need to set validation rules manually.
I am upgrading from Symfony 3.3 to Symfony 4.
KNPMenu was running fine under Symfony 3.3, but now I am seeing this exception:
An exception has been thrown during the rendering of a template ("The
menu "main" is not defined.").
services.yaml
App\Menu\MenuBuilder:
public: true
tags:
- { name: app.menu_builder.admin, method: createAdminMenu, alias: admin }
- { name: app.menu_builder.calendar, method: createCalendarMenu, alias: calendar }
- { name: app.menu_builder.main, method: createMainMenu, alias: main }
- { name: app.menu_builder.trailer, method: createTrailerMenu, alias: trailer }
- { name: app.menu_builder.user, method: createUserMenu, alias: user }
MenuBuilder
Namespace App\Menu;
use Knp\Menu\FactoryInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\Security\Core\Security;
class MenuBuilder implements ContainerAwareInterface
{
use ContainerAwareTrait;
private $factory;
/**
* #param FactoryInterface $factory
*/
public function __construct( FactoryInterface $factory )
{
$this->factory = $factory;
}
I put a die('here'); in the __construct, it is never executed.
Using php bin/console debug:container menu yields:
Information for Service "App\Menu\MenuBuilder"
==============================================
---------------- -------------------------------------------------------------------------
Option Value
---------------- -------------------------------------------------------------------------
Service ID App\Menu\MenuBuilder
Class App\Menu\MenuBuilder
Tags app.menu_builder.admin (method: createAdminMenu, alias: admin)
app.menu_builder.calendar (method: createCalendarMenu, alias: calendar)
app.menu_builder.main (method: createMainMenu, alias: main)
app.menu_builder.trailer (method: createTrailerMenu, alias: trailer)
app.menu_builder.user (method: createUserMenu, alias: user)
Public yes
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired yes
Autoconfigured yes
---------------- -------------------------------------------------------------------------
How can I get MenuBuilder __construct to execute?
Thank you all for your time.
This gist was helpful: https://gist.github.com/lsv/4d8044d21819f28f0dde52a3fb8211a0
This answer was helpful: How to avoid "knp_menu.factory" deprecation?
services.yaml
app.menu_builder:
class: App\Menu\MenuBuilder
app.menu.main:
class: Knp\Menu\MenuItem
factory: ['#app.menu_builder', 'createMainMenu']
arguments: { $options: [] }
tags:
- { name: knp_menu.menu, alias: main }
I used php bin/console debug:autowiring security to get the security authorization checker
Then I updated MenuBuilder.php like so:
Namespace App\Menu;
use Knp\Menu\FactoryInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
class MenuBuilder
{
private $factory;
private $security;
/**
* #param FactoryInterface $factory
*/
public function __construct( FactoryInterface $factory, AuthorizationCheckerInterface $security )
{
$this->factory = $factory;
$this->security = $security;
}
Adding the SecurityAuthorizationChecker allows me to control the menu items offered with this statement:
if( $this->security->isGranted( 'IS_AUTHENTICATED_FULLY' ) )
An error occurred when I tried to put the service #doctrine.orm.entity_manager as an argument for my listener UserDeletionListener.
My service:
se.doctrine_listener.user_deletion:
class: SE\CoreBundle\DoctrineListener\UserDeletionListener
arguments:
- "#doctrine.orm.entity_manager"
tags:
- { name: doctrine.event_listener, event: preRemove }
My listener:
namespace SE\CoreBundle\DoctrineListener;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Doctrine\ORM\EntityManager;
use SE\UserBundle\Entity\User;
class UserDeletionListener
{
/**
* #var \Doctrine\ORM\EntityManager
*/
private $em;
public function __construct(EntityManager $entityManager)
{
$this->em = $entityManager;
}
/...
Here is the error:
Circular reference detected for service "doctrine.dbal.default_connection", path: "doctrine.dbal.default_connection".
when you use EventArgs {lifecycle, preUpdate, etc...], you don't have to pass doctrine.orm.entity_manager anymore :-D You can get it by the method getEntityManager of the eventArgs itself
Add Lazy loading to doctrine Event Listener
*
- { name: doctrine.event_listener, event: preRemove, lazy: true }
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
I am trying to use a custom UserProvider with the FOS User bundle package and the FOS Oauth package. I have been following this tutorial http://blog.tankist.de/blog/2013/07/17/oauth2-explained-part-2-setting-up-oauth2-with-symfony2-using-fosoauthserverbundle/.
When I try and register my new user service I am getting the following error
UserProvider::__construct() must implement interface Doctrine\Common\Persistence\ObjectRepository, array given
UserProvider:
UserProvider implements UserProviderInterface
{
/**
* #var ObjectRepository
*/
protected $userRepository;
/**
* #param ObjectRepository $userRepository
*/
public function __construct(ObjectRepository $userRepository)
{
$this->userRepository = $userRepository;
}
/**
* #param string $username
* #return mixed
*/
public function loadUserByUsername($username)
{ ... }
UserRepository
class UserRepository extends EntityRepository implements ObjectRepository
services.yml
parameters:
entity_name: Hornby\UserBundle\Entity\UserRepository
services:
user_provider_me:
class: Hornby\UserBundle\Provider\UserProvider
arguments:
name: [%entity_name%]
Your services.yml file is wrong. I'm not really sure what you want to achieve but you pass array
arguments:
name: [%entity_name%] #entity_name is just a string
as an argument to UserProvider class. Constructor of this class expects ObjectRepository and this is your problem here.
A translation of services.xml from link you provided should look rather like that:
parameters:
platform.entity.user.class: Acme\DemoBundle\Entity\User
platform.user.provider.class: Acme\DemoBundle\Provider\UserProvider
services:
platform.user.manager:
class: Doctrine\ORM\EntityManager
factory: ["#doctrine", getManagerForClass]
arguments: [%platform.entity.user.class%]
platform.user.repository:
class: Acme\DemoBundle\Repository\UserRepository
factory: ["#platform.user.manager", getRepository]
arguments: [%platform.entity.user.class%]
platform.user.provider:
class: %platform.user.provider.class%
arguments: [#platform.user.repository]