Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Kohana] Klasa Event's
Forum PHP.pl > Forum > PHP > Frameworki
by_ikar
Ostatnim czasy trochę analizuje kod frameworka kohana, przy okazji ucząc się oop, generalnie ucząc się do czego można go wykorzystać. Kilka rzeczy rozumiem, ale jest sporo których nie rozumiem. Jedną z tych rzeczy jest klasa Event, która z tego co rozumiem, "uruchamia" metody klas. Przykładowo w pliku bootstrap.php znajduje się coś takiego:
  1. Event::run('system.shutdown');

Natomiast w pliku kohana.php (główny plik, "rdzenie" enignu) znajduje się taki kod:
  1. Event::add('system.shutdown', array('Kohana', 'shutdown'));

drugi parametr, który jest tablicą, kohana - nazwa "głównej klasy, shutdown - nazwa metody.

Teraz moje pytanie, jakie płyną korzyści z zastosowania klasy event, oraz czy dobrze rozumuje, że na takiej zasadzie na jakiej to opisałem, działa?
Strona dokumentacji: http://docs.kohanaphp.com/core/event mówi mi tylko tyle jak tego używać, ale jakie jest założenie używania tego, nie bardzo mi to uświadamia. Jeżeli znalazłby się ktoś kto mógłby mi to w skrócie opisać, nawet łopatologicznie - po wała korzystać z klasy event, to byłbym bardzo wdzięczny smile.gif

PS nie krzyczcie na mnie że głupi jestem - ja to wiem smile.gif więc fajnie będzie jak ktoś pomoże mi przestać być głupim. Poniżej również załączam klasę event, dla nie siedzących w temacie, lub leniwych ;P

Pozdrawiam, filip.

  1. <?php defined('SYSPATH') OR die('No direct access allowed.');
  2. /**
  3.  * Process queuing/execution class. Allows an unlimited number of callbacks
  4.  * to be added to 'events'. Events can be run multiple times, and can also
  5.  * process event-specific data. By default, Kohana has several system events.
  6.  *
  7.  * $Id: Event.php 4390 2009-06-04 03:05:36Z zombor $
  8.  *
  9.  * @package Core
  10.  * @author Kohana Team
  11.  * @copyright (c) 2007 Kohana Team
  12.  * @license <a href="http://kohanaphp.com/license.html" target="_blank">http://kohanaphp.com/license.html</a>
  13.  * @link <a href="http://docs.kohanaphp.com/general/events" target="_blank">http://docs.kohanaphp.com/general/events</a>
  14.  */
  15. final class Event {
  16.  
  17. // Event callbacks
  18. private static $events = array();
  19.  
  20. // Cache of events that have been run
  21. private static $has_run = array();
  22.  
  23. // Data that can be processed during events
  24. public static $data;
  25.  
  26. /**
  27. * Add a callback to an event queue.
  28. *
  29. * @param string event name
  30. * @param array <a href="http://php.net/callback" target="_blank">http://php.net/callback</a>
  31. * @return boolean
  32. */
  33. public static function add($name, $callback)
  34. {
  35. if ( ! isset(self::$events[$name]))
  36. {
  37. // Create an empty event if it is not yet defined
  38. self::$events[$name] = array();
  39. }
  40. elseif (in_array($callback, self::$events[$name], TRUE))
  41. {
  42. // The event already exists
  43. return FALSE;
  44. }
  45.  
  46. // Add the event
  47. self::$events[$name][] = $callback;
  48.  
  49. return TRUE;
  50. }
  51.  
  52. /**
  53. * Add a callback to an event queue, before a given event.
  54. *
  55. * @param string event name
  56. * @param array existing event callback
  57. * @param array event callback
  58. * @return boolean
  59. */
  60. public static function add_before($name, $existing, $callback)
  61. {
  62. if (empty(self::$events[$name]) OR ($key = array_search($existing, self::$events[$name])) === FALSE)
  63. {
  64. // Just add the event if there are no events
  65. return self::add($name, $callback);
  66. }
  67. else
  68. {
  69. // Insert the event immediately before the existing event
  70. return self::insert_event($name, $key, $callback);
  71. }
  72. }
  73.  
  74. /**
  75. * Add a callback to an event queue, after a given event.
  76. *
  77. * @param string event name
  78. * @param array existing event callback
  79. * @param array event callback
  80. * @return boolean
  81. */
  82. public static function add_after($name, $existing, $callback)
  83. {
  84. if (empty(self::$events[$name]) OR ($key = array_search($existing, self::$events[$name])) === FALSE)
  85. {
  86. // Just add the event if there are no events
  87. return self::add($name, $callback);
  88. }
  89. else
  90. {
  91. // Insert the event immediately after the existing event
  92. return self::insert_event($name, $key + 1, $callback);
  93. }
  94. }
  95.  
  96. /**
  97. * Inserts a new event at a specfic key location.
  98. *
  99. * @param string event name
  100. * @param integer key to insert new event at
  101. * @param array event callback
  102. * @return void
  103. */
  104. private static function insert_event($name, $key, $callback)
  105. {
  106. if (in_array($callback, self::$events[$name], TRUE))
  107. return FALSE;
  108.  
  109. // Add the new event at the given key location
  110. self::$events[$name] = array_merge
  111. (
  112. // Events before the key
  113. array_slice(self::$events[$name], 0, $key),
  114. // New event callback
  115. array($callback),
  116. // Events after the key
  117. array_slice(self::$events[$name], $key)
  118. );
  119.  
  120. return TRUE;
  121. }
  122.  
  123. /**
  124. * Replaces an event with another event.
  125. *
  126. * @param string event name
  127. * @param array event to replace
  128. * @param array new callback
  129. * @return boolean
  130. */
  131. public static function replace($name, $existing, $callback)
  132. {
  133. if (empty(self::$events[$name]) OR ($key = array_search($existing, self::$events[$name], TRUE)) === FALSE)
  134. return FALSE;
  135.  
  136. if ( ! in_array($callback, self::$events[$name], TRUE))
  137. {
  138. // Replace the exisiting event with the new event
  139. self::$events[$name][$key] = $callback;
  140. }
  141. else
  142. {
  143. // Remove the existing event from the queue
  144. unset(self::$events[$name][$key]);
  145.  
  146. // Reset the array so the keys are ordered properly
  147. self::$events[$name] = array_values(self::$events[$name]);
  148. }
  149.  
  150. return TRUE;
  151. }
  152.  
  153. /**
  154. * Get all callbacks for an event.
  155. *
  156. * @param string event name
  157. * @return array
  158. */
  159. public static function get($name)
  160. {
  161. return empty(self::$events[$name]) ? array() : self::$events[$name];
  162. }
  163.  
  164. /**
  165. * Clear some or all callbacks from an event.
  166. *
  167. * @param string event name
  168. * @param array specific callback to remove, FALSE for all callbacks
  169. * @return void
  170. */
  171. public static function clear($name, $callback = FALSE)
  172. {
  173. if ($callback === FALSE)
  174. {
  175. self::$events[$name] = array();
  176. }
  177. elseif (isset(self::$events[$name]))
  178. {
  179. // Loop through each of the event callbacks and compare it to the
  180. // callback requested for removal. The callback is removed if it
  181. // matches.
  182. foreach (self::$events[$name] as $i => $event_callback)
  183. {
  184. if ($callback === $event_callback)
  185. {
  186. unset(self::$events[$name][$i]);
  187. }
  188. }
  189. }
  190. }
  191.  
  192. /**
  193. * Execute all of the callbacks attached to an event.
  194. *
  195. * @param string event name
  196. * @param array data can be processed as Event::$data by the callbacks
  197. * @return void
  198. */
  199. public static function run($name, & $data = NULL)
  200. {
  201. if ( ! empty(self::$events[$name]))
  202. {
  203. // So callbacks can access Event::$data
  204. self::$data =& $data;
  205. $callbacks = self::get($name);
  206.  
  207. foreach ($callbacks as $callback)
  208. {
  209. call_user_func($callback);
  210. }
  211.  
  212. // Do this to prevent data from getting 'stuck'
  213. $clear_data = '';
  214. self::$data =& $clear_data;
  215. }
  216.  
  217. // The event has been run!
  218. self::$has_run[$name] = $name;
  219. }
  220.  
  221. /**
  222. * Check if a given event has been run.
  223. *
  224. * @param string event name
  225. * @return boolean
  226. */
  227. public static function has_run($name)
  228. {
  229. return isset(self::$has_run[$name]);
  230. }
  231.  
  232. } // End Event
phpion
Najlepiej będzie Ci to chyba zrozumieć na przykładzie zdarzenia system.404. Zdarzenie to uruchamiasz w ten sposób:
  1. Event::run('system.404');

Wyświetla ono widok braku strony. Teraz np. w kontrolerze pobierasz dane na podstawie ID. Jeżeli dane zostały znalezione to spoko, wyświetlasz je w widoku. Jeśli nie (np. gdy ktoś ręcznie podmienił ID w adresie) to możesz wyświetlić widok braku strony uruchamiając właśnie wspomniany event.

W skrócie: są to jakby zdefiniowane zdarzenia, które mogą zajść w systemie. Mechanizm eventów jest tak naprawdę bardzo przydatny, nie tylko w celu uproszczenia kodu (mógłbyś przecież ręcznie podstawić widok braku strony). Ja np. zaraz po przejściu routingu uruchamiam event, który sprawdza, czy użytkownik ma prawa do danej strony:
  1. Event::add('system.routing', array('ACL_Hook', 'check'));

Przed tym jednak sprawdzam, czy użytkownik jest zalogowany:
  1. Event::add_before('system.routing', array('ACL_Hook', 'check'), array('Auth_Hook', 'check'));

czyli dodaję nowy event przed sprawdzeniem uprawnień. Oto kod tej metody:
  1. /**
  2.  * Sprawdza czy akcja wymaga uwierzytelnienia oraz czy użytkownik jest uwierzytelniony.
  3.  *
  4.  * Jeżeli akcja wymaga uwierzytelnienia, a użytkownik nie jest uwierzytelniony
  5.  * uruchamia event o konieczności zalogowania.
  6.  */
  7. public function check() {
  8. Kohana::log('info', 'Auth_Hook::check() run');
  9.  
  10. if (Structure::instance()->is_authentication_required() && !Auth::instance()->is_user_authenticated()) {
  11. Event::run('system.401');
  12. }
  13. }

I tu znowu pojawia się event. Jeśli strona wymaga uwierzytelnienia, a użytkownik nie jest zalogowany to wyświetlam mu stronę z formularzem logowania, czyli uruchamiam mój event system.401.
by_ikar
Odpowiedź szybka prawie jak w komunikatorze biggrin.gif dziękować panowie. Tak jak mniej więcej myślałem. Tyle że nie sądziłem, że można zrobić to nawet tak:
  1. Event::add_before('system.routing', array('ACL_Hook', 'check'), array('Auth_Hook', 'check'));

Bo w ten sposób to znacznie poszerza zastosowanie event'a. Teraz dostrzegam wiele miejsc w których można skrócić event'em wiele kodu biggrin.gif

Dzięki jeszcze raz za wytłumaczenie smile.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.