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:
<?php
/**
* Manager Instancji. Tworzy oraz zarządza instancjami klas.
*
* @date 2006.07.01
* @author Grzegorz Drozd
* @package ae
*/
class aeInstanceManager {
/**
* @var string nazwa właściwości klasy która decyduje czy jest to singleton czy
nie
*/
const SINGLE_PROPERTY_NAME= 'aeSingleton';
/**
* @var bool domyślne traktowanie statusu klasy, w przypadku gdy dana klasa nie
ma ustawionego statusu
*/
const SINGLE_DEFAULT_VALUE= false;
/**
* @var string nazwa pola do którego należy wpisać nazwę instancji w gotowym obi
ekcie
*/
const INSTANCE_NAME_PROPERTY= 'aeInstance';
/**
* @var array przechowuje instancje klas
*/
/**
* Nie można tworzyć instancji tej klasy.
*/
final private function __construct() {
}
/**
* Postawowa metoda klasy. Zwraca obiekt danego typu.
*
* Parametry klasy są całkowicie zmienne poza pierwszym.
* Nie podanie nazwy instancji a wymaganie nowej instancji powoduje wygenerowani
e nazwy automatycznie na podstawie nazwy klasy oraz
* microtime.
*
*
* @param mixed $className string z nazwą klasy lub array z nazwą klasy oraz met
odą służącą do zwracania obiektu
*
* Akceptowalne parametry zmienne:
* @param string nazwa instancji
* @param bool true - zwraca singleton, false - zwraca nową instację
* @param array argumenty do przekazania nowo tworzonej instacji
*/
static public function getInstance
($className, $p1= null, $p2= null, $p3= null) { self::checkVersion();
$single= aeClassManager :: SINGLE_DEFAULT_VALUE;
$singleSet= false;
//sprawdzenie jakie parametry zostały podane
case 'string' :
case 'integer' :
break;
case 'array' :
break;
case 'boolean' :
// to do sprawdzenia czy podano taki argument wogóle.
$singleSet= true;
break;
}
}
$methodName = $className[1];
$className = $className[0];
}
//tworzenie nowej klasy Reflection
$class= new ReflectionClass($className);
//sprawdzenie statusu singletona
$mustBeSingleton= self :: getPropertyValue($class, aeClassManager :: SINGLE_PROPERTY_NAME);
//sprawdzenie czy argument $single jest poprawny w stosunku do własności klasy
if (($mustBeSingleton != $single XOR $singleSet != true) AND $mustBeSingleton != null) {
throw new Exception('Invalid argument, class: ' . $className. ($mustBeSingleton ? ' must be ' : " can't be ").'singleton');
}
// jeżeli obiekt o takiej nazwie instancji jest już utworzony - zwróć go
if (is_a(self :: $instances[$instanceName]['obj'], $className)) {
return self :: $instances[$instanceName];
}
// jeżeli nie podano nazwy instacji to przyjmij nazwę klasy i jeżeli nie singleton
dodaj do niej czas
if (empty ($instanceName) AND
$mustBeSingleton == false) { $instanceName= $className . '_' . (self :: getMicrotime());
} else {
$instanceName= !empty ($instanceName) ?
$instanceName : $className; }
// jeżeli wymagamy singletona - szukamy go - jeżeli nie to idziemy dalej
if ($mustBeSingleton == true AND ($retClass= self :: getInstancesOfObject($className, 1) !== false)) {
return $retClass['obj'];
}
// utowrzenie instancji klasy - poprzez odpowiednią metodę
if (!empty($methodName) AND
$class->hasMethod($methodName)){ $m = $class->getMethod($methodName);
//jeżeli nie przekazano argumentów to tworzy prostą instację
self :: $instances[$instanceName]['obj'] = $m->invoke( ($m->isStatic() ? NULL : $class) );
//lub przekazuje parametry
} else {
self :: $instances[$instanceName]['obj'] = $m->invokeArgs(($m->isStatic() ? NULL : $class), $arguments);
}
// lub konstruktor
} else {
//jeżeli nie przekazano argumentów to tworzy prostą instację
self :: $instances[$instanceName]['obj']= $class->newInstance();
//lub przekazuje argumenty
} else {
self :: $instances[$instanceName]['obj']= $class->newInstanceArgs($arguments);
}
}
// jeżeli obiekt posiada odpowiednie pole - ustaw w nie nazwę instancji.
if ($class->hasProperty(aeClassManager :: INSTANCE_NAME_PROPERTY) ) {
$varName = aeClassManager::INSTANCE_NAME_PROPERTY;
self :: $instances[$instanceName]['obj']->$varName = $instanceName;
}
//ustawienie nazwy obiektu do tabeli instances - szybsze wyszukiwanie
self :: $instances[$instanceName]['type']= $className;
return self :: $instances[$instanceName]['obj'];
}
/**
* Zwraca listę przechowywanych instancji.
*
* @return array lista instancij
*/
static public function getInstanceList
() { return self :: $instances;
}
/**
* Metoda zwraca tablicę obiektów podanego typu.
*
* @param string $objName nazwa obiektu do znalezienia na liście
* @param num $limit limit zwróconych obiektów danego typu
* @return array lista znalezionych obiektów
*/
static private function getInstancesOfObject
($objName, $limit= null) { $n= 0;
foreach (self :: $instances as $key => $val) {
if ($val['type'] == $objName) {
$ret[]= $val;
$n++;
if ($limit != null AND $limit == $n) {
break;
}
}
}
return !empty ($ret) ?
$ret : false; }
/**
* @ignore
* @internal klasa wewnętrzna tylko do tworzenia unikalnych nazw instancji
*/
static private function getMicrotime
() { return ((float) $usec + (float) $sec);
}
/**
* Funkcja zwraca z podanego obiektu typu ReflectionClass wartość pola bez wzglę
du na to
* czy to pole statyczne czy też pole normalne (wtedy ZWRACA WARTOŚĆ DOMYŚLNĄ OBIEKTU !
* a nie zmienioną - czyli taką jak w definicji obiektu)
*
* @param ReflectionClass $class klasa z której pobierane są właściwości
* @param string $property nazwa właściwości do zwrócenia
* @return mixed wartość właściwości
*/
static private function getPropertyValue
(ReflectionClass
&$class, $property) { if ($class->hasProperty($property)) {
$rp= $class->getProperty($property);
if ($rp->isStatic()) {
return $class->getStaticPropertyValue($property);
}
$ar= $class->getDefaultProperties();
return $ar[$property];
}
return null;
}
/**
* Metoda używana w destruktorach do usuwania instancji z list
*
* @todo dokończyć - nie działa
* @param string $instanceName nazwa instancji do usunięcia
*/
static public function destroyInstance
($instanceName) { unset(self::$instances[$instanceName]); }
final
static private function checkVersion
(){ throw new Exception('Incorect php version! You must use at least 5.1.3');
}
}
}
?>
Przykłady użycia:
<?php
require_once 'aeInstanceManager.class.php';
class someSingletonClass{
static public $aeSingleton = true;
public function __construct(){
}
}
class thisObjectCantBeSingleton{
public $aeSingleton = false;
public function __construct(){
}
}
class thisIsNormalObject{
public $aeInstance;
public function __construct() {
}
public function __destruct() {
aeClassManager::destroyInstance($this->aeInstance);
}
}
class singleton{
public $aeSingleton = true;
private function __construct(){
}
public static function getInstanceOfSingleton
(){ if (self::$instance == null){
$class = __CLASS__;
self::$instance = new $class;
}
return self::$instance;
}
}
//singleton - bez parametrów - kontroler zczytuje z pola w klasie
$obj1 = aeClassManager::getInstance('someSingletonClass');
$obj1 = aeClassManager::getInstance('someSingletonClass');
//tworzenie przez wywołanie specjalnej metody - działa na singletony i normalne klasy - np. db
$obj2 = aeClassManager
::getInstance(array('singleton', 'getInstanceOfSingleton'), true, array('arg1', 1
, 2
) );
//ten obiekt nie może być singletonem - dodanie parametru true wywoła wyjątek
$obj2 = aeClassManager
::getInstance('thisObjectCantBeSingleton', array('arg1', 1
, 2
) );
//parametry - poza 1szym - mogą być podawane w dowolnej kolejności
$obj4 = aeClassManager::getInstance('thisIsNormalObject', 'siakisObiekt1', false);
$obj5 = aeClassManager::getInstance('thisIsNormalObject', false, 'siakisObiekt2');
//ten obiekt zostaje singletonem - wywołanie go z tymi samymi parametrami zwróci cały czas ten sam obiekt
$obj6 = aeClassManager::getInstance('thisIsNormalObject', true, 'siakisObiekt');
$obj6 = aeClassManager::getInstance('thisIsNormalObject', true, 'siakisObiekt');
print_r(aeClassManager
::getInstanceList()); ?>
Computer games don't affect kids; I mean if <span style="font-weight: bold;">Pac Man</span> affected us as kids,we would all be running around in darkened rooms, munching magic pills and listening to repetitive electronic music.