0
votes

Short Version: What does the Symfony file: SomeFile.php service configuration do?

Recently I entered an invalid service definition in a service.yaml file while working in a Symfony project. I was greeted by this super useful error message

The configuration key "foo" is unsupported for definition "App\Services\ServiceA" in "/Users/alanstorm/Sites/symfony-4/my-project/config/services.yaml". Allowed configuration keys are "alias", "parent", "class", "shared", "synthetic", "lazy", "public", "abstract", "deprecated", "factory", "file", "arguments", "properties", "configurator", "calls", "tags", "decorates", "decoration_inner_name", "decoration_priority", "autowire", "autoconfigure", "bind" in /Users/alanstorm/Sites/symfony-4/my-project/config/services.yaml (which is loaded in resource "/Users/alanstorm/Sites/symfony-4/my-project/config/services.yaml").

I don't think I'd ever seen every valid configuration for a Symfony service listed somewhere before. I'm trying to understand what the file configuration is for and how to use it.

I tried configuration a service using it

App\Services\ServiceA:
    file: SomeFile.php

and Symfony complained

Warning: include_once(SomeFile.php): failed to open stream: No such file or directory

I tried placing a file named SomeFile.php at `src/SomeFile.php, and Symfony complained

The autoloader expected class "App\SomeFile" to be defined in file "/Users/alanstorm/Sites/symfony-4/my-project/vendor/composer/../../src/SomeFile.php". The file was found but the class was not in it, the class name or namespace probably has a typo in /Users/alanstorm/Sites/symfony-4/my-project/config/services.yaml (which is loaded in resource "/Users/alanstorm/Sites/symfony-4/my-project/config/services.yaml").

So I defined a class named App\SomeFile in src/SomeFile.php

#File: src/SomeFile.php
namespace App;
class SomeFile {
}

and Symfony loaded this file -- but when back to complaining

Warning: include_once(SomeFile.php): failed to open stream: No such file or directory in var/cache/dev/ContainerG6s3qUD/getServiceA2Service.php (line 11)

So finally, I checked out the `` file and saw it included this line

#File: var/cache/dev/ContainerG6s3qUD/getServiceA2Service.php
//...
include_once 'SomeFile.php';
//...

So, best I can tell is this file configuration is some sort of alternative to the composer autoloader -- but I can't find any docs on how to confirm thy suspicions or how to use it.

Can anyone help me understand that this configuration field is for?

1
Just recently the Symfony errors started to become more verbose. Not sure how helpful this is since most people ignore them anyways. That said, the file attribute is discussed here: symfony.com/doc/current/service_container/… Not something that get used much.Cerad
@Cerad FWIW I've found the new error messages to be helpful. I bet a lot of people do read them -- you just only hear from the people that don't :)Alan Storm

1 Answers

0
votes

Thanks to a little help from some internet friends, who were able to dig up some old documentation, I now know that the file service configuration is for including a PHP immediately before the service gets loaded.

There's a few things that tripped me up. First -- you need to use the %kernel.root_dir% parameter in order for this to work

App\Services\ServiceA:
    public: true
    file: "%kernel.root_dir%/foo.php"

The underlying container code expects this to be a full path.

Extra tricky was the following exception message

The autoloader expected class "App\SomeFile" to be defined in file "/Users/alanstorm/Sites/symfony-4/my-project/vendor/composer/../../src/SomeFile.php".

It turns out this didn't have anything to do with my file configuration. Instead, this error message was the result of the following default service.yaml configuration

_defaults:
    autowire: true
    public: true

App\:
    resource: '../src/*'
    exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

Because my included file was in src, Symfony's resource configuration seem to be trying to load it as a class file. When it wasn't a class file, it complained. Then, when the file loader tried to load a path without the %kernel.root_dir%, things were still sad.

If you're going to use these two configuration patterns together, you'll want to be sure to exclude your file file

    exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php,foo.php}'