Skip to content

ServiceSubscriberTrait is incompatible with AbstractController #49884

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

Closed
fritzmg opened this issue Mar 31, 2023 · 3 comments
Closed

ServiceSubscriberTrait is incompatible with AbstractController #49884

fritzmg opened this issue Mar 31, 2023 · 3 comments

Comments

@fritzmg
Copy link
Contributor

fritzmg commented Mar 31, 2023

Symfony version(s) affected

5.4.x, 6.2.x

Description

If you want to use ServiceSubscriberTrait in a class that happens to extend from AbstractController, the following error will appear:

Symfony\Component\ErrorHandler\Error\FatalError:
Compile Error: Declaration of 
Symfony\Contracts\Service\ServiceSubscriberTrait::setContainer(Psr\Container\ContainerInterface $container) 
must be compatible with 
Symfony\Bundle\FrameworkBundle\Controller\AbstractController::setContainer(Psr\Container\ContainerInterface $container): ?Psr\Container\ContainerInterface

  at src/Controller/AppAbstractController.php

The point of ServiceSubscriberTrait::setContainer is that it automatically looks for a setContainer method in the parent class and uses it, if available. However, that's incompatible in this case, as the parent setContainer method has a more specific return type.

How to reproduce

namespace App\Controller;

use Doctrine\DBAL\Connection;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Contracts\Service\ServiceSubscriberTrait;

class AppAbstractController extends AbstractController
{
    use ServiceSubscriberTrait;

    private function databaseConnection(): Connection
    {
        return $this->container->get(__METHOD__);
    }
}

Possible Solution

I did not create a PR right away as I am not sure whether this can technically only be fixed in Symfony 7? But if it's not fixed the ServiceSubscriberTrait is unusable for cases where a parent class actually implements setContainer with a specific return type.

Though may be instead of changing the return type for ServiceSubscriberTrait::setContainer the return type of AbstractController::setContainer should be removed, which should be safe to do in a bugfix release. After all, the ContainerAwareInterface and ContainerAwareTrait also do not use a return type on setContainer.

Additional Context

No response

@MatTheCat
Copy link
Contributor

You should upgrade symfony/contracts to v3.

Should #42088 have added symfony/contracts < 3 as conflict in symfony/framework-bundle? 🤔

@fritzmg
Copy link
Contributor Author

fritzmg commented Apr 1, 2023

You should upgrade symfony/contracts to v3.

That's not possible, because Symfony Twig Bundle 5.4.x conflicts with symfony/service-contracts >=3.0: https://github.com/symfony/twig-bundle/blob/875d0edfc8df7505c1993419882c4071fc28c477/composer.json#L46

Also symfony/service-contracts 3.x requires at least PHP 8, so depending on your platform you would still end up with this incompatible state.

@nicolas-grekas
Copy link
Member

You can work around this by declaring setContainer explicitly in your controller:

    public function setContainer(ContainerInterface $container): ?ContainerInterface
    {
        return parent::setContainer($container);
    }

Closing as there is nothing we can do on 5.4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants