-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Added a build method to the kernel to replace Bundle::build() #20107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The less often you need to create an Extension in AppBundle, the better. |
I like this a lot! |
* | ||
* @return string[] | ||
*/ | ||
public function getClassesToCompile() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it still worth it when using php7 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm planning to verify this soon. Yet this PR is right adding it: it's just moving existing things around, and we still support php 5.
If php7 makes this unnecessary, then the whole inline system could be deprecated.
To be proven first, and not in this PR imho.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Ener-Getick if not, we could always patch it to only create and load this in php 5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is mostly for new apps (which should use 7.0) so imo it doesn't make sense to allow that if that's not worth it in 7.0 but of course as @nicolas-grekas said, at worst we'll only have to deprecate it later.
Would it be worth to let the Kernel itself be a container extension? |
@backbone87 which of those methods would you actually implement of the extension? https://github.com/symfony/symfony/blob/master/src/Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php |
@@ -39,12 +39,27 @@ public function process(ContainerBuilder $container) | |||
$classes = array(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about $classes = $this->kernel->getClassesToCompile();
and drop all foreaches below.. (ie. is replacing the array_merge
with foreach
really needed for performance?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally I'd just append everything to 1 big array and then do array_merge([], ...$classes)
, but 5.5 doesn't support that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, assigning everything from the kernel as defaults isn't a bad idea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly. The order seems more logical imo.
@@ -344,6 +344,30 @@ public function setAnnotatedClassCache(array $annotatedClasses) | |||
} | |||
|
|||
/** | |||
* Return a list of classes to be cached away when the container is build. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returns (same for the other method below)
@@ -344,6 +344,30 @@ public function setAnnotatedClassCache(array $annotatedClasses) | |||
} | |||
|
|||
/** | |||
* Return a list of classes to be cached away when the container is build. | |||
* | |||
* If a class contains annotations, add it to getAnnotatedClassesToCompile()instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this is worth a duplicated extra comment, the API looks explicit enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think its worth mentioning it here, although i would word it like so "Do not add classes that contain annotations, use ... instead"
* | ||
* @param ContainerBuilder $container | ||
*/ | ||
protected function build(ContainerBuilder $container) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like the name of this method. According to the Symfony naming conventions I think this should be called buildContainer()
because we are not building the kernel, which is what the Kernel
class is about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So isnt Kernel::buildContainer
the method Bundle::build
tends to be, ie.. do we still need that? Should it be Bundle::buildContainer
?
If you go bundles, you probably (should) go extensions anyway.
If you want a more simple bundle i'd prefer the approach from #19596.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@javiereguiluz buildContainer is already taken
@tgalopin in #19205 you've added the annotated class cache and in #18533 you've added the class cache warmer. However, the kernel never received a variant of this. What is this for? I noticed that it never loads the annotated classes but it does load the normal class cache. However, there's also a ClassCacheCacheWarmer that does this. @fabpot do you know what the idea behind this is? I'm wondering if something is broken here. protected function doLoadClassCache($name, $extension)
{
if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) {
ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension);
}
} |
Added tests, everything seems to work now. |
@iltar the annotated class requires an optimized composer autoloader to work, this maybe why you don't see it working? |
@nicolas-grekas I was wondering why the kernel does load the class cache while there's also a class cache warmer, but only a class cache warmer for the annotation variant. It feels like the kernel variant could be removed. |
Could be yes, now that the cache warmer should be working as expected in 3.2. |
} | ||
|
||
foreach ($extension->getAnnotatedClassesToCompile() as $annotatedClass) { | ||
$annotatedClasses[] = $annotatedClass; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why stop using array_merge
rather than a foreach
here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically due to performance. Array merge in loops is slow (at least in php5, haven't benchmarked 7 myself): https://github.com/dseguy/clearPHP/blob/master/rules/no-array_merge-in-loop.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this is a performance optimization, you should submit it separately, as it may be worth merging it into 3.2 already.
Anything still required for this PR? @javiereguiluz had a comment about the name of the method, but the suggested name is already taken. |
What about a That would fix correct naming. |
@@ -595,6 +630,9 @@ protected function prepareContainer(ContainerBuilder $container) | |||
$container->addObjectResource($bundle); | |||
} | |||
} | |||
|
|||
$this->build($container); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would put it after bundles, to match the common convention to register your AppBundle last, which would match making AppKernel last when calling build
.
Registering normal compiler passes of the project after the core normal compiler passes is more logical IMO, and would limit the need to use priority overrides.
@@ -447,6 +471,17 @@ protected function initializeBundles() | |||
} | |||
|
|||
/** | |||
* The extension point similar to the Bundle::build() method. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
technically, you can already achieve this by overriding Kernel::buildContainer
, as long as you take care to start by calling the parent method.
} | ||
|
||
foreach ($extension->getAnnotatedClassesToCompile() as $annotatedClass) { | ||
$annotatedClasses[] = $annotatedClass; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this is a performance optimization, you should submit it separately, as it may be worth merging it into 3.2 already.
|
Status: Needs Review |
👍 Status: Reviewed |
Failure is unrelated: |
Thank you @iltar. |
…build() (iltar) This PR was merged into the 3.3-dev branch. Discussion ---------- Added a build method to the kernel to replace Bundle::build() | Q | A | | --- | --- | | Branch? | master | | Bug fix? | no | | New feature? | yes | | BC breaks? | no | | Deprecations? | no | | Tests pass? | yes | | Fixed tickets | #20099 | | License | MIT | | Doc PR | ~ | Adds a DX method to make it easier to omit using an AppBundle in your application. **Old situation** ``` php // src/AppBundle.php class AppBundle extends Bundle { public function build(ContainerBuilder $container) { $container->addCompilerPass(new SomeCompilerPass()); $container->addCompilerPass(new AnotherCompilerPass()); $container->addCompilerPass(new YetAnotherCompilerPass()); } } // src/DependencyInjection/AppExtension.php class AppExtension extends Extension { public function load(array $config, ContainerBuilder $container) { $binary = ExecutableResolver::getPath($container->getParameter('kernel.root_dir').'/../'); $snappyConfig = ['pdf' => ['binary' => realpath($binary)]]; $container->prependExtensionConfig('knp_snappy', $snappyConfig); } } ``` **New situation** ``` php // rm src/AppBundle.php // rm src/DependencyInjection/AppExtension.php // app/AppKernel.php class AppKernel extends Kernel { protected function build(ContainerBuilder $container) { $binary = ExecutableResolver::getPath($container->getParameter('kernel.root_dir').'/../'); $snappyConfig = ['pdf' => ['binary' => realpath($binary)]]; $container->prependExtensionConfig('knp_snappy', $snappyConfig); $container->addCompilerPass(new SomeCompilerPass()); $container->addCompilerPass(new AnotherCompilerPass()); $container->addCompilerPass(new YetAnotherCompilerPass()); } } ``` Still missing tests, wondering if worth adding in this state first. Commits ------- 62e80fc Added build and class cache to kernel
Adds a DX method to make it easier to omit using an AppBundle in your application.
Old situation
New situation
Still missing tests, wondering if worth adding in this state first.