Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/Adapter/ArrayContainerAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ class ArrayContainerAdapter implements ContainerInterface
*/
private $arrayContainer;

private bool $useOptimizedLookup;

/**
* ArrayContainerAdapter constructor.
* @param array|\ArrayAccess $arrayContainer
*/
public function __construct($arrayContainer)
{
$this->arrayContainer = $arrayContainer;
$this->useOptimizedLookup = is_object($arrayContainer) && method_exists($arrayContainer, 'getIfDefined');
}

/**
Expand All @@ -38,12 +41,41 @@ public function __construct($arrayContainer)
*/
public function get($id)
{
if ($this->useOptimizedLookup) {
try {
return $this->arrayContainer[$id];
} catch (\InvalidArgumentException $e) {
throw new ServiceNotFoundException("Service not found in container ($id).", 0, $e);
}
}
if (!isset($this->arrayContainer[$id])) {
throw new ServiceNotFoundException("Service not found in container ($id).");
}
return $this->arrayContainer[$id];
}

/**
* Check if the entry exists and retrieve it in a single operation.
* Avoids the double container lookup of separate has() + get() calls.
* When the underlying container supports getIfDefined (e.g. JITContainer),
* this reduces provider loading from 3 calls to 1.
*
* @param string $id Identifier of the entry to look for.
* @param mixed $result Will be set to the entry value if found.
* @return bool True if the entry was found.
*/
public function getIfDefined(string $id, mixed &$result): bool
{
if ($this->useOptimizedLookup) {
return $this->arrayContainer->getIfDefined($id, $result);
}
if (!isset($this->arrayContainer[$id])) {
return false;
}
$result = $this->arrayContainer[$id];
return true;
}

/**
* Returns true if the container can return an entry for the given identifier.
* Returns false otherwise.
Expand Down
16 changes: 13 additions & 3 deletions src/Injector.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ class Injector implements InjectorInterface
*/
private array $autoCreateCache = [];

private readonly bool $hasGetIfDefined;

public function __construct(private readonly ContainerInterface $container, private readonly ClassInspectorInterface $classInspector)
{
$this->hasGetIfDefined = method_exists($container, 'getIfDefined');
}

/**
Expand Down Expand Up @@ -237,15 +240,22 @@ private function buildParameterArray($methodSignature, $providedParameters)
private function buildParameterArrayFromContainer($methodSignature)
{
$parameters = [];
$container = $this->container;
$useOptimized = $this->hasGetIfDefined;
foreach ($methodSignature as $position => $parameterData) {
if (isset($parameterData['variadic'])) {
// variadic with no provided params = nothing to pipe
break;
}
$type = $parameterData['type'] ?? false;
if ($type) {
if ($this->container->has($type)) {
$parameters[$position] = $this->container->get($type);
if ($useOptimized) {
$value = null;
if ($container->getIfDefined($type, $value)) {
$parameters[$position] = $value;
continue;
}
} elseif ($container->has($type)) {
$parameters[$position] = $container->get($type);
continue;
}
if ($this->canAutoCreate($type)) {
Expand Down
11 changes: 11 additions & 0 deletions src/Reflection/CachingClassInspector.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ class CachingClassInspector implements ClassInspectorInterface
*/
private array $constructorCache = [];

/**
* @var array<string, array>
*/
private array $methodSignatureCache = [];

public function __construct(
private readonly ClassInspector $classInspector,
private readonly ServiceCacheInterface $serviceCache,
Expand Down Expand Up @@ -93,6 +98,11 @@ public function methodIsPublic(string $class, string $method): bool
*/
public function getMethodSignature(string $class, string $method): array
{
$cacheKey = "$class::$method";
if (isset($this->methodSignatureCache[$cacheKey])) {
return $this->methodSignatureCache[$cacheKey];
}

$key = "$class::{$method}::signature";
if ($this->serviceCache->has($key)) {
$value = $this->serviceCache->get($key);
Expand All @@ -101,6 +111,7 @@ public function getMethodSignature(string $class, string $method): array
$this->serviceCache->set($key, $value);
}

$this->methodSignatureCache[$cacheKey] = $value;
return $value;
}

Expand Down