Search code examples
symfonybundlesymfony6

symfony6 - defining and using services.yaml in third part bundle


I'm making simple "MyCoreBundle" (MystertyCoreBundle) using symfony6.1 how to make bundle's doc.

I defined my bundle class vendor/mysterty/core-bundle/CoreBundle.class

<?php

namespace Mysterty\CoreBundle;

use Symfony\Component\HttpKernel\Bundle\AbstractBundle;

class MystertyCoreBundle extends AbstractBundle
{
}

I defined some parameters and configuration in vendor/mysterty/core-bundle/config/services.yaml as defaults :

services:
  Mysterty\CoreBundle\Controller\CoreController:
    public: true
    calls:
      - method: setContainer
        arguments: ["@service_container"]

parameters:
  app.admin_email: "mymailATserver.com"

Then I made simple controller in vendor/mysterty/core-bundle/src/Controller/CoreController.php:

<?php

namespace Mysterty\CoreBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;

class CoreController extends AbstractController
{

    #[Route('/', name: 'mty_default')]
    public function indexNoLocale(): Response
    {
        $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
        $supportedLangs = explode('|', $this->getParameter('app.supported_locales'));
        $lang = in_array($lang, $supportedLangs) ? $lang : $supportedLangs[0];
        return $this->redirectToRoute('mty_home', ['_locale' => $lang]);
    }

Finally, i added the bundle's routes to \config\routes.yaml

mysterty_core:
    resource: "../vendor/mysterty/core-bundle/src/Controller/CoreController.php"
    type:     annotation
    prefix:   /

Here is the error i have on http://127.0.0.1:8000/ :

"Mysterty\CoreBundle\Controller\CoreController" has no container set, did you forget to define it as a service subscriber?

I try to make a shared bundle with default actions and components for all my symfony projects.


Solution

  • Solution by @Cerad

    You can use bin/console debug:container CoreController to see if your controller is being defined as a service. I suspect not. You probably need to add a loadExtension method to your bundle class to load your services.yaml file. It's not automatic. You will probably also have trouble injecting the container as service_container is no longer defined out of the box. Plus many of it's services are no longer public. Need to look at injecting the container service locator or just autowire the silly thing.

    So : here is the needed configuration (thx to helpers):

    define loadExtension function in MyOwnBundle.php :

    <?php
    
    namespace MyOwn\MyOwnBundle;
    
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
    use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
    
    class MyOwnBundle extends AbstractBundle
    {
        public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
        {
                // load an XML, PHP or Yaml file
                $container->import('../config/services.yaml');
        }
    }
    

    and the correct services.yaml:

    // My/CoreBundle/config/services.yaml
    services:
    
      _defaults:
        autowire: true
        autoconfigure: true
        public: true
    
      My\CoreBundle\Controller\CoreController:
        public: true
        autowire: true
        autoconfigure: true
        calls:
          - [setContainer, ['@Psr\Container\ContainerInterface']]
        tags:
          - "controller.service_arguments"
          - "container.service_subscriber"