Zdarzenia w CodeIgniterze

Czym są zdarzenia? Zdarzenia pozwalają na wykonanie określonych czynności, w określonym momencie działania naszej aplikacji, bez konieczności modyfikowania zasadniczej części naszego kodu (kontrolera, biblioteki). Dzięki temu możemy pisać aplikacje, których funkcjonalność w bardzo prosty sposób możemy rozszerzyć.

Teoretycznie CodeIgniter posiada wbudowany system zdarzeń – mowa o Hookach. Niestety nie jest to idealne rozwiązanie. W zasadzie nie przypominam sobie, abym kiedykolwiek skorzystał z Hooków m.in. dlatego, że jest to rozwiązanie mało elastyczne. Z zaobserwowaniem użycia Hooków, miałem również problem w przypadku aplikacji pisanych przez inne osoby. Kiedy już pojawia się sposobność, aby z nich skorzystać, zazwyczaj o wiele wygodniejszym rozwiązaniem okazuje się np. rozszerzenie klasy kontrolera. No ale dosyć o Hookach – przejdźmy do biblioteki Events, której autorami są Eric Barnes i Dan Horrigan.

Jak wspomniałem we wstępie, biblioteka Events pozwala na wykonywanie określonych czynności, w konkretnych momentach działania naszej aplikacji. Aby przedstawić działanie tej biblioteki, posłużę się małym przykładem, który mam nadzieję, dobrze zobrazuje jej działanie.

Na początek musimy dokonać jeszcze pewnych ustaleń. Biblioteka odpowiedzialna za wykonywanie naszych zdarzeń będzie przechowywana w katalogu events w folderze third_party. Oczywiście nic nie stoi na przeszkodzie, aby zorganizować to inaczej, chociaż przedstawiony sposób wydaje się być rozsądnym rozwiązaniem. Natomiast w kodzie, który normalnie piszemy, będą musiały się pojawić odwołania do pewnych zdarzeń, które zdefiniujemy niezależnie od tego, czy będziemy ich używać, czy nie. Chodzi o to, abyśmy mieli możliwie duże pole działania (oczywiście w przypadku pisania własnej aplikacji, trzeba tutaj zachować zdrowy rozsądek).

Załóżmy więc, że mamy kontroler Users, który w metodzie login zwraca dane użytkownika. Normalnie zaangażowalibyśmy w to bazę danych, sesje, formularze itd., ale z racji tego, że to tylko przykład będziemy przypisywać dane na „sztywno”.

class Users extends CI_Controller {

	public function __construct()
	{
		parent::__construct();
		// Ładujemy biblioteke Events
		$this->load->library('events');
		// Ładujemy pakiet events
		$this->load->add_package_path(APPPATH.'third_party/events/');
		// Ładujemy bibliotekę z załadowanego przed chwilą pakietu, ze zdarzeniami dla klasy Users
		$this->load->library('events_users');
	}

	public function login()
	{
		// Wywołujemy zdarzenie, przed zalogowaniem użytkownika (które nie zostało zarejestrowane)
		Events::trigger('pre_user_login');

		$data = array(
			'first_name' => 'Jan',
			'last_name' => 'Kowalski'
		);

		// Możemy sprawdzić, czy zdarzenie 'pre_user_login' nie jest zarejestrowane
		if ( ! Events::has_listeners('pre_user_login'))
		{
			echo 'Zdarzenie "pre_user_login" nie zostalo zarejestrowane.';
		}

		// Wywołujemy zdarzenie, po zalogowaniu użytkownika
		var_dump(Events::trigger('post_user_login', $data));
	}
}
/* End of file users.php */
/* Location: ./application/contollers/users.php */

Teraz pora na naszą bibliotekę Events_Users, w której rejestrujemy nasze zdarzenia i która przechowuje metody, z których będziemy korzystać.

class Events_Users {

	public function __construct()
	{
		// Rejestrujemy zdarzenie w momencie załadowania biblioteki Events_Users,
		// w ten sposób zdarzenie jest widoczne i gotowe do wywołania za pośrednictwem metody Event::trigger.
		Events::register('post_user_login', array($this, 'metoda_do_wywolania'));
	}

	public function metoda_do_wywolania($data)
	{
		return 'Zostales zalogowany jako: '.$data['first_name'].' '.$data['last_name'];
	}

}
/* End of file events_users.php */
/* Location: ./application/third_party/events/libraries/events_users.php */

Po przejściu w przeglądarce na adres podobny do tego: http://localhost/nazwa_projektu/index.php/users/login powinniśmy zobaczyć wyniki działania metody login i zaimplementowanych zdarzeń.

To bardzo prosty przykład. Jednak prawdziwa siła tego rozwiązania pojawia się w momencie, gdy dysponujemy rozbudowaną aplikacją. Zyskujemy wtedy możliwość „wpięcia się” w istniejącą aplikację, bez konieczności niepotrzebnego komplikowania istniejącego kodu. Innymi słowy główny kod naszej aplikacji pozostaje nietknięty, my natomiast możemy modyfikować kluczowe zachowania naszej aplikacji.

Jeśli masz wątpliwości w jaki sposób lub w jakich momentach mógłbyś użyć zdarzeń w swojej aplikacji, to możesz spojrzeć na kod źródłowy biblioteki Ion_Auth, która również ma zaimplementowany system zdarzeń. Co prawda nie korzysta ona z biblioteki, którą przedstawiłem powyżej, tylko z własnego rozwiązania, ale wszystko działa na tych samych zasadach i może służyć jako dobry przykład wykorzystania zdarzeń.

7 komentarzy do wpisu „Zdarzenia w CodeIgniterze”

  1. Eventy świetnie sprawdzają się przy operacjach typu CRUD, szczególnie jeśli implementujesz typy zawartości( np. w drupalu je masz)

    „Teraz pora na naszą bibliotekę Users_Events”

    Powinno być Events_Users.

    pzdr

  2. Fajne, tylko na pierwszy rzut oka zabieramy co nieco miejsca modelom dodając jakby nową warstwę. Ale sama koncepcja wygląda na pomocną. Gdyby dało się polączyć klasę Events_Users z tą z modelem powiązanym z kontrolerem byłoby ok.

    • Nie rozpatrywałbym tego w kwestii zastępowania czegokolwiek, to po prostu kolejna opcja, która daje nam nowe możliwości. Tylko od Ciebie zależy w jaki sposób wykorzystasz zdarzenia – możesz w nich przecież odwoływać się bez problemu do modelu lub biblioteki.

      • A no chyba, że tak. W przykładzie jest odwołanie do metody w klasie Eventów co mi się zbytnio nie podoba.

        • Zawsze odwołujemy się do jakiejś metody z klasy „Events”, ale jakie czynności w niej wykonamy, to już nasza sprawa.

Dodaj komentarz

This site uses Akismet to reduce spam. Learn how your comment data is processed.