@@ -82,6 +82,7 @@ class PhpDumper extends Dumper
82
82
private $ locatedIds = [];
83
83
private $ serviceLocatorTag ;
84
84
private $ exportedVariables = [];
85
+ private $ baseClass ;
85
86
86
87
/**
87
88
* @var ProxyDumper
@@ -151,11 +152,11 @@ public function dump(array $options = [])
151
152
152
153
if (0 !== strpos ($ baseClass = $ options ['base_class ' ], '\\' ) && 'Container ' !== $ baseClass ) {
153
154
$ baseClass = sprintf ('%s\%s ' , $ options ['namespace ' ] ? '\\' .$ options ['namespace ' ] : '' , $ baseClass );
154
- $ baseClassWithNamespace = $ baseClass ;
155
+ $ this -> baseClass = $ baseClass ;
155
156
} elseif ('Container ' === $ baseClass ) {
156
- $ baseClassWithNamespace = Container::class;
157
+ $ this -> baseClass = Container::class;
157
158
} else {
158
- $ baseClassWithNamespace = $ baseClass ;
159
+ $ this -> baseClass = $ baseClass ;
159
160
}
160
161
161
162
$ this ->initializeMethodNamesMap ('Container ' === $ baseClass ? Container::class : $ baseClass );
@@ -222,7 +223,7 @@ public function dump(array $options = [])
222
223
$ proxyClasses = $ this ->inlineFactories ? $ this ->generateProxyClasses () : null ;
223
224
224
225
$ code =
225
- $ this ->startClass ($ options ['class ' ], $ baseClass , $ baseClassWithNamespace ).
226
+ $ this ->startClass ($ options ['class ' ], $ baseClass , $ preload ).
226
227
$ this ->addServices ($ services ).
227
228
$ this ->addDeprecatedAliases ().
228
229
$ this ->addDefaultParametersMethod ()
@@ -296,6 +297,33 @@ public function dump(array $options = [])
296
297
$ time = $ options ['build_time ' ];
297
298
$ id = hash ('crc32 ' , $ hash .$ time );
298
299
300
+ if ($ preload ) {
301
+ $ code [$ options ['class ' ].'.preload.php ' ] = <<<EOF
302
+ <?php
303
+
304
+ // This file has been auto-generated by the Symfony Dependency Injection Component
305
+ // You can reference it in the "opcache.preload" php.ini setting on PHP >= 7.4 when preloading is desired
306
+
307
+ use Symfony\Component\DependencyInjection\Dumper\Preloader;
308
+
309
+ require dirname(__DIR__, 3).'/vendor/autoload.php';
310
+ require __DIR__.'/Container {$ hash }/ {$ options ['class ' ]}.php';
311
+
312
+ \$classes = [];
313
+
314
+ EOF ;
315
+
316
+ foreach ($ preload as $ class ) {
317
+ $ code [$ options ['class ' ].'.preload.php ' ] .= sprintf ("\$classes[] = '%s'; \n" , $ class );
318
+ }
319
+
320
+ $ code [$ options ['class ' ].'.preload.php ' ] .= <<<'EOF'
321
+
322
+ Preloader::preload($classes);
323
+
324
+ EOF;
325
+ }
326
+
299
327
$ code [$ options ['class ' ].'.php ' ] = <<<EOF
300
328
<?php
301
329
{$ namespaceLine }
@@ -426,14 +454,16 @@ private function collectLineage(string $class, array &$lineage)
426
454
if (!$ r = $ this ->container ->getReflectionClass ($ class , false )) {
427
455
return ;
428
456
}
429
- if ($ this ->container instanceof $ class ) {
457
+ if (is_a ( $ class , $ this ->baseClass , true ) ) {
430
458
return ;
431
459
}
432
460
$ file = $ r ->getFileName ();
433
461
if (!$ file || $ this ->doExport ($ file ) === $ exportedFile = $ this ->export ($ file )) {
434
462
return ;
435
463
}
436
464
465
+ $ lineage [$ class ] = substr ($ exportedFile , 1 , -1 );
466
+
437
467
if ($ parent = $ r ->getParentClass ()) {
438
468
$ this ->collectLineage ($ parent ->name , $ lineage );
439
469
}
@@ -446,6 +476,7 @@ private function collectLineage(string $class, array &$lineage)
446
476
$ this ->collectLineage ($ parent ->name , $ lineage );
447
477
}
448
478
479
+ unset($ lineage [$ class ]);
449
480
$ lineage [$ class ] = substr ($ exportedFile , 1 , -1 );
450
481
}
451
482
@@ -522,13 +553,17 @@ private function addServiceInclude(string $cId, Definition $definition): string
522
553
}
523
554
524
555
foreach (array_diff_key (array_flip ($ lineage ), $ this ->inlinedRequires ) as $ file => $ class ) {
556
+ $ file = preg_replace ('#^ \\$this->targetDirs\[(\d++)\]# ' , sprintf ('\dirname(__DIR__, %d + $1) ' , $ this ->asFiles ), $ file );
525
557
$ code .= sprintf (" include_once %s; \n" , $ file );
526
558
}
527
559
}
528
560
529
561
foreach ($ this ->inlinedDefinitions as $ def ) {
530
562
if ($ file = $ def ->getFile ()) {
531
- $ code .= sprintf (" include_once %s; \n" , $ this ->dumpValue ($ file ));
563
+ $ file = $ this ->dumpValue ($ file );
564
+ $ file = '( ' === $ file [0 ] ? substr ($ file , 1 , -1 ) : $ file ;
565
+ $ file = preg_replace ('#^ \\$this->targetDirs\[(\d++)\]# ' , sprintf ('\dirname(__DIR__, %d + $1) ' , $ this ->asFiles ), $ file );
566
+ $ code .= sprintf (" include_once %s; \n" , $ file );
532
567
}
533
568
}
534
569
@@ -1016,7 +1051,7 @@ private function addNewInstance(Definition $definition, string $return = '', str
1016
1051
return $ return .sprintf ('new %s(%s) ' , $ this ->dumpLiteralClass ($ this ->dumpValue ($ class )), implode (', ' , $ arguments )).$ tail ;
1017
1052
}
1018
1053
1019
- private function startClass (string $ class , string $ baseClass , string $ baseClassWithNamespace ): string
1054
+ private function startClass (string $ class , string $ baseClass , ? array & $ preload ): string
1020
1055
{
1021
1056
$ namespaceLine = !
10000
$ this ->asFiles && $ this ->namespace ? "\nnamespace {$ this ->namespace }; \n" : '' ;
1022
1057
@@ -1064,8 +1099,8 @@ public function __construct()
1064
1099
$ code .= " \$this->containerDir = \$containerDir; \n" ;
1065
1100
}
1066
1101
1067
- if (Container::class !== $ baseClassWithNamespace ) {
1068
- $ r = $ this ->container ->getReflectionClass ($ baseClassWithNamespace , false );
1102
+ if (Container::class !== $ this -> baseClass ) {
1103
+ $ r = $ this ->container ->getReflectionClass ($ this -> baseClass , false );
1069
1104
if (null !== $ r
1070
1105
&& (null !== $ constructor = $ r ->getConstructor ())
1071
1106
&& 0 === $ constructor ->getNumberOfRequiredParameters ()
@@ -1085,7 +1120,7 @@ public function __construct()
1085
1120
$ code .= $ this ->addMethodMap ();
1086
1121
$ code .= $ this ->asFiles && !$ this ->inlineFactories ? $ this ->addFileMap () : '' ;
1087
1122
$ code .= $ this ->addAliases ();
1088
- $ code .= $ this ->addInlineRequires ();
1123
+ $ code .= $ this ->addInlineRequires ($ preload );
1089
1124
$ code .= <<<EOF
1090
1125
}
1091
1126
@@ -1285,7 +1320,7 @@ protected function {$methodNameAlias}()
1285
1320
return $ code ;
1286
1321
}
1287
1322
1288
- private function addInlineRequires (): string
1323
+ private function addInlineRequires (? array & $ preload ): string
1289
1324
{
1290
1325
if (!$ this ->hotPathTag || !$ this ->inlineRequires ) {
1291
1326
return '' ;
@@ -1304,6 +1339,7 @@ private function addInlineRequires(): string
1304
1339
1305
1340
foreach ($ inlinedDefinitions as $ def ) {
1306
1341
if (\is_string ($ class = \is_array ($ factory = $ def ->getFactory ()) && \is_string ($ factory [0 ]) ? $ factory [0 ] : $ def ->getClass ())) {
1342
+ $ preload [$ class ] = $ class ;
1307
1343
$ this ->collectLineage ($ class , $ lineage );
1308
1344
}
1309
1345
}
@@ -1314,11 +1350,12 @@ private function addInlineRequires(): string
1314
1350
foreach ($ lineage as $ file ) {
1315
1351
if (!isset ($ this ->inlinedRequires [$ file ])) {
1316
1352
$ this ->inlinedRequires [$ file ] = true ;
1353
+ $ file = preg_replace ('#^ \\$this->targetDirs\[(\d++)\]# ' , sprintf ('\dirname(__DIR__, %d + $1) ' , $ this ->asFiles ), $ file );
1317
1354
$ code .= sprintf ("\n include_once %s; " , $ file );
1318
1355
}
1319
1356
}
1320
1357
1321
- return $ code ? sprintf ("\n \$this->privates['service_container'] = function () {%s \n }; \n" , $ code ) : '' ;
1358
+ return $ code ? sprintf ("\n \$this->privates['service_container'] = static function () {%s \n }; \n" , $ code ) : '' ;
1322
1359
}
1323
1360
1324
1361
private function addDefaultParametersMethod (): string
0 commit comments