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://avto-iz-korei-1.ru]авто из кореи под ключ цены[/url] .
Avto iz Korei_noPi
31 Jul 25 at 8:03 am
nova comics free comic reader PC
batcave-753
31 Jul 25 at 8:03 am
Запой — это не просто бытовое пьянство, а одно из наиболее опасных проявлений алкогольной зависимости. Во время запоя организм перестаёт функционировать в нормальном режиме: сердечно-сосудистая система работает на износ, нервная система перегружена токсинами, а печень не справляется с нагрузкой. На этом фоне могут возникать тяжёлые осложнения — от судорог и гипогликемии до нарушения дыхания и алкогольного психоза. Чем дольше длится запой, тем глубже метаболические нарушения и выше риск серьёзных последствий.
Детальнее – https://vyvod-iz-zapoya-kolomna3.ru/vyvod-iz-zapoya-nedorogo-v-kolomne
BruceNut
31 Jul 25 at 8:06 am
For latest information you have to pay a visit the web and on internet I found this site as
a best web page for most up-to-date updates.
keo nha cai
31 Jul 25 at 8:08 am
manga reader no ads online manga site best
manga-11
31 Jul 25 at 8:10 am
Pretty great post. I just stumbled upon your weblog and wanted to mention that
I’ve truly loved browsing your blog posts.
After all I’ll be subscribing for your feed and I’m hoping you write once more soon!
رشته حسابداری بدون کنکور
31 Jul 25 at 8:10 am
прогнозы на футбол на сегодня [url=www.prognozy-na-futbol-2.ru]www.prognozy-na-futbol-2.ru[/url] .
prognozi na fytbol_ijmi
31 Jul 25 at 8:11 am
What i don’t realize is actually how you are now not
really much more smartly-favored than you may be now.
You’re very intelligent. You understand thus significantly relating to this
matter, produced me in my opinion imagine it from a
lot of numerous angles. Its like women and men are not interested until
it is one thing to do with Woman gaga! Your own stuffs outstanding.
Always care for it up!
my page :: monthly internet Hungary
monthly internet Hungary
31 Jul 25 at 8:11 am
Мега онион
RichardPep
31 Jul 25 at 8:13 am
мелбет скачать [url=https://melbet1033.ru]https://melbet1033.ru[/url]
melbet_cfPn
31 Jul 25 at 8:15 am
best mexican pharmacy online [url=https://mexicarerxhub.shop/#]buy propecia mexico[/url] MexiCare Rx Hub
JamesCoaby
31 Jul 25 at 8:17 am
Публикация приглашает вас исследовать неизведанное — от древних тайн до современных достижений науки. Вы узнаете, как случайные находки превращались в революции, а смелые мысли — в новые эры человеческого прогресса.
Детальнее – https://astirholidays.com/product/thailand-tour-package
Jasondus
31 Jul 25 at 8:18 am
В этом обзорном материале представлены увлекательные детали, которые находят отражение в различных аспектах жизни. Мы исследуем непонятные и интересные моменты, позволяя читателю увидеть картину целиком. Погрузитесь в мир знаний и удивительных открытий!
Не упусти важное! – https://movietheme.dubdesign.net/demo1/nintendo/11
Melvinalask
31 Jul 25 at 8:20 am
В этом информативном тексте представлены захватывающие события и факты, которые заставят вас задуматься. Мы обращаем внимание на важные моменты, которые часто остаются незамеченными, и предлагаем новые перспективы на привычные вещи. Подготовьтесь к тому, чтобы быть поглощенным увлекательными рассказами!
Получить полную информацию – http://www.strongertechnology.com/2017/12/efficiency-through-technology
MichaelNoult
31 Jul 25 at 8:22 am
авто из кореи до 1500000 рублей [url=https://avto-iz-korei-1.ru]авто из кореи до 1500000 рублей[/url] .
Avto iz Korei_xvPi
31 Jul 25 at 8:23 am
купить диплом университета с занесением в реестр [url=http://arus-diplom31.ru/]купить диплом университета с занесением в реестр[/url] .
Diplomi_gdpl
31 Jul 25 at 8:24 am
melbet account [url=http://melbet1033.ru]http://melbet1033.ru[/url]
melbet_gjPn
31 Jul 25 at 8:26 am
лучшие манхвы манхва бесплатно
com-x-674
31 Jul 25 at 8:27 am
купить диплом колледжа с занесением в реестр в [url=https://www.arus-diplom35.ru]купить диплом колледжа с занесением в реестр в[/url] .
Kypit diplom lubogo VYZa!_xoot
31 Jul 25 at 8:27 am
Мы собрали для вас самые захватывающие факты из мира науки и истории. От малознакомых деталей до грандиозных событий — эта статья расширит ваш кругозор и подарит новое понимание того, как устроен наш мир.
Доступ к полной версии – https://andorrawithlove.com/jardins_de_juberri
JamesEdunk
31 Jul 25 at 8:28 am
free colored manga site romance manga online free
manga-166
31 Jul 25 at 8:35 am
В этой публикации мы предлагаем подробные объяснения по актуальным вопросам, чтобы помочь читателям глубже понять их. Четкость и структурированность материала сделают его удобным для усвоения и применения в повседневной жизни.
Лучшее решение — прямо здесь – https://puntoeacapo.uno/articoli/ingressobambini
AngeloBioca
31 Jul 25 at 8:36 am
Эта публикация завернет вас в вихрь увлекательного контента, сбрасывая стереотипы и открывая двери к новым идеям. Каждый абзац станет для вас открытием, полным ярких примеров и впечатляющих достижений. Подготовьтесь быть вовлеченными и удивленными каждый раз, когда продолжите читать.
Только факты! – http://dg162.net/wp/%D0%B2%D0%B0%D0%B6%D0%BD%D0%BE
Jasonincon
31 Jul 25 at 8:37 am
comics online action comics 2025 online
batcave-856
31 Jul 25 at 8:38 am
Эта публикация завернет вас в вихрь увлекательного контента, сбрасывая стереотипы и открывая двери к новым идеям. Каждый абзац станет для вас открытием, полным ярких примеров и впечатляющих достижений. Подготовьтесь быть вовлеченными и удивленными каждый раз, когда продолжите читать.
Следуйте по ссылке – https://sonyah.pro/index.php/en/component/k2/item/7/7?start=153850
WilliamLop
31 Jul 25 at 8:45 am
купить диплом о среднем образовании в реестр [url=http://www.arus-diplom34.ru]купить диплом о среднем образовании в реестр[/url] .
Bistro i prosto zakazat diplom VYZa!_ptkn
31 Jul 25 at 8:46 am
IndiGenix Pharmacy: india online pharmacy – IndiGenix Pharmacy
Richardquaxy
31 Jul 25 at 8:46 am
кайтинг Путешествия с кайтом: логистика и подготовка оборудования
Kennethvut
31 Jul 25 at 8:49 am
купить диплом с занесением в реестр в спб [url=arus-diplom35.ru]arus-diplom35.ru[/url] .
Zakazat diplom o visshem obrazovanii!_bmot
31 Jul 25 at 8:50 am
Чем дольше продолжается запой, тем большее количество токсинов накапливается в организме, нарушается водно-электролитный баланс, усугубляется работа внутренних органов, поэтому своевременное обращение за профессиональной медицинской помощью позволяет не только остановить развитие критических состояний, но и значительно снизить вероятность возникновения серьезных осложнений, угрожающих жизни и здоровью пациента
Подробнее можно узнать тут – https://vyvod-iz-zapoya-novokuznetsk66.ru/vyvod-iz-zapoya-nedorogo-novokuzneczk/
EleanorWit
31 Jul 25 at 8:56 am
Great website you have here but I was wondering if you
knew of any forums that cover the same topics discussed here?
I’d really love to be a part of online community where I can get
suggestions from other experienced individuals that share the same interest.
If you have any suggestions, please let me know. Appreciate
it!
my blog post – fiber internet Hungary
fiber internet Hungary
31 Jul 25 at 8:58 am
romance manga online free latest manga updates online
manga-865
31 Jul 25 at 8:58 am
манхва про демонов читать манхву с переводом
com-x-330
31 Jul 25 at 9:03 am
MexiCare Rx Hub: isotretinoin from mexico – buy modafinil from mexico no rx
Richardbog
31 Jul 25 at 9:03 am
Great blog here! Also your website loads up very fast!
What host are you using? Can I get your affiliate link to your host?
I wish my web site loaded up as fast as yours lol
Also visit my blog post: Hungary broadband for foreigners
Hungary broadband for foreigners
31 Jul 25 at 9:05 am
В этой публикации мы предлагаем подробные объяснения по актуальным вопросам, чтобы помочь читателям глубже понять их. Четкость и структурированность материала сделают его удобным для усвоения и применения в повседневной жизни.
Выяснить больше – https://f5fashion.vn/top-hon-51-ve-vest-cartoon-hay-nhat
Robertwox
31 Jul 25 at 9:08 am
Эта обзорная заметка содержит ключевые моменты и факты по актуальным вопросам. Она поможет читателям быстро ориентироваться в теме и узнать о самых важных аспектах сегодня. Получите краткий курс по современной информации и оставайтесь в курсе событий!
Продолжить изучение – https://f5fashion.vn/nhung-luu-y-cho-nguoi-lan-dau-mua-ve-may-bay-gia-re
DwayneDip
31 Jul 25 at 9:11 am
comics online free digital comics reader
batcave-563
31 Jul 25 at 9:14 am
кайтинг Кайтсёрфинг – это возможность увидеть мир с другой стороны, открыть для себя новые горизонты и найти свое место под солнцем. Это ваша страсть, ваша свобода, ваша жизнь.
Kennethvut
31 Jul 25 at 9:17 am
купить легально диплом [url=https://www.arus-diplom34.ru]купить легально диплом[/url] .
Priobresti diplom lubogo VYZa!_gekn
31 Jul 25 at 9:17 am
Перед игрой на деньги необходимо
пополнить баланс.
франк казино рабочее зеркало
31 Jul 25 at 9:19 am
manga online best manga reader 2025
manga-187
31 Jul 25 at 9:20 am
номер мелбет [url=melbet1035.ru]номер мелбет[/url]
melbet_qzKt
31 Jul 25 at 9:23 am
купить проведенный диплом весь [url=https://arus-diplom35.ru]купить проведенный диплом весь[/url] .
Zakazat diplom o visshem obrazovanii!_uuot
31 Jul 25 at 9:24 am
В этой публикации мы предлагаем подробные объяснения по актуальным вопросам, чтобы помочь читателям глубже понять их. Четкость и структурированность материала сделают его удобным для усвоения и применения в повседневной жизни.
Ознакомьтесь с аналитикой – https://f5fashion.vn/di-dau-mien-tay-mua-nuoc-noi
Jeffreyswink
31 Jul 25 at 9:28 am
IndiGenix Pharmacy: buy medicines online in india – IndiGenix Pharmacy
Richardbog
31 Jul 25 at 9:30 am
обучение кайтсёрфингу Кайтсёрфинг оборудование: инвестируйте в качество. Кайт, доска, трапеция – основа вашего комфорта и безопасности.
Kennethvut
31 Jul 25 at 9:30 am
Awesome! Its truly awesome article, I have got much clear
idea concerning from this post.
situs toto togel
31 Jul 25 at 9:33 am
романтическая манхва манхва бесплатно
com-x-122
31 Jul 25 at 9:34 am
It’s amazing designed for me to have a web page, which is
good in favor of my knowledge. thanks admin
Here is my web blog :: internet in Hongarije
internet in Hongarije
31 Jul 25 at 9:34 am