Skip to content
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

Add container compilation #218

Merged
merged 7 commits into from
May 27, 2024
Merged

Conversation

frederikbosch
Copy link
Contributor

@frederikbosch frederikbosch commented May 16, 2024

A goal of compiling the container, is that reflection does not need to be used anymore after compilation. A compiled container knows all the object meta information to resolve/construct objects. It has only one task left: instantiating new instances.

Therefore, before creating the container compiler, we need to make sure reflection is not a requirement after unification of objects, which is a process inside Resolver. This PR will change two things.

  1. The Blueprint class constructs new objects, but used reflection to do so. From now on, it will use new $className.
  2. The expandParams call in Resolver will be moved to the Blueprint because it is part of the object construction. The method also used reflection to determine whether a parameter is variadic. From now on, the Blueprint knows all parameters of an object with its parameter settings, including if it is variadic or not. This removes another need for reflection during object construction.

And finally, this PR adds the feature of container compilation. All objects that are added through $di->params, $di->setters and $di->mutations, plus extra objects that can be passed, are compiled into blueprints.

After this PR is merged, a container might be constructed as follows.

$serializedContainerFile = '/var/compiled.ser';

if (file_exists($serializedContainerFile)) {
  $di = \unserialize(file_get_contents($serializedContainerFile));
} else {
  $config_classes = [
      new \Aura\Di\Fake\FakeLibraryConfig,
      new \Aura\Di\Fake\FakeProjectConfig,
      new \Aura\Di\Fake\FakeCompilationTestConfig(),
  ];
  
  $extra_classes = [
      FakeConstructAttributeClass::class
  ];

  $builder = new ContainerBuilder();
  $di = $builder->newCompiledInstance($config_classes, $extra_classes);

  $serialized = \serialize($di);
  file_put_contents($serializedContainerFile, $serialized); // atomic for concurrency
}

$di = $this->builder->configureCompiledInstance($di, $config_classes);

@frederikbosch frederikbosch marked this pull request as draft May 16, 2024 09:56
@frederikbosch frederikbosch marked this pull request as ready for review May 16, 2024 10:20
@frederikbosch frederikbosch changed the title Do not use reflection after unifying objects Add container compilation May 17, 2024
@frederikbosch frederikbosch mentioned this pull request May 17, 2024
7 tasks
@frederikbosch
Copy link
Contributor Author

This PR leaves one final question, at least for me, how to scan classes for attributes? Should we add such an attribute scanner? Which one is used by other projects? Or does each framework has its own scanner?

@koriym How are you solving that in your project?
@harikt Do you have any experience with that?

@koriym
Copy link
Member

koriym commented May 17, 2024

@frederikbosch BEAR.Sunday needed to support a mix of doctrine/annotations and PHP8 attributes, so I created Koriym.Attribute. (Mentioned in PHP Annotated - 2022 Spring )

The attribute read part is very simple.

https://github.com/koriym/Koriym.Attributes/blob/1.x/src/AttributeReader.php#L87-L93

@harikt
Copy link
Member

harikt commented May 18, 2024

I have no idea on this. May be want to look into other compiler DI . Also please do look into the recent discussions on the php-fig regarding compiled container.

@frederikbosch frederikbosch force-pushed the remove_reflection_from_instantiating branch from 4c18d26 to c5c7176 Compare May 22, 2024 08:16
@frederikbosch
Copy link
Contributor Author

frederikbosch commented May 22, 2024

I removed the comments I made earlier on. The solutions have been simplified significantly.

When the ContainerConfigClassScanner is added as config class to ContainerBuilder, it will scan for classes and attributes. Attributes can modify the container. This means that if it finds a #[Route] attribute, it can be added to a list of routes in the container. It is possible to do so for both self-created and external attributes. This makes Aura/Di ready to work with attributes from any project or library.

Furthermore, the documentation contains:

@frederikbosch frederikbosch force-pushed the remove_reflection_from_instantiating branch from 7d6ef5b to 5acc9bf Compare May 22, 2024 09:05
@frederikbosch
Copy link
Contributor Author

I renamed ContainerConfigClassScanner to ClassScanner. I believe there is no real value in prefixing (or post-fixing) the class name. Other than that, I think it's good to go for merging and an alpha release of 5.x.

@frederikbosch frederikbosch merged commit f6b7faf into 5.x May 27, 2024
11 checks passed
@harikt harikt deleted the remove_reflection_from_instantiating branch May 28, 2024 05:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants