Closed thekid closed 4 months ago
The API class uses Database and Templates traits, as well as an Injection trait:
class Api {
use Injection, Database, Templates;
public function toString(): string {
return nameof($this).'(db= '.$this->conn.', templates= '.$this->templates.')';
}
}
trait Database {
private $conn;
#[@inject(name= 'db-dsn')]
private function database(string $dsn): void {
$this->conn= $dsn;
}
}
trait Templates {
private $templates;
#[@inject(name= 'templates-path')]
private function templates(string $templates): void {
$this->templates= $templates;
}
}
The Injection trait glues it all together:
use inject\Injector;
trait Injection {
public function __construct(Injector $inject) {
$type= typeof($this);
foreach ($type->getTraits() as $trait) {
foreach ($trait->getMethods() as $m) {
$m->hasAnnotation('inject') && $this->{$m->getName()}(...$inject->args($m));
}
}
}
}
Needs this small patch to work:
diff --git a/src/main/php/inject/Injector.class.php b/src/main/php/inject/Injector.class.php
index 0165f00..7694d6c 100755
--- a/src/main/php/inject/Injector.class.php
+++ b/src/main/php/inject/Injector.class.php
@@ -128,7 +128,7 @@ class Injector {
* @return var
* @throws inject.ProvisionException
*/
- protected function args($routine, $named) {
+ public function args($routine, $named= []) {
$args= [];
foreach ($routine->getParameters() as $i => $param) {
$name= $param->getName();
Maybe use Traits as name instead of Injection?
use inject\Traits;
class Api {
use Traits, Database, Templates;
public function toString(): string {
return nameof($this).'(db= '.$this->conn.', templates= '.$this->templates.')';
}
}
Basic pattern
Problem
This works fine as long as we only want to inject one thing. If, for example, we'd also want to have a message queue injected, we couldn't simply create another trait like this; although I'd like to be able to write this:
With method injection, this would still be possible! What other method can we find here, though? /cc @mikey179