Skip to content

refactor(core): decouple discovery#2041

Draft
brendt wants to merge 19 commits into3.xfrom
discovery-improvements
Draft

refactor(core): decouple discovery#2041
brendt wants to merge 19 commits into3.xfrom
discovery-improvements

Conversation

@brendt
Copy link
Member

@brendt brendt commented Mar 11, 2026

A couple of changes with this PR:

  • Adding the Registry class, which keeps track of loaded discovery locations and classes. For now there's a passthrouh in FrameworkKernel to ensure backwards compatibility. Thanks to this class though, there are less dependencies between discovery and core
  • Also moving the Composer class from core to discovery, totally eliminating all dependencies between the two. Everything that uses Composer also uses Discovery, so I think it's fine to keep it there for now (I want to avoid making another package just for the sake of it with one class)
  • Then… what I so long resisted doing. GenericContainer now implements Psr\Container\ContainerInterface. Luckily PHP's variance checker is smart enough to allow our implementation, and it's actually compatible out of the box.
  • Finally, discovery now uses the PSR container. I first made the container fully optional, but I don't see how that's useful: you need to do something with discovered items, and I think it makes sense that all of that goes through a container of some sorts.

Here are two examples of how discovery can be used standalone. First you require tempest/discovery, nothing else.

Then, you can for example do this:

// Registry setup, `tempest/framework` does this for you, but as a standalone package you must manage it yourself.
// Probably worth improving in the future.
$registry = new Registry(locations: [
    new DiscoveryLocation('Tempest\\Discovery\\', __DIR__ . '/vendor/tempest/discovery/src/'),
    new DiscoveryLocation('App\\', __DIR__ . '/src'),
]);

// A dummy container setup, I assume a real project already has it set up. What's important is that both the registry and container itself are available in the container.
$container = new Tempest\Container\GenericContainer();
$container->singleton(Registry::class, $registry);
$container->singleton(Container::class, $container);

// This is the actual discovery code. By default, `DiscoveryConfig` will use symfony's file adapter, but people can adjust however they like. I'm going to improve this even more.
$loadDiscovery = new LoadDiscoveryClasses(
    registry: $registry,
    discoveryConfig: new DiscoveryConfig(),
    discoveryCache: new DiscoveryCache(DiscoveryCacheStrategy::NONE),
    container: $container,
);

$loadDiscovery();

Then here's an example with the php-di container:

$builder = new ContainerBuilder();
$container = $builder->build();
$container->set(Registry::class, $registry);
$container->set(Container::class, $container);
$container->set(AppDiscovery::class, new AppDiscovery($container));

$loadDiscovery = new LoadDiscoveryClasses(
    registry: $registry,
    discoveryConfig: new DiscoveryConfig(),
    discoveryCache: new DiscoveryCache(DiscoveryCacheStrategy::NONE),
    container: $container,
);

$loadDiscovery();

@brendt brendt requested a review from aidan-casey as a code owner March 11, 2026 10:10
@brendt brendt marked this pull request as draft March 11, 2026 10:10
@github-actions
Copy link

github-actions bot commented Mar 11, 2026

Benchmark Results

Comparison of discovery-improvements against 3.x (ab8cfb14398f19936e9c4be649a2c42c805dbcf1).

Open to see the benchmark results
Benchmark Set Mem. Peak Time Variability
ViewRenderBench(benchExpressions) - 23.974mb +0.01% 553.138μs +7.09% ±1.60% -51.61%

Generated by phpbench against commit f616bdc

@iamdadmin
Copy link
Contributor

Aidan's not the only one who loves the commits :D

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.

2 participants