UserProvider not implementing correct interface - php

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]

Related

symfony4, Dependency injection, no default argument

I have setup service to controller function like this
App\Controller\Controller:
calls:
- [new, ['#request_stack','#doctrine.orm.default_entity_manager']]
I needed Entity Manager inside controller action and my function looks like this
public function new(RequestStack $request, EntityManager $em): Response
{
$currentRequest = $request->getCurrentRequest();
$data = json_decode($currentRequest->getContent(), true);
....
return new ApiResponse(['message' => $message['message'], 'body' => 'success']);
}
and when executing comes to line return new ApiResponse it gives error
Controller "Controller::new()" requires that you provide a value for the "$request" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.
How to get entity manager in controller action or how to resolve this problem?
As the Symfony 4 Doc on Doctrine says :
// you can fetch the EntityManager via $this->getDoctrine()
// or you can add an argument to your action: index(EntityManagerInterface $entityManager)
$entityManager = $this->getDoctrine()->getManager();
So you can just get the entity manager this way in your controller
However, you can also register the Entity Manager as a service to use it.
Be sure to set the autowire to true :
# config/services.yaml
services:
_defaults:
autowire: true
and register it as a service :
# config/services.yaml
services:
#....
controller_em:
class: App\Controller\Controller
arguments: [ '#doctrine.orm.default_entity_manager' ]
public: true
So that you can use it like so in your controller :
private $objectManager;
public function __construct(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
}
You can also use this way to use the Entity Manager in Voter or Manager.
well. you need to inject your stuff into controller's object constructor - that is called DI in Symfony-way (or via set-methods):
services.yml - if everything ok with your autowire
App\Controller\Controller:
calls:
- [new]
if not add it manually:
App\Controller\Controller:
arguments:
- '#doctrine.orm.default_entity_manager'
calls:
- [new]
Controller.php
/** #var EntityManager */
private $em;
public __construct(EntityManager $em)
{
$this->em = $em;
}
and then just use it in your method:
public function new(RequestStack $request): Response
{
$this->em ...
}
For your information you can create your own AbsractController to inject the EntityManager in all controller extending it like this.
<?php
namespace App\Controller;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BaseController;
abstract class AbstractController extends BaseController
{
/**
* #var EntityManagerInterface
*/
protected $em;
/**
* #required
*
* #param EntityManagerInterface $em
*/
public function setEntityManager(EntityManagerInterface $em)
{
$this->em = $em;
}
}
If a controller extends this AbstractController, you could access $this->em everywhere in it.
The "required" annotation here is the key to enable what you tried to do without the need of adding configuration as you did. It's like adding a calls line in your configuration!
You could do something like this for every services you need in all your controllers.

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

How To Use Doctrine In symfony2 AbstractType

I'm trying to use doctrine in asymfony2 form type.
In services.yml I have:
fyp_user.profile.form.type:
class: FYP\UserBundle\Form\Type\ProfileFormType
arguments:
- fos_user.model.user.class
- #doctrine.orm.entity_manager
tags:
- { name: form.type, alias: fyp_user_profile }
My class looks like:
use Doctrine\ORM\EntityManager;
class ProfileFormType extends AbstractType
{
private $em;
private $session;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
I'm to do something like:
$cust = $this->em->getRepository('MyBundle:Customers')->findOneByEmail($email);
I keep getting
Type error: Argument 1 passed to FYP\UserBundle\Form\Type\ProfileFormType::__construct() must be an instance of Doctrine\ORM\EntityManager, string given, called in /Applications/MAMP/htdocs/upgrade/app/cache/dev/appDevDebugProjectContainer.php on line 3594
Thanks.
You have a mismatch between service definition and class constructor. In service definition you have two arguments: fos_user.model.user.class and #doctrine.orm.entity_manager and your constructor accepts only one (EntityManager). Just remove first entry from your arguments list in service definition and you'll be good

Categories