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

Comments

@LailaMai
Copy link

@LailaMai LailaMai 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
Copy link
Author

@LailaMai LailaMai 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
Copy link

@phpeek phpeek 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
Copy link
Author

@LailaMai LailaMai commented Feb 28, 2018

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

@XWB
Copy link
Member

@XWB XWB commented Mar 2, 2018

Thanks @phpeek

@stof
Copy link
Member

@stof stof 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
Copy link

@slince slince 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
Copy link

@phpeek phpeek 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
Copy link

@blackarcanis blackarcanis commented Mar 21, 2018

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

@LailaMai
Copy link
Author

@LailaMai LailaMai 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
Copy link

@phpeek phpeek 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
Copy link

@marcel-burkhard marcel-burkhard 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
Copy link

@DH-INT DH-INT commented Apr 14, 2018

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

@LailaMai
Copy link
Author

@LailaMai LailaMai 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
Copy link

@devozanges devozanges commented Jun 4, 2018

the version 2.0.2 fix the same problem for me.
thx

@HeahDude
Copy link

@HeahDude HeahDude 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
Linked pull requests

Successfully merging a pull request may close this issue.

10 participants
You can’t perform that action at this time.