-
Notifications
You must be signed in to change notification settings - Fork 5
GitAuto: [FEATURE] Add Auto-Registration and Dependency Resolution to DI Container in Pancake #253
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
base: main
Are you sure you want to change the base?
Changes from all commits
8aca1aa
9568370
9cb19e5
5e8725c
d37137d
ecba022
3f4e0a4
6b1bc25
6bc07a7
80944da
9ee215a
9ab53ce
31de321
d70f362
8a7e57b
5521cb6
f4db55b
15edcc7
dc1b948
d40498f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| # DIContainer Documentation | ||
|
|
||
| The `DIContainer` class provides a simple and flexible Dependency Injection (DI) Container with auto-registration and automatic dependency resolution features. | ||
|
|
||
| ## Features | ||
|
|
||
| - **Auto-Registration**: Automatically registers services that are not explicitly registered. | ||
| - **Automatic Dependency Resolution**: Resolves all dependencies, including constructor dependencies, recursively. | ||
| - **Configurable**: Auto-registration can be enabled or disabled as needed. | ||
|
|
||
| ## Usage | ||
|
|
||
| ### Enabling Auto-Registration | ||
|
|
||
| By default, auto-registration is enabled. You can create a `DIContainer` instance and resolve services without explicit registration: | ||
|
|
||
| ```php | ||
| $container = new DIContainer(); | ||
| $service = $container->resolve(MyService::class); | ||
| ``` | ||
|
|
||
| ### Disabling Auto-Registration | ||
|
|
||
| To disable auto-registration, pass `false` to the constructor: | ||
|
|
||
| ```php | ||
| $container = new DIContainer(false); | ||
| ``` | ||
|
|
||
| ### Registering Services Explicitly | ||
|
|
||
| You can still register services explicitly using `registerSingleton` or `registerTransient`: | ||
|
|
||
| ```php | ||
| $container->registerSingleton(MyService::class, new MyService()); | ||
| $container->registerTransient(MyOtherService::class, function() { | ||
| return new MyOtherService(); | ||
| }); | ||
| ``` | ||
|
|
||
| ### Handling Dependencies | ||
|
|
||
| The container automatically resolves dependencies for services with constructor arguments: | ||
|
|
||
| ```php | ||
| class MyService { | ||
| public function __construct(Dependency $dependency) {} | ||
| } | ||
|
|
||
| $service = $container->resolve(MyService::class); | ||
| ``` | ||
|
|
||
| ## Exception Handling | ||
|
|
||
| If a service cannot be resolved, an exception is thrown with a clear message: | ||
|
|
||
| - **Service Not Found**: When auto-registration is disabled and a service is not registered. | ||
| - **Cannot Resolve Dependency**: When a dependency cannot be resolved due to missing type hints or non-existent classes. | ||
|
|
||
| ## Considerations | ||
|
|
||
| - Explicitly registered services take precedence over auto-registered services. | ||
| - Ensure that all dependencies have appropriate type hints for successful resolution. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| <?php | ||
|
|
||
| class DIContainer | ||
| { | ||
| private $services = []; | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line(s) before first member var; 0 found Warning
Expected 1 blank line(s) before first member var; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Missing member variable doc comment Warning
Missing member variable doc comment
|
||
| private $autoRegisterEnabled = true; | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line(s) before member var; 0 found Warning
Expected 1 blank line(s) before member var; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Missing member variable doc comment Warning
Missing member variable doc comment
|
||
|
|
||
| public function __construct($autoRegisterEnabled = true) | ||
Check warningCode scanning / Phpcs (reported by Codacy) Incorrect spacing between default value and equals sign for argument "$autoRegisterEnabled"; expected 0 but found 1 Warning
Incorrect spacing between default value and equals sign for argument "$autoRegisterEnabled"; expected 0 but found 1
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines before function; 1 found Warning
Expected 2 blank lines before function; 1 found
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function __construct() Warning
Missing doc comment for function __construct()
Check warningCode scanning / Phpcs (reported by Codacy) Incorrect spacing between argument "$autoRegisterEnabled" and equals sign; expected 0 but found 1 Warning
Incorrect spacing between argument "$autoRegisterEnabled" and equals sign; expected 0 but found 1
|
||
| { | ||
| $this->autoRegisterEnabled = $autoRegisterEnabled; | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 1 found Warning
Expected 2 blank lines after function; 1 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning
Expected 1 blank line before closing function brace; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end __construct() Warning
Expected //end __construct()
|
||
|
|
||
| public function resolve($name) | ||
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function resolve() Warning
Missing doc comment for function resolve()
|
||
| { | ||
| if (isset($this->services[$name])) { | ||
Check noticeCode scanning / Phpcs (reported by Codacy) Implicit true comparisons prohibited; use === TRUE instead Note
Implicit true comparisons prohibited; use === TRUE instead
|
||
| return $this->services[$name]; | ||
| } | ||
|
|
||
| if ($this->autoRegisterEnabled) { | ||
Check noticeCode scanning / Phpcs (reported by Codacy) Implicit true comparisons prohibited; use === TRUE instead Note
Implicit true comparisons prohibited; use === TRUE instead
|
||
| return $this->autoRegister($name); | ||
| } | ||
|
|
||
| throw new Exception("Service not found: $name"); | ||
Check failureCode scanning / Phpcs (reported by Codacy) All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '"Service not found: $name"'. Error
All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '"Service not found: $name"'.
|
||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end resolve() Warning
Expected //end resolve()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 1 found Warning
Expected 2 blank lines after function; 1 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning
Expected 1 blank line before closing function brace; 0 found
|
||
|
|
||
| private function autoRegister($name) | ||
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function autoRegister() Warning
Missing doc comment for function autoRegister()
|
||
| { | ||
| if (!class_exists($name)) { | ||
Check noticeCode scanning / Phpcs (reported by Codacy) Operator ! prohibited; use === FALSE instead Note
Operator ! prohibited; use === FALSE instead
|
||
| throw new Exception("Class not found: $name"); | ||
Check failureCode scanning / Phpcs (reported by Codacy) All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '"Class not found: $name"'. Error
All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '"Class not found: $name"'.
|
||
| } | ||
|
|
||
| $reflectionClass = new ReflectionClass($name); | ||
| $constructor = $reflectionClass->getConstructor(); | ||
|
|
||
| if (is_null($constructor)) { | ||
Check failureCode scanning / Phpcs (reported by Codacy) The use of function is_null() is discouraged; use strict comparison "=== null" instead. Error
The use of function is_null() is discouraged; use strict comparison "=== null" instead.
Check noticeCode scanning / Phpcs (reported by Codacy) Implicit true comparisons prohibited; use === TRUE instead Note
Implicit true comparisons prohibited; use === TRUE instead
|
||
| return new $name(); | ||
| } | ||
|
|
||
| $parameters = $constructor->getParameters(); | ||
| $dependencies = []; | ||
|
|
||
| foreach ($parameters as $parameter) { | ||
| $dependencyClass = $parameter->getClass(); | ||
| if (is_null($dependencyClass)) { | ||
Check failureCode scanning / Phpcs (reported by Codacy) The use of function is_null() is discouraged; use strict comparison "=== null" instead. Error
The use of function is_null() is discouraged; use strict comparison "=== null" instead.
Check noticeCode scanning / Phpcs (reported by Codacy) Implicit true comparisons prohibited; use === TRUE instead Note
Implicit true comparisons prohibited; use === TRUE instead
|
||
| throw new Exception("Cannot resolve dependency: " . $parameter->getName()); | ||
Check failureCode scanning / Phpcs (reported by Codacy) All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '$parameter'. Error
All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '$parameter'.
Check warningCode scanning / Phpcs (reported by Codacy) Concat operator must not be surrounded by spaces Warning
Concat operator must not be surrounded by spaces
|
||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) No blank line found after control structure Warning
No blank line found after control structure
|
||
| $dependencies[] = $this->resolve($dependencyClass->getName()); | ||
| } | ||
|
|
||
| return $reflectionClass->newInstanceArgs($dependencies); | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end autoRegister() Warning
Expected //end autoRegister()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning
Expected 1 blank line before closing function brace; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 1 found Warning
Expected 2 blank lines after function; 1 found
|
||
|
|
||
| public function setAutoRegisterEnabled(bool $enabled) | ||
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function setAutoRegisterEnabled() Warning
Missing doc comment for function setAutoRegisterEnabled()
|
||
| { | ||
| $this->autoRegisterEnabled = $enabled; | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 1 found Warning
Expected 2 blank lines after function; 1 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end setAutoRegisterEnabled() Warning
Expected //end setAutoRegisterEnabled()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning
Expected 1 blank line before closing function brace; 0 found
|
||
|
|
||
| public function registerSingleton($name, $instance) | ||
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function registerSingleton() Warning
Missing doc comment for function registerSingleton()
|
||
| { | ||
| $this->services[$name] = $instance; | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 1 found Warning
Expected 2 blank lines after function; 1 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end registerSingleton() Warning
Expected //end registerSingleton()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning
Expected 1 blank line before closing function brace; 0 found
|
||
|
|
||
| public function registerTransient($name, $closure) | ||
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function registerTransient() Warning
Missing doc comment for function registerTransient()
|
||
| { | ||
| $this->services[$name] = $closure(); | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning
Expected 1 blank line before closing function brace; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end registerTransient() Warning
Expected //end registerTransient()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 0 found Warning
Expected 2 blank lines after function; 0 found
|
||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end class Warning
Expected //end class
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| <?php | ||
|
|
||
| use PHPUnit\Framework\TestCase; | ||
|
|
||
| class DIContainerTest extends TestCase | ||
| { | ||
| public function testAutoRegistration() | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines before function; 0 found Warning test
Expected 2 blank lines before function; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function testAutoRegistration() Warning test
Missing doc comment for function testAutoRegistration()
|
||
| { | ||
| $container = new DIContainer(); | ||
| $service = $container->resolve(TestService::class); | ||
| $this->assertInstanceOf(TestService::class, $service); | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end testAutoRegistration() Warning test
Expected //end testAutoRegistration()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning test
Expected 1 blank line before closing function brace; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 1 found Warning test
Expected 2 blank lines after function; 1 found
|
||
|
|
||
| public function testDependencyResolution() | ||
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function testDependencyResolution() Warning test
Missing doc comment for function testDependencyResolution()
|
||
| { | ||
| $container = new DIContainer(); | ||
| $service = $container->resolve(ServiceWithDependencies::class); | ||
| $this->assertInstanceOf(ServiceWithDependencies::class, $service); | ||
| $this->assertInstanceOf(Dependency::class, $service->getDependency()); | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end testDependencyResolution() Warning test
Expected //end testDependencyResolution()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 1 found Warning test
Expected 2 blank lines after function; 1 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning test
Expected 1 blank line before closing function brace; 0 found
|
||
|
|
||
| public function testAutoRegistrationDisabled() | ||
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function testAutoRegistrationDisabled() Warning test
Missing doc comment for function testAutoRegistrationDisabled()
|
||
| { | ||
| $this->expectException(Exception::class); | ||
| $this->expectExceptionMessage('Service not found: UnregisteredService'); | ||
|
|
||
| $container = new DIContainer(false); | ||
| $container->resolve(UnregisteredService::class); | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end testAutoRegistrationDisabled() Warning test
Expected //end testAutoRegistrationDisabled()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 1 found Warning test
Expected 2 blank lines after function; 1 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning test
Expected 1 blank line before closing function brace; 0 found
|
||
|
|
||
| public function testExceptionHandlingForUnresolvableDependency() | ||
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function testExceptionHandlingForUnresolvableDependency() Warning test
Missing doc comment for function testExceptionHandlingForUnresolvableDependency()
|
||
| { | ||
| $this->expectException(Exception::class); | ||
| $this->expectExceptionMessage('Cannot resolve dependency: unresolvable'); | ||
|
|
||
| $container = new DIContainer(); | ||
| $container->resolve(ServiceWithUnresolvableDependency::class); | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning test
Expected 1 blank line before closing function brace; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 0 found Warning test
Expected 2 blank lines after function; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end testExceptionHandlingForUnresolvableDependency() Warning test
Expected //end testExceptionHandlingForUnresolvableDependency()
|
||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end class Warning test
Expected //end class
|
||
|
|
||
| class TestService | ||
| { | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end class Warning test
Expected //end class
|
||
|
|
||
| class Dependency | ||
| { | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end class Warning test
Expected //end class
|
||
|
|
||
| class ServiceWithDependencies | ||
| { | ||
| private $dependency; | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line(s) before first member var; 0 found Warning test
Expected 1 blank line(s) before first member var; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Missing member variable doc comment Warning test
Missing member variable doc comment
|
||
|
|
||
| public function __construct(Dependency $dependency) | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines before function; 1 found Warning test
Expected 2 blank lines before function; 1 found
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function __construct() Warning test
Missing doc comment for function __construct()
|
||
| { | ||
| $this->dependency = $dependency; | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 1 found Warning test
Expected 2 blank lines after function; 1 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end __construct() Warning test
Expected //end __construct()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning test
Expected 1 blank line before closing function brace; 0 found
|
||
|
|
||
| public function getDependency() | ||
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function getDependency() Warning test
Missing doc comment for function getDependency()
|
||
| { | ||
| return $this->dependency; | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end getDependency() Warning test
Expected //end getDependency()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning test
Expected 1 blank line before closing function brace; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 0 found Warning test
Expected 2 blank lines after function; 0 found
|
||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end class Warning test
Expected //end class
|
||
|
|
||
| class UnregisteredService | ||
| { | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end class Warning test
Expected //end class
|
||
|
|
||
| class ServiceWithUnresolvableDependency | ||
| { | ||
| public function __construct($unresolvable) | ||
Check warningCode scanning / Phpcs (reported by Codacy) Missing doc comment for function __construct() Warning test
Missing doc comment for function __construct()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines before function; 0 found Warning test
Expected 2 blank lines before function; 0 found
|
||
Check noticeCode scanning / Phpmd (reported by Codacy) This rule prohibits the definition of unused parameters in methods or constructors. Note test
Avoid unused parameters such as '$unresolvable'.
|
||
| { | ||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected 2 blank lines after function; 0 found Warning test
Expected 2 blank lines after function; 0 found
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end __construct() Warning test
Expected //end __construct()
Check warningCode scanning / Phpcs (reported by Codacy) Expected 1 blank line before closing function brace; 0 found Warning test
Expected 1 blank line before closing function brace; 0 found
|
||
| } | ||
Check warningCode scanning / Phpcs (reported by Codacy) Expected //end class Warning test
Expected //end class
|
||
Check warning
Code scanning / Markdownlint (reported by Codacy)
Expected: 1; Actual: 3 Warning