Assume following directory structure:
/src
/DTO
/Factory
/Collection
I want to exclude all classes, including classes from subdirectories of /DTO directory
In my services file I do:
services:
_defaults:
autowire: true
autoconfigure: true
public: false
App\:
resource: '../src/*
exclude:
- '../src/DTO/*'
This leads to:
Symfony\Component\DependencyInjection\Exception\RuntimeException : Cannot autowire service App\DTO\Factory\Collection\MyCollection
If this service placed in DTO folder directly - then autowiring works.
Can I specify the exclude expression in any way to include subfolders?
To exclude everything from DTO folder use:
App\:
resource: '../src/*'
exclude:
- '../src/DTO'
i.e. w/o * symbol
I found a solution to exclude not only classes placed directly in folder, but also subfolders with two asterisk signs (**).
Here is the example of a valid configuration:
services:
_defaults:
autowire: true
autoconfigure: true
public: false
App\:
resource: '../src/*
exclude:
- '../src/DTO/**'
Related
i was deconnected any times at my application so i've want fix the problem but i've this error ans my folders / services was correctly configured. I would like to know if anyone has ever encountered this problem and if so how to fix it.
Services.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
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.
# 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/'
- '../src/Entity/'
- '../src/Kernel.php'
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
CoreController
namespace App\Controller;
use App\Entity\Intervention;
use Doctrine\ORM\Mapping\Id;
use Doctrine\DBAL\Schema\Index;
use App\Repository\OperateurRepository;
use Doctrine\Persistence\ManagerRegistry;
use App\Repository\InterventionRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class CoreController extends AbstractController
{```
I've fix with
calls:
- [setContainer, ["#service_container"]]
in services.yaml
I am trying to implement Symfony Dependency Injection Component (https://symfony.com/doc/current/components/dependency_injection.html) in a non Symfony project.
It works well if I put all my services and parameters into a single "services.yaml" file.
Ex:
# services.yaml
parameters:
mysql.host: "127.0.0.1"
mysql.database: "database"
mysql.username: "root"
mysql.password: ""
oracle.database: ""
oracle.username: ""
oracle.password: ""
cookie.domain: ".site.local"
cookie.lifetime: 0
cookie.useHttps: true
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
OtherNamespace\:
resource: '../someHomemadeLibrary/src/*'
OtherNamespace\Database\Drivers\MySqlDriver:
class: OtherNamespace\Database\Drivers\MySqlDriver
arguments:
$host: "%mysql.host%"
$database: "%mysql.database%"
$username: "%mysql.username%"
$password: "%mysql.password%"
# ...
As the file is getting very large, I wanted to split it into different files, as explained here : https://symfony.com/doc/current/service_container/import.html#importing-configuration-with-imports
So I tried :
# index.php
$containerBuilder = new ContainerBuilder();
$loader = new YamlFileLoader($containerBuilder, new FileLocator('config/'));
$loader->load('services.yaml');
# services.yaml
imports:
- { resource: "databases.yaml" }
- { resource: "sessions.yaml" }
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
OtherNamespace\:
resource: '../someHomemadeLibrary/src/*'
# databases.yaml
parameters:
mysql.host: "127.0.0.1"
mysql.database: "database"
mysql.username: "root"
mysql.password: ""
services:
OtherNamespace\Database\Drivers\MySqlDriver:
class: OtherNamespace\Database\Drivers\MySqlDriver
arguments:
$host: "%mysql.host%"
$database: "%mysql.database%"
$username: "%mysql.username%"
$password: "%mysql.password%"
# ...
But in this configuration, I get the following error :
Fatal error: Uncaught
Symfony\Component\DependencyInjection\Exception\RuntimeException:
Cannot autowire service "OtherNamespace\Database\Drivers\MySqlDriver": argument
"$host" of method "__construct()" is type-hinted "string", you
should configure its value explicitly.
If I switch the import order, then it is the CookieSession that has a problem. It is like the import is overriding the parameters and services to only use the last one ? How can I split my services and their parameters in multiple files ?
Thank you !
The problem was that my services were correctly imported from my databases.yaml and other yaml into my services.yaml file, but in this file, I also had automatic classes conversion into services.
So my services defined were reloaded/converted, but without the parameters and all. I added exclusions and it works!
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
OtherNamespace\:
resource: '../someHomemadeLibrary/src/*'
exclude:
[
'.../theClassFileDeclaredInAnotherYaml.php',
'../or/a/whole/folder/not/to/be/loaded/again/*.php'
]
Thanks to #NicoHaase, #Cerad and #WillB. for their help !
I've started a Symfony project for an API and have created my first controller
# services.yaml
parameters:
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
App\Controller\:
resource: '../src/EndPoints/*'
tags: ['controller.service_arguments']
Controller:
namespace App\Controller;
class RegisterController extends AbstractController {
public function register(Request $request): Response {
//stuff
}
}
I run this the first time and get an expected result. I do modifications to RegisterController and it dies with the error
Compile Error: Cannot declare class App\Controller\RegisterController,
because the name is already in use
If I go into the services.yaml and save it (no modifications) I can run it again with the updated code.
This has only just started happening when I've added doctrine-test-bundle and been doing testing however I don't think the two things are related. I've checked my .env.local APP_ENV is dev. What is causing a cache that means I have to resave services.yaml for any change to work?
You are importing the controllers twice.
Here, you are importing all your classes, but your controllers are not excluded from auto-wiring:
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
And here you import your controller classes again
App\Controller\:
resource: '../src/EndPoints/*'
tags: ['controller.service_arguments']
When the container gets compiled, you end up with a double definition for these classes.
Just do:
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
- '../src/EndPoints/'
App\Controller\:
resource: '../src/EndPoints/*'
tags: ['controller.service_arguments']
and you'll be set.
Additionally, you have a PSR-4 mismatch, where the classes at src/Endpoints belong to the namespace Controller. That's not problematic per-se, but it will only work if your composer.json is properly set. Better have directories that match the namespaces, do not make it harder than it should be.
From your services.yaml looks like you need to change the controller part.
From
App\Controller\:
resource: '../src/EndPoints/'
tags: ['controller.service_arguments']
To
App\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
But if you want to put controllers into the EndPoints folder, you need also change the alias in your config.
App\EndPoints\:
resource: '../src/EndPoints/*'
tags: ['controller.service_arguments']
// controller
namespace App\EndPoints;
class RegisterController extends AbstractController {
public function register(Request $request): Response {
//stuff
}
}
And don't forget to change the routing config
you just forget the namespace in the class that you have been created an use it
When I import services in the main configuration:
imports:
- { resource: services/attribute_loaders.yaml }
The services in the included file will be replaced with an autoconfigured version, so I've missed all my configured tags:
services:
App\Infrastructure\Bridge\Doctrine\EventListener\AttributeLoader\OrderAttributeLoader:
autowire: true
tags:
- name: 'doctrine_mongodb.odm.event_listener'
entity: 'App\Infrastructure\Bridge\Doctrine\EventListener\AttributeLoader\OrderAttributeLoader'
event: 'postLoad'
As a workaround, I've excluded my service from autoconfigure.
Is there any way to decompose services into several files?
That's exactly how you do it.
If you are going to use multiple files to configure your services, you simply can't define the same service twice.
Your definitions need to be specific enough so they do not overlap.
If you are going to use broad resource settings, you will need to add all the corresponding excludes so services defined in different files are not defined before it's time:
services:
App\:
resource: '../src/*'
exclude:
- '../src/Infrastructure/Symfony/DependencyInjection'
- '../src/Infrastructure/Symfony/Kernel.php'
- '../src/Tests'
- '../src/Messenger'
Services on src/Messenger, that belong to the App\Messenger namespace, can be defined independently on a different file:
E.g. something like this:
# messenger_services.yaml
services:
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false
App\Messenger\CommandHandler\:
resource: '../../src/Messenger/CommandHandler/*'
tags:
- {name: 'messenger.message_handler', bus: command.bus}
App\Messenger\EventHandler\:
resource: '../../src/Application/EventHandler/*'
tags:
- {name: 'messenger.message_handler', bus: event.bus}
I learning Symfony3 on https://knpuniversity.com. Now on create their own filters in Twig (https://knpuniversity.com/screencast/symfony-services/create-twig-extension). In this video the author creates a class filter, but when using this filter in the Twig template:
<dd>{{ genus.funFact|markdownify }}</dd>
Symfony crashes with the error, and the author of the video says that the filter has used need to say Symfony about new filter Twig'. This is done using the register Twig extension as service in the services.yml. But, I have it all working, without errors, without any registrations in service.yml.
Do steel need register Twig Extensions in the services.yml?
Or is now not required and determines its own Twig extension?
I have a Symfony 3.3.6 (in video used 3.0.0).
Here listing my service.yml:
parameters:
services:
_defaults:
autowire: true
autoconfigure: true
public: false
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
AppBundle\Service\MarkdownTransformer:
arguments:
- '#markdown.parser'
- '#doctrine_cache.providers.my_markdown_cache'
public: true
# AppBundle\Twig\MarkdownExtension:
# arguments: ['#AppBundle\Service\MarkdownTransformer']
# tags:
# - { name: twig.extension }
# public: true
In the bottom I'm added the settings block, which registers a new TWIG extension. Without this block, Symfony throws an exception (in the author of the lesson). But I have everything working without this block. So for example, I have it commented out.