Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__construct() must implement interface Symfony\Component\EventDispatcher\EventDispatcherInterface, none given #2744

Closed
LailaMai opened this issue Feb 23, 2018 · 15 comments · Fixed by #2807

Comments

@LailaMai
Copy link

commented Feb 23, 2018

Hello,
My project was working just fine till I made composer update and I get this error:

Catchable Fatal Error: Argument 1 passed to FOS\UserBundle\Controller\ProfileController::__construct() must implement interface Symfony\Component\EventDispatcher\EventDispatcherInterface, none given, called in C:\wamp\www\themecheck.org\var\cache\dev\jms_diextra\controller_injectors\UserBundleControllerAccountController.php on line 13 and defined

My composer infos:

"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.1.*",
"doctrine/orm": "^2.5",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"symfony/swiftmailer-bundle": "^2.3.10",
"symfony/monolog-bundle": "^3.0.2",
"symfony/polyfill-apcu": "^1.0",
"sensio/distribution-bundle": "^5.0",
"sensio/framework-extra-bundle": "^3.0.2",
"incenteev/composer-parameter-handler": "^2.0",
"friendsofsymfony/user-bundle": "~2.0",
"jms/i18n-routing-bundle": "^2.0",
"jms/translation-bundle": "^1.3",
"jms/di-extra-bundle": "^1.8",
"guzzlehttp/guzzle": "^6.2",
"stof/doctrine-extensions-bundle": "^1.2"
},

Stack Trace

in vendor\friendsofsymfony\user-bundle\Controller\ProfileController.php at line 39 -

36: private $formFactory;
37: private $userManager;
38:
39: public function __construct(EventDispatcherInterface $eventDispatcher, FactoryInterface $formFactory, UserManagerInterface $userManager)
40: {
41: $this->eventDispatcher = $eventDispatcher;
42: $this->formFactory = $formFactory;

**highlight the 39 line in log

I have tried many solutions like overriding the parent constructor or adding public function __construct(){parent::__construct();} in the override controller but nothing seems to work.

Is there something changed in the FosUserBundle that create this bug? how can I fix it ?

@LailaMai

This comment has been minimized.

Copy link
Author

commented Feb 27, 2018

Actually I set in composer the version like that:
"friendsofsymfony/user-bundle": "=2.0.1", (run composer update of course) and now things work again, I see that the recent changes made in FosUserBundle cause code breakage which normally shouldn't.

@phpeek

This comment has been minimized.

Copy link

commented Feb 27, 2018

@LailaMai This is probably due to the fact that Your AccountController extends ProfileController and overrides its original actions. This is correct and works in Symfony 2 / 3(though deprecated) but will no longer work in Symfony 4 since bundle inheritance is no longer supported - https://symfony.com/doc/current/bundles/inheritance.html

Since FOSUserBundle version 2.1 supports Symfony 4, all controllers are registered as services - e.g.
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/config/profile.xml#L21. Your controller's class will never be injected with those services - hence an error You're seeing.

I've reached out to @stof via Twitter on how to handle this and used his advice by overriding via routing - https://twitter.com/Stof70/status/968478748906541057, however this will not work, since controller still won't be injected with services.

What I would suggest for now is creating compiler pass and overriding fos_user.profile.controller service's class as described here - https://symfony.com/doc/current/bundles/override.html#services-configuration

This proves to be working for me.

P.S. Not sure if that's a game changer, but I'm on Symfony 2.8. 😢

@LailaMai

This comment has been minimized.

Copy link
Author

commented Feb 28, 2018

OK I'll try this solution and see what will happen, Thanks @phpeek 👍

@XWB

This comment has been minimized.

Copy link
Member

commented Mar 2, 2018

Thanks @phpeek

@stof

This comment has been minimized.

Copy link
Member

commented Mar 2, 2018

@phpeek overriding via routing still allows you to use DI for yoru own class. And when creating your own controller replacing some action, you should probably not even make it extend the FOSUserbundle class (which does not provide inheritance-based extension point anyway)

@slince

This comment has been minimized.

Copy link

commented Mar 5, 2018

@phpeek @XWB

I have created a controller ChangePasswordController extends FOS\UserBundle\Controller\ChangePasswordController

However how i get service from container? $this->container is invalid in the constructor.

class ChangePasswordController extends FOSChangePasswordController
{
    public function __construct() {
        $eventDispatcher = $this->get('event_dispatcher');
        $formFactory = $this->get('fos_user.change_password.form.factory');
        $userManager = $this->get('fos_user.user_manager');
        parent::__construct($eventDispatcher, $formFactory, $userManager);
    }
}
@phpeek

This comment has been minimized.

Copy link

commented Mar 5, 2018

@stof Granted, this is probably not the best way on extending FOSUserBundle controllers. However, I see issues related to this problem being submitted, so looks like people took this bad approach. Do You think this should be treated as BC break and bump in major version ?

@slince If you've created a compiler pass for Your ChangePasswordController, those services will be injected into its constructor. If You're not doing anything custom in Your controller's constructor, You don't have to override parent's constructor.

@blackarcanis

This comment has been minimized.

Copy link

commented Mar 21, 2018

@phpeek So to be sure, "good way" to do is to create a compiler pass, right ?

@LailaMai

This comment has been minimized.

Copy link
Author

commented Mar 21, 2018

Finally in my case, I had at first time, "AccountController extends FOS\UserBundle\Controller\ProfileController" , with overriding the editAction and I had also "RegistrationController extends FOS\UserBundle\Controller\RegistrationController" with overriding confirmAction and confirmedAction, I updated my composer as following:
"require": {
"symfony/symfony": "3.4.*",
"friendsofsymfony/user-bundle": "~2.0",
.....
},
I don't really know how to work with compiler pass in my case, so in order to fix the bundle inheritance deprecation ,I just removed this line from UserBundle:
public function getParent() { return 'FOSUserBundle'; }
And changed "class AccountController extends Controller" and "class RegistrationController extends Controller" and everything works fine as normal, the deprecation messages also disappeared.

@phpeek

This comment has been minimized.

Copy link

commented Mar 28, 2018

@blackarcanis No :) Consider it a "hacky" way.

As @stof mentioned here extending any of the FOSUserBundle's controllers is not a a valid extension point. You should rather create Your own controller instead.

The problem here is that properties of base controller classes are marked as private, not protected - e.g ProfileController

It means You won't be able to access them in Your controller when extending base controller unless You redefine them in Your controller, override __constructor and create compiler pass. With all that said, it should be more clear why this is a "hacky" way of solving this issue. 😢

@marcel-burkhard

This comment has been minimized.

Copy link

commented Apr 9, 2018

I didn't override the Controller but used another (nasty) shortcut in an application where the user can request to reset his password in another application (not symfony) and that request is sent to the symfony application through a json api:

$response = $this->forward('FOS\UserBundle\Controller\ResettingController::sendEmailAction', [
    'request' => $request
]);

$expectedRedirectUrl = $this->generateUrl('fos_user_resetting_check_email', ['username' => $username]);

if (!$response instanceof RedirectResponse) {
	return new JsonResponse([
		'error' => 'Something went wrong.'
	], 500);
}

if ($response->getTargetUrl() != $expectedRedirectUrl) {
	return new JsonResponse([
		'error' => 'Something went wrong.'
	], 500);
}

return new JsonResponse([
	'success' => true
], 200);

this doesn't work with "friendsofsymfony/user-bundle": "~2.1" so I downgraded to ~2.0
error (shortened) was:

[3] request.CRITICAL: Uncaught PHP Exception Type error: Too few arguments to function FOS\UserBundle\Controller\ResettingController::__construct(), 0 passed in ...\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\Controller\ControllerResolver.php on line 195 and exactly 6 expected" "} []`

I'm actually surprised that $this->forward() doesn't know how to create a ResettingController.
Silly question: Is there a configuration workaround so I can keep my code and version 2.1?

@DH-INT

This comment has been minimized.

Copy link

commented Apr 14, 2018

@LailaMai it's work fine for me after downgrading fosuserbundle with ~2.0.1

@LailaMai

This comment has been minimized.

Copy link
Author

commented Apr 16, 2018

@DH-INT I know , I mentioned that on my second comment, but if you need to upgrade the bundle in future you need to make some modifications to make it work fine again.

@devozanges

This comment has been minimized.

Copy link

commented Jun 4, 2018

the version 2.0.2 fix the same problem for me.
thx

@HeahDude

This comment has been minimized.

Copy link

commented Jun 7, 2018

I had the same issue, see #2807.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
10 participants
You can’t perform that action at this time.