Log class – klasa loggera zdarzeń cz 3

Ostatnia część tworzenia projektu loggera zdarzeń – klasy Log. Skupimy się na wykończeniu projektu, który naprawi powstałe wcześniej niedociągnięcia, trudności w korzystaniu. Utworzona klasa połączy nam wszystkie funkcjonalności w jedno. Doda kilka funkcjonalności, wprowadzi wygodę w użytkowaniu, łatwość zmian.

W pierwszej części ustaliliśmy wymagania klasy Log, ustaliliśmy strukturę, zasady funkcjonowania klasy oraz napisaliśmy interfejs.
W drugiej części rozwinęliśmy nasz projekt o klasę logFile implementującą wcześniej utworzony interfejs, omówiliśmy możliwość rozszerzeń funkcjonalności o nowe klasy (LogDB) oraz spotkaliśmy się z problemem szybkiej zmiany rodzaju wykorzystywanej klasy.

Tworzenie klasy

Stwórzmy klasę, która połączy w sobie możliwość używania różnych klas loggera (logFile, logDb). Aby zachować ustalone na początku wymagania, dać możliwość łatwego wykorzystania, szybkiej zmiany silnika bez potrzeby wielu zmian w kodzie oraz maksymalnie skrócić zapis, musimy skorzystać z kilku technologi OOP.

Pierwsza z nich – klasa statyczna, druga – singleton. Czemu tak?
Klasa statyczna + singleton załatwi nam szybkie i wygodnie użycie:

log::info('Szybko i sprawnie');

. Dzięki temu, po ustaleniu na początku skryptu silnika przechowywania logów w dalszej części możemy wygodnie korzystać z w/w zapisu. Dodatkowo przejście z logowania do pliku na logowanie do bazy nastąpi tylko w jednym miejscu. Jak zapewne zauważyliście nawet nazwa klasy została maksymalnie skrócona log, aby użycie było jak najbardziej wygodne.

Zatem do dzieła. Wzór klasy będzie następujący:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class log implements log_log{
	private static $driver;
	private static $drivers = array();
	private static $defaultDriverName = 'log_logFile';
 
	protected function __construct(){}
	protected function __clone(){}
 
	public static function instance(){}
	public static function addDriver(log_log $driver){}
	public static function useDriver($drivername=''){}
 
	public static function error($err,$driverName=''){}
	public static function warn($err,$driverName=''){}
	public static function info($err,$driverName=''){}
}
?>

Zmienne klasy

W klasie log mamy zadeklarowane 3 zmienne. Każda z nich ma swoje, łatwe do odgadnięcia, zastosowanie:
private static $driver; – aktualny sterownik klasy loggera
private static $drivers = array(); – tablica dostępnych (dodanych) sterowników
private static $defaultDriverName = 'log_logFile'; – nazwa domyślnego sterownika

Statyczna zmienna klasy $driver; przechowuje aktualnie wybrany sterownik, do którego następuje zapis logów. W trakcie korzystania z klasy będzie możliwa zmiana sterownika, dzięki temu, nawet w jednym skrypcie zachowamy możliwość wybrania innego sterownika do zapisu logu konkretnego zdarzenia.
Kolejna zmienna $drivers; jest tablicą przechowującą obiekty klas poszczególnych sterowników. Dzięki temu po jednokrotnym wykorzystaniu konkretnego sterownika, w przypadku jego ponownego użycia obiekt nie jest tworzony na nowo.
Trzecia zmienna $defaultDriverName; jak sama nazwa wskazuje, przechowuje nazwę domyślnego sterownika klasy loggera. Dzięki temu klasa jest gotowa do użycia bez ustawiania sterownika przy każdym, pierwszym, uruchomieniu skryptu.

Metody

Trzech ostatnich metod error(), warn(), info() nie muszę omawiać, zostało to już przedstawione w poprzednich częściach. Jedyną różnicą względem poprzednich implementacji jest dodanie nowego parametru: $driverName =''. Parametr ten, jak nazwa wskazuje, podaje nazwę sterownika, którego należy użyć do zapisu danego komunikatu. Domyślnie nie jest zdefiniowany, a w przypadku jego nie podania, wykorzystywany jest domyślny sterownik. Istnieje jednak możliwość podania innego sterownika do zapisu konkretnego komunikatu. Dzięki temu rozszerzamy funkcjonalność naszej klasy, o wybór sterownika dla konkretnego komunikatu, lub pojedynczego wystąpienia.

Utworzyliśmy dwie metody z dostępem ustawionym na protected:

protected function __construct(){}
protected function __clone(){}

Ich zadaniem jest pilnowanie, aby nasza klasa była rzeczywiście singletonem. Zabezpiecza przed utworzeniem nowego obiektu klasy log z poza niej samej oraz przed utworzeniem kopii takiego obiektu.

Przejdźmy teraz do najważniejszych metod, które są w tym przypadku sednem całego projektu:

public static function instance(){}
public static function addDriver(log_log $driver){}
public static function useDriver($drivername=''){}

Pierwsza statyczna metoda instance() ma za zadanie zwracać instancję obiektu klasy log. Jest to typowa metoda w przypadku wykorzystania singletona.
Druga metoda addDriver(log_log $driver) służy dodaniu nowego sterownika do tablicy sterowników. Dzięki wykorzystaniu interfejsu możemy w tej metodzie ograniczyć sterowniki tylko do tych, które implementują interfejs log_log. Jest to bardzo dobre rozwiązanie, dzięki któremu mamy pewność, że przekazywany do metody sterownik posiada minimum metod wymaganych dla naszej klasy.
Trzecia metoda useDriver($drivername='') ustala aktualny sterownik klasy loggera do wykorzystania. Jeśli sterownik (nazwa) nie zostanie podany, klasa skorzysta z domyślnego.

Wypełnienie klasy

Skoro mamy już gotowy zgrabny schemat klasy możemy przejść do uzupełnienia jej metod ciałami:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php
/**
 * Klasa główna logów
 * @author Vokiel
 * @package log
 */
class log implements log_log{
	/**
	 * Aktualny sterownik cache
	 * @var	object
	 */
	private static $driver;
	/**
	 * Tablica załadowanych sterowników
	 * @var	array
	 */
	private static $drivers = array();
	/**
	 * Domyślny sterownik
	 * @var	string
	 */
	private static $defaultDriverName = 'logFile';
 
	/**
	 * Prywatny konstruktor - wzorzec singleton
	 */
	protected function __construct(){}
	/**
	 * Prywatna metoda __clone - wzorzec singleton
	 */
	protected function __clone(){}
 
	/**
	 * Pobranie instancji klasy log
	 * @return	object
	 */
	public static function instance(){
		if (is_null(self::$driver)){
			if (empty(self::$drivers)){
				self::$drivers[self::$defaultDriverName] = new self::$defaultDriverName();
				self::$driver = self::$drivers[self::$defaultDriverName];
			}else{
				$keys = array_keys(self::$drivers);
				self::$driver = self::$drivers[$keys[0]];
			}
		}
		return self::$driver;
	}
	/**
	 * Dodanie nowego sterownika dla logów
	 * @param	object	logInterface $driver
	 */
	public static function addDriver(log_log $driver){
		self::$drivers[get_class($driver)] = $driver;
		self::$driver=$driver;
	}
	/**
	 * Ustawienie aktywnego sterownika logów
	 * @param	string	$drivername	Nazwa sterownika
	 */
	public static function useDriver($drivername=''){
		if ($drivername && !empty(self::$drivers[$drivername])){
			self::$driver = self::$drivers[$drivername];
		}else{
			self::$driver = self::$drivers[self::$defaultDriverName];
		}
	}
 
	/**
	 * Dodanie błędu do logów
	 * @see log_log#error($err)
	 * @param	string	$err		Treść błedu
	 * @param	strin	$driverName	Nazwa sterownika, który ma przechwycić wiadomość
	 */
	public static function error($err,$driverName=''){
		if ($driverName){
			self::useDriver($driverName);
		}
		self::instance();
		self::$driver->error($err);
	}
	/**
	 * Dodanie ostrzeżenia do logów
	 * @see log_log#warn($err) 
	 * @param	string	$err		Treść ostrzeżenia
	 * @param	strin	$driverName	Nazwa sterownika, który ma przechwycić wiadomość
	 */
	public static function warn($err,$driverName=''){
		if ($driverName){
			self::useDriver($driverName);
		}
		self::instance();
		self::$driver->warn($err);
	}
	/**
	 * Dodanie komunikatu informacyjnego do logów
	 * @see log_log#info($err)
	 * @param	string	$err		Treść informacji
	 * @param	strin	$driverName	Nazwa sterownika, który ma przechwycić wiadomość
	 */
	public static function info($err,$driverName=''){
		if ($driverName){
			self::useDriver($driverName);
		}
		self::instance();
		self::$driver->info($err);
	}
}// end of log class
?>

Niestety w tym przypadku musimy kilka razy powtórzyć te same działania. Jednak dzięki temu, że zrobimy to raz w kodzie nie będziemy musieli powielać tego w momencie korzystania z klasy w trakcie programowania.
Metoda nstance() jest niemalże standardowym użyciem singletona, z tą tylko różnicą, że poza tworzeniem singletona przy okazji ustala domyślny sterownik.
Metoda addDriver(log_log $driver) dodaje nowy sterownik do tablicy sterowników możliwych do wykorzystania. Sterowniki w tablicy przechowywane są pod postacią nazwa_klasy_sterownika:obiekt_sterownika
Kolejna metoda useDriver($drivername='') ustawia zmienną klasy $driver na podany w argumencie sterownik, bądź na domyślny jeśli żaden nie zostanie podany.

Pozostałe trzy, znane już nam metody, działają w bardzo prosty sposób. Jeśli zostanie podana nazwa sterownika, metoda ustawia aktualny sterownik na ten podany. Następnie pobiera instancję klasy i dopisuje do obiektu sterownika komunikat przekazany w pierwszym parametrze. Jeśli natomiast nie zostanie podany sterownik metoda skorzysta z domyślnego.

Zakończenie

Aby dodatkowo nie przedłużać i tak już długiego wpisu, na zakończenie przedstawię już tylko możliwości wykorzystania klasy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
 
/* dołączenie wymaganych klas, wymagane w każdym przykładzie */
require_once 'log/log_log.interface.php';
require_once 'log/logFile.class.php';
require_once 'log/logDb.class.php';
require_once 'log/log.class.php';
 
/* Przykład 1*/
log::info('Wykorzystanie domyślnego sterownika');
log::error('Błąd');
 
/* Przykład 2 */
log::addDriver(new logDb()); // dodanie nowego sterownika
log::info('Info do bazy danych','logDb');
log::info('Info do pliku','logFile');
 
/* Przykład 3 */
log::addDriver(new logDb()); // dodanie nowego sterownika
log::info('Info do bazy danych');
log::useDriver('logFile');
log::info('Info do pliku');
log::warn('Ostrzeżenie do pliku');
log::warn('Ostrzeżenie do bazy','logDb');
?>

 

Przeczytaj także

Komentarze

Brak komentarzy.

Dodaj komentarz

 
(nie będzie publikowany)
 
 
Komentarz
 
 

Dozwolone tagi XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
© 2009 - 2016 Vokiel.com
WordPress Theme by Arcsin modified by Vokiel