Witam.
Chciałem przedstawić klasę prostego kontenera.
Wzorowałem się na kontenerze z laravela, lecz nie "kopiowałem", a pisałem samodzielnie, co na pewno widać
Chciałbym prosić o ocenę kodu, w miarę możliwości tego jak będzie wydajny oraz wytknięcie błędów.
Z góry dziękuję za waszą pomoc
class Container implements ArrayAccess { protected $bindings = http://www.php.net/array(); protected $instances = http://www.php.net/array(); private $maxdepth = 10; // ================================================== // public function make($key, $params = http://www.php.net/array()) { if($bind = $this->getBinding($key)) { if(http://www.php.net/isset($bind['closure'])) { if(http://www.php.net/isset($bind['singleton']) and $bind['singleton'] === true) { $bind['instance'] = $bind['closure'](); $this->instances[$key] = $bind['instance']; http://www.php.net/unset($this->bindings[$key]['closure'], $this->bindings[$key]['singleton']); } else { $bind['instance'] = $bind['closure'](); } } return $bind['instance']; } else { $ret = $this->makeClassWithParams($key, (http://www.php.net/array)$params); if($ret != false) { $this->bind($key, $ret); } return $ret; } } public function bind($key, $value) { return $this->makeBinding($key, $value, false); } public function singleton($key, $value) { return $this->makeBinding($key, $value, true); } // ================================================== // protected function makeClassWithParams($name, http://www.php.net/array $params, $depth = 1) { if($depth >= $this->maxdepth) { throw new OutOfBoundsException('Maximum depth of makeClassWithParams is '.$this->maxdepth); return false; } if(class_exists($name)) { $class = new ReflectionClass($name); $constructor = $class->getConstructor()->getParameters(); if(!http://www.php.net/empty($constructor) and http://www.php.net/empty($params)) { $constructor = $class->getConstructor()->getParameters(); foreach($constructor as $classparam) { $classparam = $classparam->getClass(); if(http://www.php.net/is_null($classparam)) { $params[] = null; } else { $params[] = $this->makeClassWithParams($classparam->name, http://www.php.net/array(), $depth+1); } } $class = $class->newInstanceArgs($params); } else { $class = $class->newInstanceArgs($params); } return $class; } else { http://www.php.net/echo $name; return false; } } protected function makeBinding($key, $value, $singleton) { $this->clearBinding($key); $bind = http://www.php.net/array(); $bind['instance'] = $key; if($value instanceof Closure) { $bind['closure'] = $value; $bind['singleton'] = (bool)$singleton; } else { $bind['instance'] = $value; } if(http://www.php.net/isset($bind['instance'])) { $this->instances[$key] = $bind['instance']; } else { $this->instances[$key] = null; } $bind['instance'] = $key; $this->bindings[$key] = $bind; } protected function getBinding($key) { if(http://www.php.net/isset($this->bindings[$key])) { $bind = $this->bindings[$key]; if(! http://www.php.net/is_null($this->instances[$key])) { $bind['instance'] = $this->instances[$key]; } return $bind; } return false; } protected function clearBinding($key) { http://www.php.net/unset($this->bindings[$key], $this->instances[$key]); } // ================================================== // public function offsetGet($key) { return $this->make($key); } public function offsetSet($key, $value) { $function = function() use ($value) { return $value; }; $this->bind($key, $function); } public function offsetExists($key) { return http://www.php.net/isset($this->bindings['key']); } public function offsetUnset($key) { $this->clearBinding($key); } public function __set($key, $value) { $this[$key] = $value; } public function __get($key) { return $this[$key]; } }
Byłoby prościej jakbyś napisał o co w tym chodzi, jak tego użyć i stworzył dokumentacje ;)
Kurcze też Wam zahashowało komentarze na // ================================================== //
?
Nie ma opcji edytuj więc muszę dorzucić to tutaj.
Przepraszam za brak komentarzy i opisu działania, nadrobiłem, są komentarze(błędy stylistyczne, błędy składni językowej lub inne dziwne rzeczy mogą się tam znaleźć niestety). Poniżej zamieszczam kod oraz użycie
http://pastebin.com/2H0FsKsB
// Tworzenie instancji kontrolera, można również rozszerzyć jakąś klasę $container = new Container(); // Dodanie tekstu do kontenera $container->bind('tekst', 'Dowolna zawartość do przechowania'); // Dodawanie stworzonej instancji do kontenera $container->bind('instancja', $container); // Dodanie funkcji anonimowej do kontenera $container->bind('funkcja_anonimowa', function() { return http://www.php.net/rand(); }); // Dodanie funkcji anonimowej jako singleton do kontenera $container->bind('funkcja_anonimowa_singleton', function() { return http://www.php.net/rand(); }, true); // Tworzenie klasy przy użyciu kontenera wraz z wymaganymi parametrami konstruktora class Test1 {} class Test2 {} class Test3 {} class Example { public function __construct(Test1 $test1, Test2 $test2, Test3 $test3) {} } $container->make('Example'); // ================================================================= // /** * Testowanie przechowywanych rzeczy. * Można użyć $container->nazwa_bindu; * Można użyć $container->make('nazwa_bindu'); * Można użyć $container['nazwa_bindu']; */ http://www.php.net/var_dump($container->tekst); http://www.php.net/var_dump($container->make('instancja')); http://www.php.net/var_dump($container['funkcja_anonimowa']); http://www.php.net/var_dump($container['funkcja_anonimowa_singleton']); http://www.php.net/var_dump($container['Example']);
class Demo { public $text; public function __construct($text = 'yyyyyyy') { $this->text = $text; } public function test() { return http://www.php.net/rand(); } public function add($t) { $this->text = $t; } }
$di->make('Demo');
http://www.php.net/var_dump($di->Demo->text);
http://pastebin.com/PUfFshcY
Poprawka.
Faktycznie nie uwzględniłem, że parametr konstruktora może posiadać wartość domyślną.
Dziękuje serdecznie !*! za znalezienie tego buga. Jeśli jest coś jeszcze to chętnie przyjmę to do informacji
Grunt, że działa. Nie wiem jak to się sprawdza w praktyce przy czymś większym. Osobiście mam wrażenie, że trochę przebajerowałeś z makeClassWithParameters i samym ReflectionClass. Choć może to tylko subiektywne odczucie.
Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)