Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP][class] Prosty container
untorched
post 5.10.2014, 00:16:09
Post #1





Grupa: Zarejestrowani
Postów: 318
Pomógł: 76
Dołączył: 27.12.2011
Skąd: Dąbrowa Górnicza

Ostrzeżenie: (0%)
-----


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ć smile.gif
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 smile.gif

  1. class Container implements ArrayAccess {
  2.  
  3. protected $bindings = array();
  4.  
  5. protected $instances = array();
  6.  
  7. private $maxdepth = 10;
  8.  
  9. // ================================================== //
  10.  
  11. public function make($key, $params = array())
  12. {
  13. if($bind = $this->getBinding($key))
  14. {
  15. if(isset($bind['closure']))
  16. {
  17. if(isset($bind['singleton']) and $bind['singleton'] === true)
  18. {
  19. $bind['instance'] = $bind['closure']();
  20. $this->instances[$key] = $bind['instance'];
  21.  
  22. unset($this->bindings[$key]['closure'], $this->bindings[$key]['singleton']);
  23. }
  24. else
  25. {
  26. $bind['instance'] = $bind['closure']();
  27. }
  28. }
  29.  
  30. return $bind['instance'];
  31. }
  32. else
  33. {
  34. $ret = $this->makeClassWithParams($key, (array)$params);
  35.  
  36. if($ret != false)
  37. {
  38. $this->bind($key, $ret);
  39. }
  40.  
  41. return $ret;
  42. }
  43. }
  44.  
  45. public function bind($key, $value)
  46. {
  47. return $this->makeBinding($key, $value, false);
  48. }
  49.  
  50. public function singleton($key, $value)
  51. {
  52. return $this->makeBinding($key, $value, true);
  53. }
  54.  
  55. // ================================================== //
  56.  
  57. protected function makeClassWithParams($name, array $params, $depth = 1)
  58. {
  59. if($depth >= $this->maxdepth)
  60. {
  61. throw new OutOfBoundsException('Maximum depth of makeClassWithParams is '.$this->maxdepth);
  62. return false;
  63. }
  64.  
  65. if(class_exists($name))
  66. {
  67. $class = new ReflectionClass($name);
  68.  
  69. $constructor = $class->getConstructor()->getParameters();
  70.  
  71.  
  72. if(!empty($constructor) and empty($params))
  73. {
  74. $constructor = $class->getConstructor()->getParameters();
  75.  
  76. foreach($constructor as $classparam)
  77. {
  78. $classparam = $classparam->getClass();
  79.  
  80. if(is_null($classparam))
  81. {
  82. $params[] = null;
  83. }
  84. else
  85. {
  86. $params[] = $this->makeClassWithParams($classparam->name, array(), $depth+1);
  87. }
  88. }
  89.  
  90. $class = $class->newInstanceArgs($params);
  91. }
  92. else
  93. {
  94. $class = $class->newInstanceArgs($params);
  95. }
  96.  
  97. return $class;
  98. }
  99. else
  100. {
  101. echo $name;
  102. return false;
  103. }
  104. }
  105.  
  106. protected function makeBinding($key, $value, $singleton)
  107. {
  108. $this->clearBinding($key);
  109.  
  110. $bind = array();
  111.  
  112. $bind['instance'] = $key;
  113.  
  114. if($value instanceof Closure)
  115. {
  116. $bind['closure'] = $value;
  117. $bind['singleton'] = (bool)$singleton;
  118. }
  119. else
  120. {
  121. $bind['instance'] = $value;
  122. }
  123.  
  124. if(isset($bind['instance']))
  125. {
  126. $this->instances[$key] = $bind['instance'];
  127. }
  128. else
  129. {
  130. $this->instances[$key] = null;
  131. }
  132.  
  133. $bind['instance'] = $key;
  134.  
  135. $this->bindings[$key] = $bind;
  136. }
  137.  
  138. protected function getBinding($key)
  139. {
  140. if(isset($this->bindings[$key]))
  141. {
  142. $bind = $this->bindings[$key];
  143.  
  144. if(! is_null($this->instances[$key]))
  145. {
  146. $bind['instance'] = $this->instances[$key];
  147. }
  148.  
  149. return $bind;
  150. }
  151.  
  152. return false;
  153. }
  154.  
  155. protected function clearBinding($key)
  156. {
  157. unset($this->bindings[$key], $this->instances[$key]);
  158. }
  159.  
  160. // ================================================== //
  161.  
  162. public function offsetGet($key)
  163. {
  164. return $this->make($key);
  165. }
  166.  
  167. public function offsetSet($key, $value)
  168. {
  169. $function = function() use ($value) {
  170. return $value;
  171. };
  172.  
  173. $this->bind($key, $function);
  174. }
  175.  
  176. public function offsetExists($key)
  177. {
  178. return isset($this->bindings['key']);
  179. }
  180.  
  181. public function offsetUnset($key)
  182. {
  183. $this->clearBinding($key);
  184. }
  185.  
  186. public function __set($key, $value)
  187. {
  188. $this[$key] = $value;
  189. }
  190.  
  191. public function __get($key)
  192. {
  193. return $this[$key];
  194. }
  195.  
  196. }


Ten post edytował untorched 5.10.2014, 00:50:05
Go to the top of the page
+Quote Post
!*!
post 7.10.2014, 08:33:12
Post #2





Grupa: Zarejestrowani
Postów: 4 298
Pomógł: 447
Dołączył: 16.11.2006

Ostrzeżenie: (0%)
-----


Byłoby prościej jakbyś napisał o co w tym chodzi, jak tego użyć i stworzył dokumentacje ;)


--------------------
Nie udzielam pomocy poprzez PW i nie mam GG.
Niektóre języki programowania, na przykład C# są znane z niezwykłej przenośności (kompatybilność ze wszystkimi wersjami Visty jest wiele warta).
Go to the top of the page
+Quote Post
Daimos
post 7.10.2014, 21:26:06
Post #3





Grupa: Zarejestrowani
Postów: 1 319
Pomógł: 118
Dołączył: 26.11.2003
Skąd: Lublin

Ostrzeżenie: (0%)
-----


Kurcze też Wam zahashowało komentarze na // ================================================== //
?
wink.gif


--------------------
scriptun.com. Startup z poradnikami do gier ttp.zone i ttpzone.pl
Go to the top of the page
+Quote Post
untorched
post 8.10.2014, 21:55:58
Post #4





Grupa: Zarejestrowani
Postów: 318
Pomógł: 76
Dołączył: 27.12.2011
Skąd: Dąbrowa Górnicza

Ostrzeżenie: (0%)
-----


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

  1. // Tworzenie instancji kontrolera, można również rozszerzyć jakąś klasę
  2. $container = new Container();
  3.  
  4. // Dodanie tekstu do kontenera
  5. $container->bind('tekst', 'Dowolna zawartość do przechowania');
  6.  
  7. // Dodawanie stworzonej instancji do kontenera
  8. $container->bind('instancja', $container);
  9.  
  10. // Dodanie funkcji anonimowej do kontenera
  11. $container->bind('funkcja_anonimowa', function() {
  12. return rand();
  13. });
  14.  
  15. // Dodanie funkcji anonimowej jako singleton do kontenera
  16. $container->bind('funkcja_anonimowa_singleton', function() {
  17. return rand();
  18. }, true);
  19.  
  20. // Tworzenie klasy przy użyciu kontenera wraz z wymaganymi parametrami konstruktora
  21. class Test1 {}
  22. class Test2 {}
  23. class Test3 {}
  24.  
  25. class Example {
  26. public function __construct(Test1 $test1, Test2 $test2, Test3 $test3) {}
  27. }
  28.  
  29. $container->make('Example');
  30.  
  31. // ================================================================= //
  32.  
  33. /**
  34.  * Testowanie przechowywanych rzeczy.
  35.  * Można użyć $container->nazwa_bindu;
  36.  * Można użyć $container->make('nazwa_bindu');
  37.  * Można użyć $container['nazwa_bindu'];
  38.  */
  39.  
  40. var_dump($container->tekst);
  41.  
  42. var_dump($container->make('instancja'));
  43.  
  44. var_dump($container['funkcja_anonimowa']);
  45.  
  46. var_dump($container['funkcja_anonimowa_singleton']);
  47.  
  48. var_dump($container['Example']);


Powinno wszystko działać. Aczkolwiek liczę się z tym, że możliwie popełniłem tu kilka błędów.
Proszę o opinie na temat kodu, wygody użycia, braków itd.
Go to the top of the page
+Quote Post
!*!
post 9.10.2014, 17:36:27
Post #5





Grupa: Zarejestrowani
Postów: 4 298
Pomógł: 447
Dołączył: 16.11.2006

Ostrzeżenie: (0%)
-----


  1. class Demo
  2. {
  3. public $text;
  4.  
  5. public function __construct($text = 'yyyyyyy')
  6. {
  7. $this->text = $text;
  8. }
  9. public function test()
  10. {
  11. return rand();
  12. }
  13.  
  14. public function add($t)
  15. {
  16. $this->text = $t;
  17. }
  18. }


  1. $di->make('Demo');


  1. var_dump($di->Demo->text);

Zwróci null.


--------------------
Nie udzielam pomocy poprzez PW i nie mam GG.
Niektóre języki programowania, na przykład C# są znane z niezwykłej przenośności (kompatybilność ze wszystkimi wersjami Visty jest wiele warta).
Go to the top of the page
+Quote Post
untorched
post 9.10.2014, 22:50:16
Post #6





Grupa: Zarejestrowani
Postów: 318
Pomógł: 76
Dołączył: 27.12.2011
Skąd: Dąbrowa Górnicza

Ostrzeżenie: (0%)
-----


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 smile.gif
Go to the top of the page
+Quote Post
!*!
post 11.10.2014, 13:06:00
Post #7





Grupa: Zarejestrowani
Postów: 4 298
Pomógł: 447
Dołączył: 16.11.2006

Ostrzeżenie: (0%)
-----


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.


--------------------
Nie udzielam pomocy poprzez PW i nie mam GG.
Niektóre języki programowania, na przykład C# są znane z niezwykłej przenośności (kompatybilność ze wszystkimi wersjami Visty jest wiele warta).
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 28.03.2024 - 12:30