diff --git a/README.md b/README.md
index e4fec945a..b850d12b9 100644
--- a/README.md
+++ b/README.md
@@ -58,6 +58,7 @@ potentially very difficult to debug due to dissimilar or unsupported package ver
- [Autoload aliases](docs/further-reading.md#autoload-aliases)
- [Class aliases](docs/further-reading.md#class-aliases)
- [Function aliases](docs/further-reading.md#function-aliases)
+ - [Symfony support](docs/further-reading.md#symfony-support)
- [Limitations](docs/limitations.md#limitations)
- [Dynamic symbols](docs/limitations.md#dynamic-symbols)
- [Date symbols](docs/limitations.md#date-symbols)
diff --git a/docs/further-reading.md b/docs/further-reading.md
index 33ab9a6be..da9f29154 100644
--- a/docs/further-reading.md
+++ b/docs/further-reading.md
@@ -4,6 +4,7 @@
- [Autoload aliases](#autoload-aliases)
- [Class aliases](#class-aliases)
- [Function aliases](#function-aliases)
+- [Symfony support](#symfony-support)
### How to deal with unknown third-party symbols
@@ -65,6 +66,51 @@ When [exposing a function] or when a globally declared [excluded function]
declaration is found (see [#706]), an alias will be registered.
+### Symfony Support
+
+When using [PHP configuration][symfony-php-config] files for your services, some elements may not be prefixed correctly
+due to being strings. For example (taken directly from the Symfony docs):
+
+```php
+services()
+ ->defaults()
+ ->autowire() // Automatically injects dependencies in your services.
+ ->autoconfigure() // 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
+ $services->load('App\\', '../src/')
+ ->exclude('../src/{DependencyInjection,Entity,Kernel.php}');
+
+ // order is important in this file because service definitions
+ // always *replace* previous ones; add your own service configuration below
+};
+```
+
+The string `'App\\'` from `$services->load()` will not be made into `'Prefix\\App\\'`. To address this
+you need to use [patchers]. Alternatively, PHP-Scoper provides one which should should handle such cases:
+
+```php
+ [$symfonyPatcher],
+ // ...
+];
+```
+
+Note that the path is the "regular path(s)" that can be passed to patchers.
+
+
@@ -76,3 +122,5 @@ declaration is found (see [#706]), an alias will be registered.
[exposing a class]: configuration.md#exposing-classes
[exposing a function]: configuration.md#exposing-functions
[#706]: https://github.com/humbug/php-scoper/pull/706
+[patchers]: ./configuration.md#patchers
+[symfony-php-config]: https://symfony.com/doc/current/service_container.html#explicitly-configuring-services-and-arguments
diff --git a/res/create-symfony-php-services-patcher.php b/res/create-symfony-php-services-patcher.php
new file mode 100644
index 000000000..7828109ed
--- /dev/null
+++ b/res/create-symfony-php-services-patcher.php
@@ -0,0 +1,34 @@
+,
+ * Pádraic Brady
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Creates a patcher able to fix the paths of the Symfony PHP configuration files.
+ *
+ * @param string|array $filesPath
+ */
+return static function (array|string $fileOrFilesPath): Closure {
+ $filesPath = (array) $fileOrFilesPath;
+
+ return static function (string $filePath, string $prefix, string $contents) use ($filesPath): string {
+ if (!in_array($filePath, $filesPath, true)) {
+ return $contents;
+ }
+
+ return preg_replace(
+ '/(.*->load\((?:\n\s+)?\')(.+?\\\\)(\',.*)/',
+ '$1'.$prefix.'\\\\$2$3',
+ $contents,
+ );
+ };
+};
diff --git a/tests/Patcher/SymfonyPhpServicesPatcherTest.php b/tests/Patcher/SymfonyPhpServicesPatcherTest.php
new file mode 100644
index 000000000..a552c9046
--- /dev/null
+++ b/tests/Patcher/SymfonyPhpServicesPatcherTest.php
@@ -0,0 +1,109 @@
+,
+ * Pádraic Brady
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Humbug\PhpScoper\Patcher;
+
+use Closure;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @internal
+ */
+final class SymfonyPhpServicesPatcherTest extends TestCase
+{
+ private const FILE_PATH = 'path/to/config.php';
+
+ private Closure $patcher;
+
+ protected function setUp(): void
+ {
+ $this->patcher = (require __DIR__.'/../../res/create-symfony-php-services-patcher.php')([self::FILE_PATH]);
+ }
+
+ /**
+ * @dataProvider symfonyConfigFileProvider
+ */
+ public function test_it_can_patch_a_symfony_service_file(
+ string $prefix,
+ string $contents,
+ string $expected,
+ ): void {
+ $actual = ($this->patcher)(self::FILE_PATH, $prefix, $contents);
+
+ self::assertSame($expected, $actual);
+ }
+
+ public static function symfonyConfigFileProvider(): iterable
+ {
+ $prefix = 'Prefix';
+
+ yield 'load statement' => [
+ $prefix,
+ <<<'PHP'
+ use SomeNamespace\SomeClass;
+
+ return static function (ContainerConfigurator $containerConfigurator) {
+ $services = $containerConfigurator->services();
+
+ $services->load('SomeNamespace\ConsoleColorDiff\\', __DIR__ . '/../src');
+
+ $services->set(SomeClass::class);
+ }
+ PHP,
+ <<<'PHP'
+ use SomeNamespace\SomeClass;
+
+ return static function (ContainerConfigurator $containerConfigurator) {
+ $services = $containerConfigurator->services();
+
+ $services->load('Prefix\SomeNamespace\ConsoleColorDiff\\', __DIR__ . '/../src');
+
+ $services->set(SomeClass::class);
+ }
+ PHP,
+ ];
+
+ yield 'multiline load statement' => [
+ $prefix,
+ <<<'PHP'
+ use SomeNamespace\SomeClass;
+
+ return static function (ContainerConfigurator $containerConfigurator) {
+ $services = $containerConfigurator->services();
+
+ $services->load(
+ 'SomeNamespace\ConsoleColorDiff\\',
+ __DIR__ . '/../src',
+ );
+
+ $services->set(SomeClass::class);
+ }
+ PHP,
+ <<<'PHP'
+ use SomeNamespace\SomeClass;
+
+ return static function (ContainerConfigurator $containerConfigurator) {
+ $services = $containerConfigurator->services();
+
+ $services->load(
+ 'Prefix\SomeNamespace\ConsoleColorDiff\\',
+ __DIR__ . '/../src',
+ );
+
+ $services->set(SomeClass::class);
+ }
+ PHP,
+ ];
+ }
+}