PHP hook, building hooks in your application
Introduction
One of the real challenges in building any type of framework, core or application is making it possible for the developers to hook into the business logic at specific points. Since PHP is not event based, nor it works with interrupts you have to come up an alternative. 
The test case
Lets assume we are the main developers of a webshop framework. Programmers can use our framework to build complete webshops. Programmers can manage the orders that are placed on the webshop with the order class. The order class is part of our framework and we don’t want it to be extended by any programmer. However we don’t want to limit to programmers in their possibilities to hook into the orders process. 
For example programmers should be able to send an email to the webshopowner if an order changes from one specific delivery status to another. This functionality is not part of the default behavior in our framework and is custom for the progammers webshop implementation.
Like said before, PHP doesn’t provide interrupts or real events so we need to come up with another way to implement hooks into our application. Lets take a look at the observer pattern.
Implementing the Observer pattern
The observer pattern is a design-pattern that describes a way for objects to be notified to specific state-changes in objects of the application.
For the first implementation we can use SPL. The SPL provides in two simple objects:
SPLSubject
- attach (new observer to attach)
- detach (existing observer to detach)
- notify (notify all observers)
SPLObserver
- update (Called from the subject (i.e. when it’s value has changed).
iOrderRef = $iOrderRef;
		
		// Get order information from the database or an other resources
		$this->iStatus = Order::STATUS_SHIPPED;
	}
	
	/**
	 * Attach an observer
	 * 
	 * @param SplObserver $oObserver 
	 * @return void
	 */
	public function attach(SplObserver $oObserver)
	{
		$sHash = spl_object_hash($oObserver);
		if (isset($this->aObservers[$sHash])) {
			throw new Exception('Observer is already attached');
		}
		$this->aObservers[$sHash] = $oObserver;
	}
	/**
	 * Detach observer
	 * 
	 * @param SplObserver $oObserver 
	 * @return void
	 */
	public function detach(SplObserver $oObserver)
	{
		$sHash = spl_object_hash($oObserver);
		if (!isset($this->aObservers[$sHash])) {
			throw new Exception('Observer not attached');
		}
		unset($this->aObservers[$sHash]);
	}
	/**
	 * Notify the attached observers
	 * 
	 * @param string $sEvent, name of the event
	 * @param mixed $mData, optional data that is not directly available for the observers
	 * @return void
	 */
	public function notify()
	{
		foreach ($this->aObservers as $oObserver) {
			try {
				$oObserver->update($this);
			} catch(Exception $e) {
			}
		}
	}
	/**
	 * Add an order
	 * 
	 * @param array $aOrder 
	 * @return void
	 */
	public function delete()
	{
		$this->notify();
	}
	
	/**
	 * Return the order reference number
	 * 
	 * @return int
	 */
	public function getRef()
	{
		return $this->iOrderRef;
	}
	
	/**
	 * Return the current order status
	 * 
	 * @return int
	 */
	public function getStatus()
	{
		return $this->iStatus;
	}
	
	/**
	 * Update the order status
	 */
	public function updateStatus($iStatus)
	{
		$this->notify();
		// ...
		$this->iStatus = $iStatus;
		// ...
		$this->notify();
	}
}
/**
 * Order status handler, observer that sends an email to secretary
 * if the status of an order changes from shipped to delivered, so the
 * secratary can make a phone call to our customer to ask for his opinion about the service
 * 
 * @package Shop
 */
class OrderStatusHandler implements SplObserver
{
	/**
	 * Previous orderstatus
	 * @var int
	 */
	protected $iPreviousOrderStatus;
	/**
	 * Current orderstatus
	 * @var int
	 */
	protected $iCurrentOrderStatus;
	
	/**
	 * Update, called by the observable object order
	 * 
	 * @param Observable_Interface $oSubject
	 * @param string $sEvent
	 * @param mixed $mData 
	 * @return void
	 */
	public function update(SplSubject $oSubject)
	{
		if(!$oSubject instanceof Order) {
			return;
		}
		if(is_null($this->iPreviousOrderStatus)) {
			$this->iPreviousOrderStatus = $oSubject->getStatus();
		} else {
			$this->iCurrentOrderStatus = $oSubject->getStatus();
			if($this->iPreviousOrderStatus === Order::STATUS_SHIPPED && $this->iCurrentOrderStatus === Order::STATUS_DELIVERED) {
				$sSubject = sprintf('Order number %d is shipped', $oSubject->getRef());
				//mail('secratary@example.com', 'Order number %d is shipped', 'Text');
				echo 'Mail sended to the secratary to help her remember to call our customer for a survey.';
			}
		}
	}
}
$oOrder = new Order(26012011);
$oOrder->attach(new OrderStatusHandler());
$oOrder->updateStatus(Order::STATUS_DELIVERED);
$oOrder->delete();
?>
There are several problems with the implementation above. To most important disadvantage is that we have only one update method in our observer. In this update method we don’t know when and why we are getting notified, just that something happened. We should keep track of everything that happens in the subject. (Or use debug_backtrace… just joking, don’t even think about using it that way ever!).
Taking it a step further, events
Lets take a look at the next example, we will extend the Observer implementation with some an additional parameter for the eventname that occured.
Finishing up, optional data
iOrderRef = $iOrderRef;
		
		// Get order information from the database or something else...
		$this->iStatus = Order::STATUS_SHIPPED;
	}
	
	/**
	 * Attach an observer
	 * 
	 * @param Observer_Interface $oObserver 
	 * @return void
	 */
	public function attachObserver(Observer_Interface $oObserver)
	{
		$sHash = spl_object_hash($oObserver);
		if (isset($this->aObservers[$sHash])) {
			throw new Exception('Observer is already attached');
		}
		$this->aObservers[$sHash] = $oObserver;
	}
	/**
	 * Detach observer
	 * 
	 * @param Observer_Interface $oObserver 
	 * @return void
	 */
	public function detachObserver(Observer_Interface $oObserver)
	{
		$sHash = spl_object_hash($oObserver);
		if (!isset($this->aObservers[$sHash])) {
			throw new Exception('Observer not attached');
		}
		unset($this->aObservers[$sHash]);
	}
	/**
	 * Notify the attached observers
	 * 
	 * @param string $sEvent, name of the event
	 * @param mixed $mData, optional data that is not directly available for the observers
	 * @return void
	 */
	public function notifyObserver($sEvent, $mData=null)
	{
		foreach ($this->aObservers as $oObserver) {
			try {
				$oObserver->update($this, $sEvent, $mData);
			} catch(Exception $e) {
			}
		}
	}
	/**
	 * Add an order
	 * 
	 * @param array $aOrder 
	 * @return void
	 */
	public function add($aOrder = array())
	{
		$this->notifyObserver('onAdd');
	}
	
	/**
	 * Return the order reference number
	 * 
	 * @return int
	 */
	public function getRef()
	{
		return $this->iOrderRef;
	}
	
	/**
	 * Return the current order status
	 * 
	 * @return int
	 */
	public function getStatus()
	{
		return $this->iStatus;
	}
	
	/**
	 * Update the order status
	 */
	public function updateStatus($iStatus)
	{
		$this->notifyObserver('onBeforeUpdateStatus');
		// ...
		$this->iStatus = $iStatus;
		// ...
		$this->notifyObserver('onAfterUpdateStatus');
	}
}
/**
 * Order status handler, observer that sends an email to secretary
 * if the status of an order changes from shipped to delivered, so the
 * secratary can make a phone call to our customer to ask for his opinion about the service
 * 
 * @package Shop
 */
class OrderStatusHandler implements Observer_Interface
{
	protected $iPreviousOrderStatus;
	protected $iCurrentOrderStatus;
	
	/**
	 * Update, called by the observable object order
	 * 
	 * @param Observable_Interface $oObservable
	 * @param string $sEvent
	 * @param mixed $mData 
	 * @return void
	 */
	public function update(Observable_Interface $oObservable, $sEvent, $mData=null)
	{
		if(!$oObservable instanceof Order) {
			return;
		}
		
		switch($sEvent) {
			case 'onBeforeUpdateStatus':
				$this->iPreviousOrderStatus = $oObservable->getStatus();
				return;
			case 'onAfterUpdateStatus':
				$this->iCurrentOrderStatus = $oObservable->getStatus();
				
				if($this->iPreviousOrderStatus === Order::STATUS_SHIPPED && $this->iCurrentOrderStatus === Order::STATUS_DELIVERED) {
					$sSubject = sprintf('Order number %d is shipped', $oObservable->getRef());
					//mail('secratary@example.com', 'Order number %d is shipped', 'Text');
					echo 'Mail sended to the secratary to help her remember to call our customer for a survey.';
				}
		}
	}
}
$oOrder = new Order(26012011);
$oOrder->attachObserver(new OrderStatusHandler());
$oOrder->updateStatus(Order::STATUS_DELIVERED);
$oOrder->add();
?>
Now we are able to take action on different events that occur.
Disadvantages
Although this implementation works quite well there are some drawbacks. One of those drawbacks is that we need to dispatch an event in our framework, if we don’t programmers can’t hook into our application. Triggering events everywhere give us a small performance penalty however I do think this way of working gives the programmers a nice way to hook into your application on those spots that you want them to hook in.
Just for the record
Notice that this code is just an example and can still use some improvements, for example: each observer is initialized even it will maybe never be notified, therefore I suggest to make use of lazy in some cases for loading the objects. There are other systems to hook into an application, more to follow!
обучение продвижению сайтов [url=https://kursy-seo-12.ru]обучение продвижению сайтов[/url] .
kyrsi seo_ypor
30 Oct 25 at 10:18 pm
Главное за сегодня тут: https://baikalinform.ru/pestraya-zhiznb/izgotovlenie-etiketok-spetsialisty-rasskazali-pro-vidy-materialov-tehnologii-pechati-i-sootvetstvie-standartam
StevenGathe
30 Oct 25 at 10:19 pm
diskrete Lieferung per DHL: diskrete Lieferung per DHL – Potenzmittel ohne ärztliches Rezept
RichardImmon
30 Oct 25 at 10:20 pm
рулонные шторки на окна [url=rulonnye-shtory-s-elektroprivodom7.ru]рулонные шторки на окна[/url] .
rylonnie shtori s elektroprivodom_wbMl
30 Oct 25 at 10:20 pm
купить диплом зарегистрированный в реестре [url=http://frei-diplom2.ru]http://frei-diplom2.ru[/url] .
Diplomi_dqEa
30 Oct 25 at 10:20 pm
«ПрофДетокс» — выездная наркологическая служба для жителей Ивантеевки и ближайших районов. Мы запускаем помощь без очередей и лишней огласки: врач приезжает анонимно, проводит очную оценку, допускает к терапии и запускает инфузионную поддержку без универсальных коктейлей. Наша задача — снять интоксикацию и абстиненцию, стабилизировать давление и пульс, снизить тревогу, мягко наладить сон по показаниям и дать семье понятный план на ближайшие двое суток. Если дома нет условий для безопасной ночи, предложим палату «ПрофДетокса» с круглосуточным наблюдением. Приватность встроена в процесс, а смета фиксируется до начала процедур.
Узнать больше – [url=https://narkolog-na-dom-ivanteevka8.ru/]нарколог на дом вывод[/url]
JerryPeect
30 Oct 25 at 10:20 pm
Плесень ушла после обработка от тараканов стоимость, спасибо!
уничтожение тараканов в кафе
Wernermog
30 Oct 25 at 10:20 pm
Клопы вернулись после дезинфекция медицинских учреждений, что делать?
уничтожение тараканов в кафе
KennethceM
30 Oct 25 at 10:20 pm
kraken vk3
kraken vk5
JamesDaync
30 Oct 25 at 10:22 pm
как купить диплом техникума отзывы [url=frei-diplom9.ru]как купить диплом техникума отзывы[/url] .
Diplomi_ezea
30 Oct 25 at 10:23 pm
Ресторан чистый после дезинсекция предприятий.
дезинфекция медицинских учреждений
KennethceM
30 Oct 25 at 10:24 pm
школа seo [url=https://kursy-seo-12.ru]https://kursy-seo-12.ru[/url] .
kyrsi seo_nsor
30 Oct 25 at 10:24 pm
successpathway.bond – The branding is clean, yet more content and trust elements should be added.
Louise Fittje
30 Oct 25 at 10:25 pm
диплом с занесением в реестр купить [url=frei-diplom2.ru]диплом с занесением в реестр купить[/url] .
Diplomi_pkEa
30 Oct 25 at 10:26 pm
Great goods from you, man. I’ve take into accout your stuff previous to and you are simply too great.
I really like what you have received here, really like what you’re saying and the best way during which you are saying it.
You make it enjoyable and you still take care of to stay it wise.
I can not wait to read much more from you. That is really
a great website.
خریدار میز و صندلی اداری دست دوم
30 Oct 25 at 10:27 pm
купить диплом автотранспортного техникума [url=frei-diplom8.ru]купить диплом автотранспортного техникума[/url] .
Diplomi_rwsr
30 Oct 25 at 10:28 pm
VitaHomme: Kamagra livraison rapide en France – Kamagra pas cher France
RichardImmon
30 Oct 25 at 10:29 pm
купить диплом техникума об окончании [url=educ-ua7.ru]educ-ua7.ru[/url] .
Diplomi_cfea
30 Oct 25 at 10:30 pm
электрокарниз двухрядный [url=http://elektrokarniz499.ru/]http://elektrokarniz499.ru/[/url] .
elektrokarniz_taKl
30 Oct 25 at 10:31 pm
купить диплом в воткинске [url=https://rudik-diplom2.ru/]купить диплом в воткинске[/url] .
Diplomi_cvpi
30 Oct 25 at 10:31 pm
купить диплом зубного техника [url=https://rudik-diplom10.ru]купить диплом зубного техника[/url] .
Diplomi_gvSa
30 Oct 25 at 10:31 pm
постоянный виртуальный номер для смс
постоянный виртуальный номер для смс
30 Oct 25 at 10:31 pm
купить диплом с занесением в реестр пенза [url=https://www.frei-diplom2.ru]купить диплом с занесением в реестр пенза[/url] .
Diplomi_wwEa
30 Oct 25 at 10:33 pm
Платформа была запущена чуть более
четырех лет назад в 2017 году и быстро начала собирать подписчиков по всему миру.
https://www.carrieconnects.com/forum/money-saving-forum/what-is-football-betting-knowledge-recommended-about-football-betting
30 Oct 25 at 10:35 pm
купить проведенный диплом красноярск [url=https://frei-diplom4.ru/]купить проведенный диплом красноярск[/url] .
Diplomi_waOl
30 Oct 25 at 10:36 pm
электрические гардины [url=https://elektrokarniz797.ru/]электрические гардины[/url] .
elektrokarniz_ceEi
30 Oct 25 at 10:36 pm
обучение продвижению сайтов [url=www.kursy-seo-12.ru/]обучение продвижению сайтов[/url] .
kyrsi seo_svor
30 Oct 25 at 10:36 pm
курс seo [url=https://www.kursy-seo-12.ru]https://www.kursy-seo-12.ru[/url] .
kyrsi seo_meor
30 Oct 25 at 10:38 pm
ишимбайский нефтяной колледж купить диплом [url=https://frei-diplom8.ru]https://frei-diplom8.ru[/url] .
Diplomi_igsr
30 Oct 25 at 10:38 pm
ясміна церковне ім’я
Michaelmaync
30 Oct 25 at 10:39 pm
https://vintfint.com/blogs/104348/Melbet-Bonus-Code-2026-RICH888-130-Deal
Arthurnor
30 Oct 25 at 10:39 pm
Технологии делают жизнь проще kraken актуальные ссылки kraken онион kraken онион тор кракен онион
RichardPep
30 Oct 25 at 10:40 pm
автоматические карнизы для штор [url=https://elektrokarniz499.ru]автоматические карнизы для штор[/url] .
elektrokarniz_pwKl
30 Oct 25 at 10:41 pm
купить диплом в нижним тагиле [url=https://rudik-diplom1.ru]купить диплом в нижним тагиле[/url] .
Diplomi_wqer
30 Oct 25 at 10:43 pm
seo с нуля [url=http://kursy-seo-12.ru]http://kursy-seo-12.ru[/url] .
kyrsi seo_ouor
30 Oct 25 at 10:44 pm
купить диплом инженера электрика [url=http://rudik-diplom10.ru]купить диплом инженера электрика[/url] .
Diplomi_yzSa
30 Oct 25 at 10:44 pm
купить диплом в сарове [url=rudik-diplom11.ru]купить диплом в сарове[/url] .
Diplomi_qyMi
30 Oct 25 at 10:45 pm
купить диплом о высшем образовании с занесением в реестр цена [url=http://www.frei-diplom2.ru]купить диплом о высшем образовании с занесением в реестр цена[/url] .
Diplomi_geEa
30 Oct 25 at 10:46 pm
chery 8 max chery arrizo 8
chery-503
30 Oct 25 at 10:47 pm
курсы по seo [url=https://www.kursy-seo-12.ru]курсы по seo[/url] .
kyrsi seo_inor
30 Oct 25 at 10:47 pm
купить диплом проведенный москва [url=http://frei-diplom4.ru]http://frei-diplom4.ru[/url] .
Diplomi_rkOl
30 Oct 25 at 10:48 pm
Обработка дезинфекция цена частного дома.
обработка квартиры от клопов
KennethceM
30 Oct 25 at 10:50 pm
электропривод рулонных штор [url=https://rulonnye-shtory-s-elektroprivodom7.ru/]rulonnye-shtory-s-elektroprivodom7.ru[/url] .
rylonnie shtori s elektroprivodom_cuMl
30 Oct 25 at 10:51 pm
kraken vk6
kraken СПб
JamesDaync
30 Oct 25 at 10:51 pm
купить диплом в новокузнецке [url=https://rudik-diplom3.ru]купить диплом в новокузнецке[/url] .
Diplomi_yaei
30 Oct 25 at 10:51 pm
kamagra oral jelly: Vita Homme – acheter Kamagra en ligne
RobertJuike
30 Oct 25 at 10:51 pm
Kamagra online kaufen: Kamagra Oral Jelly Deutschland – vital pharma 24
RichardImmon
30 Oct 25 at 10:53 pm
Профессиональная дезинфекция офисов обязательна.
санитарная обработка
KennethceM
30 Oct 25 at 10:53 pm
Tarz?n?z? 90’lar?n unutulmaz modas?ndan esinlenerek gunumuze tas?mak ister misiniz? Oyleyse bu yaz?m?z tam size gore!
Хочу выделить материал про Ev Dekorasyonunda S?kl?k ve Fonksiyonellik.
Вот, можете почитать:
[url=https://evimsicak.com]https://evimsicak.com[/url]
90’lar?n guzellik s?rlar?yla tarz?n?za yeni bir soluk kazand?rabilirsiniz. Eski moda, yeni size ilham olsun!
Josephassof
30 Oct 25 at 10:53 pm
рулонные шторы в москве [url=https://rulonnye-shtory-s-elektroprivodom7.ru]рулонные шторы в москве[/url] .
rylonnie shtori s elektroprivodom_pvMl
30 Oct 25 at 10:53 pm