Witam.

Podana poniżej klasa ułatwia zarządzanie grupami obiektów. Zwraca instancje obiektów do użycia wewnątrz metod i funkcji - odpada $GLOBALS i global. Wersja rozwojowa. Przyszłościowo można zintegrować z rozwiązaniem __autoload.

Klasa korzysta z Reflection API dostępnym tylko w php5 oraz z niektórych metod dostępnych od wersji 5.1.3. Jest możliwe przerobienie tego na kod bardziej uniwersalny ( przy użyciu np. eval ) ale nie mam teraz czasu na to ( może w tygodniu znajdę czas ). Rozwiązując inaczej przekazywanie parametrów można obejść użycie metody newInstanceArgs.

Kod udostępniony na licencji GPL.
Kod klasy:
  1. <?php
  2. /**
  3.  * Manager Instancji. Tworzy oraz zarządza instancjami klas.
  4.  * 
  5.  * @date 2006.07.01
  6.  * @author Grzegorz Drozd
  7.  * @package ae
  8.  */
  9. class aeInstanceManager {
  10. /**
  11.  * @var string nazwa właściwości klasy która decyduje czy jest to singleton czy 
    nie
  12.  */
  13. const SINGLE_PROPERTY_NAME= 'aeSingleton';
  14.  
  15. /**
  16.  * @var bool domyślne traktowanie statusu klasy, w przypadku gdy dana klasa nie 
    ma ustawionego statusu
  17.  */
  18. const SINGLE_DEFAULT_VALUE= false;
  19.  
  20. /**
  21.  * @var string nazwa pola do którego należy wpisać nazwę instancji w gotowym obi
    ekcie
  22.  */
  23. const INSTANCE_NAME_PROPERTY= 'aeInstance';
  24.  
  25. /**
  26.  * @var array przechowuje instancje klas
  27.  */
  28. static private $instances= array ();
  29.  
  30. /**
  31.  * Nie można tworzyć instancji tej klasy.
  32.  */
  33. final private function __construct() {
  34.  
  35. }
  36.  
  37. /**
  38.  * Postawowa metoda klasy. Zwraca obiekt danego typu.
  39.  * 
  40.  * Parametry klasy są całkowicie zmienne poza pierwszym.
  41.  * Nie podanie nazwy instancji a wymaganie nowej instancji powoduje wygenerowani
    e nazwy automatycznie na podstawie nazwy klasy oraz
  42.  * microtime.
  43.  * 
  44.  * 
  45.  * @param mixed $className string z nazwą klasy lub array z nazwą klasy oraz met
    odą służącą do zwracania obiektu
  46.  * 
  47.  * Akceptowalne parametry zmienne:
  48.  * @param string nazwa instancji
  49.  * @param bool true - zwraca singleton, false - zwraca nową instację
  50.  * @param array argumenty do przekazania nowo tworzonej instacji
  51.  */
  52. static public function getInstance($className, $p1= null, $p2= null, $p3= null) {
  53. self::checkVersion();
  54. $single= aeClassManager :: SINGLE_DEFAULT_VALUE;
  55. $singleSet= false;
  56.  
  57. //sprawdzenie jakie parametry zostały podane
  58. for ($i= 1; $i < func_num_args(); $i++) {
  59. switch (gettype(func_get_arg($i))) {
  60. case 'string' :
  61. case 'integer' :
  62. $instanceName= func_get_arg($i);
  63. break;
  64.  
  65. case 'array' :
  66. $arguments= func_get_arg($i);
  67. break;
  68.  
  69. case 'boolean' :
  70. $single= func_get_arg($i);
  71.  
  72. // to do sprawdzenia czy podano taki argument wogóle.
  73. $singleSet= true;
  74. break;
  75. }
  76. }
  77.  
  78. if (is_array($className)){
  79. $methodName = $className[1];
  80. $className = $className[0];
  81. }
  82.  
  83. //tworzenie nowej klasy Reflection
  84. $class= new ReflectionClass($className);
  85.  
  86. //sprawdzenie statusu singletona
  87. $mustBeSingleton= self :: getPropertyValue($class, aeClassManager :: SINGLE_PROPERTY_NAME);
  88.  
  89. //sprawdzenie czy argument $single jest poprawny w stosunku do własności klasy
  90. if (($mustBeSingleton != $single XOR $singleSet != true) AND $mustBeSingleton != null) {
  91. throw new Exception('Invalid argument, class: ' . $className. ($mustBeSingleton ? ' must be ' : " can't be ").'singleton');
  92. }
  93.  
  94. // jeżeli obiekt o takiej nazwie instancji jest już utworzony - zwróć go
  95. if (is_a(self :: $instances[$instanceName]['obj'], $className)) {
  96. return self :: $instances[$instanceName];
  97. }
  98.  
  99. // jeżeli nie podano nazwy instacji to przyjmij nazwę klasy i jeżeli nie singleton
     dodaj do niej czas
  100. if (empty ($instanceName) AND $mustBeSingleton == false) {
  101. $instanceName= $className . '_' . (self :: getMicrotime());
  102. } else {
  103. $instanceName= !empty ($instanceName) ? $instanceName : $className;
  104. }
  105.  
  106. // jeżeli wymagamy singletona - szukamy go - jeżeli nie to idziemy dalej
  107. if ($mustBeSingleton == true AND ($retClass= self :: getInstancesOfObject($className, 1) !== false)) {
  108. return $retClass['obj'];
  109. }
  110.  
  111. // utowrzenie instancji klasy - poprzez odpowiednią metodę
  112. if (!empty($methodName) AND $class->hasMethod($methodName)){
  113. $m = $class->getMethod($methodName);
  114. //jeżeli nie przekazano argumentów to tworzy prostą instację
  115. if (empty ($arguments) OR !is_array($arguments)) {
  116. self :: $instances[$instanceName]['obj'] = $m->invoke( ($m->isStatic() ? NULL : $class) );
  117. //lub przekazuje parametry
  118. } else {
  119. self :: $instances[$instanceName]['obj'] = $m->invokeArgs(($m->isStatic() ? NULL : $class), $arguments);
  120. }
  121.  
  122. // lub konstruktor
  123. } else {
  124. //jeżeli nie przekazano argumentów to tworzy prostą instację
  125. if (empty ($arguments) OR !is_array($arguments)) {
  126. self :: $instances[$instanceName]['obj']= $class->newInstance();
  127. //lub przekazuje argumenty
  128. } else {
  129. self :: $instances[$instanceName]['obj']= $class->newInstanceArgs($arguments);
  130. }
  131. }
  132.  
  133. // jeżeli obiekt posiada odpowiednie pole - ustaw w nie nazwę instancji.
  134. if ($class->hasProperty(aeClassManager :: INSTANCE_NAME_PROPERTY) ) {
  135. $varName = aeClassManager::INSTANCE_NAME_PROPERTY;
  136. self :: $instances[$instanceName]['obj']->$varName = $instanceName;
  137. }
  138.  
  139. //ustawienie nazwy obiektu do tabeli instances - szybsze wyszukiwanie
  140. self :: $instances[$instanceName]['type']= $className;
  141.  
  142. return self :: $instances[$instanceName]['obj'];
  143. }
  144.  
  145. /**
  146.  * Zwraca listę przechowywanych instancji.
  147.  * 
  148.  * @return array lista instancij
  149.  */
  150. static public function getInstanceList() {
  151. return self :: $instances;
  152. }
  153.  
  154. /**
  155.  * Metoda zwraca tablicę obiektów podanego typu.
  156.  * 
  157.  * @param string $objName nazwa obiektu do znalezienia na liście
  158.  * @param num $limit limit zwróconych obiektów danego typu
  159.  * @return array lista znalezionych obiektów
  160.  */
  161. static private function getInstancesOfObject($objName, $limit= null) {
  162. $ret= array ();
  163. $n= 0;
  164. foreach (self :: $instances as $key => $val) {
  165. if ($val['type'] == $objName) {
  166. $ret[]= $val;
  167. $n++;
  168. if ($limit != null AND $limit == $n) {
  169. break;
  170. }
  171. }
  172. }
  173. return !empty ($ret) ? $ret : false;
  174. }
  175.  
  176. /**
  177.  * @ignore
  178.  * @internal klasa wewnętrzna tylko do tworzenia unikalnych nazw instancji
  179.  */
  180. static private function getMicrotime() {
  181. list ($usec, $sec)= explode(" ", microtime());
  182. return ((float) $usec + (float) $sec);
  183. }
  184.  
  185. /**
  186.  * Funkcja zwraca z podanego obiektu typu ReflectionClass wartość pola bez wzglę
    du na to 
  187.  * czy to pole statyczne czy też pole normalne (wtedy ZWRACA WARTOŚĆ DOMYŚLNĄ OBIEKTU ! 
  188.  * a nie zmienioną - czyli taką jak w definicji obiektu)
  189.  * 
  190.  * @param ReflectionClass $class klasa z której pobierane są właściwości
  191.  * @param string $property nazwa właściwości do zwrócenia
  192.  * @return mixed wartość właściwości
  193.  */
  194. static private function getPropertyValue(ReflectionClass &$class, $property) {
  195. if ($class->hasProperty($property)) {
  196. $rp= $class->getProperty($property);
  197. if ($rp->isStatic()) {
  198. return $class->getStaticPropertyValue($property);
  199. }
  200.  
  201. $ar= $class->getDefaultProperties();
  202. return $ar[$property];
  203. }
  204. return null;
  205. }
  206.  
  207. /**
  208.  * Metoda używana w destruktorach do usuwania instancji z list
  209.  * 
  210.  * @todo dokończyć - nie działa
  211.  * @param string $instanceName nazwa instancji do usunięcia
  212.  */
  213. static public function destroyInstance($instanceName) {
  214. unset(self::$instances[$instanceName]);
  215. }
  216.  
  217. final static private function checkVersion(){
  218. if (version_compare('5.1.3', PHP_VERSION, '>')){
  219. throw new Exception('Incorect php version! You must use at least 5.1.3');
  220. }
  221. }
  222. }
  223. ?>


Przykłady użycia:
  1. <?php
  2.  
  3. require_once 'aeInstanceManager.class.php';
  4.  
  5. class someSingletonClass{
  6. static public $aeSingleton = true;
  7.  
  8. public function __construct(){
  9. print '1<br/>';
  10. }
  11.  
  12. }
  13.  
  14. class thisObjectCantBeSingleton{
  15. public $aeSingleton = false;
  16.  
  17. public function __construct(){
  18.  print '2<br />';
  19. }
  20. }
  21.  
  22. class thisIsNormalObject{
  23. public $aeInstance;
  24.  
  25. public function __construct() {
  26.  print '3<br />';
  27. }
  28.  
  29. public function __destruct() {
  30. aeClassManager::destroyInstance($this->aeInstance);
  31. }
  32. }
  33.  
  34. class singleton{
  35. static $instance = null;
  36. public $aeSingleton = true;
  37.  
  38. private function __construct(){
  39. print '3<br />';
  40. }
  41.  
  42. public static function getInstanceOfSingleton(){
  43. if (self::$instance == null){
  44. $class = __CLASS__;
  45. self::$instance = new $class;
  46. }
  47. return self::$instance;
  48. } 
  49. }
  50.  
  51. //singleton - bez parametrów - kontroler zczytuje z pola w klasie
  52. $obj1 = aeClassManager::getInstance('someSingletonClass');
  53. $obj1 = aeClassManager::getInstance('someSingletonClass');
  54.  
  55. //tworzenie przez wywołanie specjalnej metody - działa na singletony i normalne klasy - np. db
  56. $obj2 = aeClassManager::getInstance(array('singleton', 'getInstanceOfSingleton'), true, array('arg1', 1, 2) );
  57.  
  58. //ten obiekt nie może być singletonem - dodanie parametru true wywoła wyjątek
  59. $obj2 = aeClassManager::getInstance('thisObjectCantBeSingleton', array('arg1', 1, 2) );
  60.  
  61. //parametry - poza 1szym - mogą być podawane w dowolnej kolejności
  62. $obj4 = aeClassManager::getInstance('thisIsNormalObject', 'siakisObiekt1', false);
  63. $obj5 = aeClassManager::getInstance('thisIsNormalObject', false, 'siakisObiekt2');
  64. //ten obiekt zostaje singletonem - wywołanie go z tymi samymi parametrami zwróci cały czas ten sam obiekt
  65. $obj6 = aeClassManager::getInstance('thisIsNormalObject', true, 'siakisObiekt');
  66. $obj6 = aeClassManager::getInstance('thisIsNormalObject', true, 'siakisObiekt');
  67.  
  68. print '<pre>';
  69. print_r(aeClassManager::getInstanceList());
  70. ?>