32
32
use Symfony \Component \DependencyInjection \LazyProxy \PhpDumper \DumperInterface as ProxyDumper ;
33
33
use Symfony \Component \DependencyInjection \LazyProxy \PhpDumper \NullDumper ;
34
34
use Symfony \Component \DependencyInjection \Parameter ;
35
+ use Symfony \Component \DependencyInjection \ParameterBag \EnvPlaceholderParameterBag ;
35
36
use Symfony \Component \DependencyInjection \Reference ;
36
37
use Symfony \Component \DependencyInjection \ServiceLocator as BaseServiceLocator ;
37
38
use Symfony \Component \DependencyInjection \TypedReference ;
@@ -216,7 +217,7 @@ public function dump(array $options = [])
216
217
}
217
218
218
219
$ code =
219
- $ this ->startClass ($ options ['class ' ], $ baseClass , $ baseClassWithNamespace ).
220
+ $ this ->startClass ($ options ['class ' ], $ baseClass , $ baseClassWithNamespace, $ preload ).
220
221
$ this ->addServices ($ services ).
221
222
$ this ->addDeprecatedAliases ().
222
223
$ this ->addDefaultParametersMethod ()
@@ -243,6 +244,10 @@ public function dump(array $options = [])
243
244
EOF ;
244
245
$ files = [];
245
246
247
+ if ($ preload ) {
248
+ $ files ['preload.php ' ] = "<?php \n" .str_replace ("\n include_once " , "\ninclude_once " , $ preload )."\n" ;
249
+ }
250
+
246
251
$ ids = $ this ->container ->getRemovedIds ();
247
252
foreach ($ this ->container ->getDefinitions () as $ id => $ definition ) {
248
253
if (!$ definition ->isPublic ()) {
@@ -277,6 +282,39 @@ public function dump(array $options = [])
277
282
$ time = $ options ['build_time ' ];
278
283
$ id = hash ('crc32 ' , $ hash .$ time );
279
284
285
+ if ($ preload ) {
286
+ $ preload = <<<EOF
287
+ <?php
288
+
289
+ // This file has been auto-generated by the Symfony Dependency Injection Component
290
+ // You can reference it in the "opcache.preload" php.ini setting on PHP >= 7.4 when preloading is desired
291
+
292
+
293
+ EOF ;
294
+
295
+ $ lineage = [];
296
+
297
+ $ this ->collectLineage ($ baseClassWithNamespace , $ lineage , true );
298
+ $ lineage [] = "__DIR__.'/Container {$ hash }/ {$ options ['class ' ]}.php' " ;
299
+ $ lineage [] = "__DIR__.'/Container {$ hash }/preload.php' " ;
300
+
301
+ foreach ($ lineage as $ file ) {
302
+ $ this ->inlinedRequires [$ file ] = true ;
303
+ $ preload .= sprintf ("include_once %s; \n" , preg_replace ('#^ \\$this->targetDirs\[(\d++)\]# ' , 'dirname(__DIR__, $1) ' , $ file ));
304
+ }
305
+
306
+ $ this ->collectLineage (EnvPlaceholderParameterBag::class, $ lineage );
307
+
308
+ foreach ($ lineage as $ file ) {
309
+ if (!isset ($ this ->inlinedRequires [$ file ])) {
310
+ $ this ->inlinedRequires [$ file ] = true ;
311
+ $ preload .= sprintf ("include_once %s; \n" , preg_replace ('#^ \\$this->targetDirs\[(\d++)\]# ' , 'dirname(__DIR__, $1) ' , $ file ));
312
+ }
313
+ }
314
+
315
+ $ code [$ options ['class ' ].'.preload.php ' ] = $ preload ;
316
+ }
317
+
280
318
$ code [$ options ['class ' ].'.php ' ] = <<<EOF
281
319
<?php
282
320
{$ namespaceLine }
@@ -391,15 +429,15 @@ private function connectCircularReferences($sourceId, &$currentPath, &$subPath =
391
429
unset($ subPath [$ sourceId ]);
392
430
}
393
431
394
- private function collectLineage ($ class , array &$ lineage )
432
+ private function collectLineage ($ class , array &$ lineage, bool $ allowContainer = false )
395
433
{
396
434
if (isset ($ lineage [$ class ])) {
397
435
return ;
398
436
}
399
437
if (!$ r = $ this ->container ->getReflectionClass ($ class , false )) {
400
438
return ;
401
439
}
402
- if ($ this ->container instanceof $ class ) {
440
+ if (! $ allowContainer && $ this ->container instanceof $ class ) {
403
441
return ;
404
442
}
405
443
$ file = $ r ->getFileName ();
@@ -408,15 +446,15 @@ private function collectLineage($class, array &$lineage)
408
446
}
409
447
410
448
if ($ parent = $ r ->getParentClass ()) {
411
- $ this ->collectLineage ($ parent ->name , $ lineage );
449
+ $ this ->collectLineage ($ parent ->name , $ lineage, $ allowContainer );
412
450
}
413
451
414
452
foreach ($ r ->getInterfaces () as $ parent ) {
415
- $ this ->collectLineage ($ parent ->name , $ lineage );
453
+ $ this ->collectLineage ($ parent ->name , $ lineage, $ allowContainer );
416
454
}
417
455
418
456
foreach ($ r ->getTraits () as $ parent ) {
419
- $ this ->collectLineage ($ parent ->name , $ lineage );
457
+ $ this ->collectLineage ($ parent ->name , $ lineage, $ allowContainer );
420
458
}
421
459
422
460
$ lineage [$ class ] = substr ($ exportedFile , 1 , -1 );
@@ -474,13 +512,14 @@ private function addServiceInclude(string $cId, Definition $definition): string
474
512
}
475
513
476
514
foreach (array_diff_key (array_flip ($ lineage ), $ this ->inlinedRequires ) as $ file => $ class ) {
477
- $ code .= sprintf (" include_once %s; \n" , $ file );
515
+ $ code .= sprintf (" include_once %s; \n" , preg_replace ( ' #^ \\ $this->targetDirs\[(\d++)\]# ' , sprintf ( ' \dirname(__DIR__, %d + $1) ' , $ this -> asFiles ), $ file) );
478
516
}
479
517
}
480
518
481
519
foreach ($ this ->inlinedDefinitions as $ def ) {
482
520
if ($ file = $ def ->getFile ()) {
483
- $ code .= sprintf (" include_once %s; \n" , $ this ->dumpValue ($ file ));
521
+ $ file = $ this ->dumpValue ($ file );
522
+ $ code .= sprintf (" include_once %s; \n" , preg_replace ('#^ \\$this->targetDirs\[(\d++)\]# ' , sprintf ('\dirname(__DIR__, %d + $1) ' , $ this ->asFiles ), $ file ));
484
523
}
485
524
}
486
525
@@ -958,7 +997,7 @@ private function addNewInstance(Definition $definition, string $return = '', str
958
997
return $ return .sprintf ('new %s(%s) ' , $ this ->dumpLiteralClass ($ this ->dumpValue ($ class )), implode (', ' , $ arguments )).$ tail ;
959
998
}
960
999
961
- private function startClass (string $ class , string $ baseClass , string $ baseClassWithNamespace ): string
1000
+ private function startClass (string $ class , string $ baseClass , string $ baseClassWithNamespace, ? string & $ preload ): string
962
1001
{
963
1002
$ namespaceLine = !$ this ->asFiles && $ this ->namespace ? "\nnamespace {$ this ->namespace }; \n" : '' ;
964
1003
@@ -1026,7 +1065,11 @@ public function __construct()
1026
1065
$ code .= $ this ->addMethodMap ();
1027
1066
$ code .= $ this ->asFiles ? $ this ->addFileMap () : '' ;
1028
1067
$ code .= $ this ->addAliases ();
1029
- $ code .= $ this ->addInlineRequires ();
1068
+
1069
+ if ($ preload = $ this ->getInlineRequires ()) {
1070
+ $ code .= sprintf ("\n \$this->privates['service_container'] = static function () {%s \n }; \n" , $ this ->asFiles ? "\n require_once __DIR__.'/preload.php'; " : $ preload );
1071
+ }
1072
+
1030
1073
$ code .= <<<EOF
1031
1074
}
1032
1075
@@ -1227,7 +1270,7 @@ protected function {$methodNameAlias}()
1227
1270
return $ code ;
1228
1271
}
1229
1272
1230
- private function addInlineRequires (): string
1273
+ private function getInlineRequires (): string
1231
1274
{
1232
1275
if (!$ this ->hotPathTag || !$ this ->inlineRequires ) {
1233
1276
return '' ;
@@ -1251,11 +1294,11 @@ private function addInlineRequires(): string
1251
1294
foreach ($ lineage as $ file ) {
1252
1295
if (!isset ($ this ->inlinedRequires [$ file ])) {
1253
1296
$ this ->inlinedRequires [$ file ] = true ;
1254
- $ code .= sprintf ("\n include_once %s; " , $ file );
1297
+ $ code .= sprintf ("\n include_once %s; " , preg_replace ( ' #^ \\ $this->targetDirs\[(\d++)\]# ' , sprintf ( ' \dirname(__DIR__, %d + $1) ' , $ this -> asFiles ), $ file) );
1255
1298
}
1256
1299
}
1257
1300
1258
- return $ code ? sprintf ( "\n \$ this->privates['service_container'] = function () {%s \n }; \n" , $ code ) : '' ;
1301
+ return $ code ;
1259
1302
}
1260
1303
1261
1304
private function addDefaultParametersMethod (): string
0 commit comments