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!
J’adore passionnement Betway Casino, c’est une veritable aventure pleine d’adrenaline. La gamme de jeux est tout simplement phenomenale, incluant des slots de pointe de Microgaming et NetEnt. Le service client est de haut niveau, offrant des reponses claires et utiles. Les gains arrivent rapidement, parfois les bonus comme les 125 tours gratuits pourraient etre plus reguliers. Globalement, Betway Casino ne decoit jamais pour les passionnes de jeux numeriques ! De plus la navigation est intuitive sur l’application mobile iOS/Android, facilite chaque session de jeu.
betway apk|
Kevinman8zef
3 Sep 25 at 11:14 am
купить диплом с занесением в реестр цена [url=https://arus-diplom31.ru/]купить диплом с занесением в реестр цена[/url] .
Diplomi_japl
3 Sep 25 at 11:15 am
ставки на спорт мостбет [url=http://mostbet4122.ru/]ставки на спорт мостбет[/url]
mostbet_tkpl
3 Sep 25 at 11:16 am
Для любых водителей — от стартующих до профессионалов, открыт портал с интересными публикациями, автословарём, обновлениями и видео. Читать полезности > сайт-блог [url=https://citroen-avtoservise.ru]https://citroen-avtoservise.ru[/url] публикует рекомендациями для всех. Посмотри новое — прочитать блог.
Spravkiope
3 Sep 25 at 11:16 am
It’s an awesome piece of writing designed for all the internet users;
they will take advantage from it I am sure.
vovan casino официальный сайт
3 Sep 25 at 11:18 am
888starz onlayn qimor o’yinlari orqali kengaytirish mumkin. Bu o’yin maydoni taqdim etadi.
mavjud . qimor ixlosmandlari mumkin.
hamda yordam beradi. ko’plab ma’lumotlar joylashgan maqolalar mavjud.
joriy etadi . himoya qilinadi . Shu sababli, mumkin.
888starz no deposit bonus code [url=https://www.888starz-uzs.net/promo-code]https://888starz-uzs.net/promo-code/[/url]
888starz_yzOi
3 Sep 25 at 11:20 am
Ancient Tumble casinos AZ
Darwinlix
3 Sep 25 at 11:21 am
Эта публикация завернет вас в вихрь увлекательного контента, сбрасывая стереотипы и открывая двери к новым идеям. Каждый абзац станет для вас открытием, полным ярких примеров и впечатляющих достижений. Подготовьтесь быть вовлеченными и удивленными каждый раз, когда продолжите читать.
Практические советы ждут тебя – https://insan-org.de/ar/28007-2
Edwardfaibe
3 Sep 25 at 11:22 am
В этой статье представлен занимательный и актуальный контент, который заставит вас задуматься. Мы обсуждаем насущные вопросы и проблемы, а также освещаем истории, которые вдохновляют на действия и изменения. Узнайте, что стоит за событиями нашего времени!
Почему это важно? – http://zebranolab.ru
Richardcrone
3 Sep 25 at 11:22 am
J’apprecie enormement CasinoAndFriends, ca ressemble a une energie de jeu irresistible. La selection de jeux est impressionnante avec plus de 1000 titres, proposant des jeux de table classiques comme le blackjack et la roulette. Le support est reactif via chat en direct de 6h a minuit, garantissant une aide immediate. Les retraits sont rapides, souvent traites en 24 heures pour les e-wallets, parfois plus de tours gratuits seraient un atout. En resume, CasinoAndFriends est un incontournable pour les amateurs de casino en ligne ! En bonus le site est concu avec modernite et ergonomie, renforce l’immersion totale.
casinoandfriends recension|
Michaelmike4zef
3 Sep 25 at 11:22 am
cialis sans ordonnance: commander cialis discretement – IntimaPharma France
AnthonyFup
3 Sep 25 at 11:24 am
купить аттестат за 11 класс в бишкеке [url=https://arus-diplom23.ru]купить аттестат за 11 класс в бишкеке[/url] .
Diplomi_dnol
3 Sep 25 at 11:24 am
At this moment I am going away to do my breakfast, when having my breakfast coming over again to read further news.
stickman.pro
3 Sep 25 at 11:28 am
купить диплом киев сколько [url=https://www.educ-ua3.ru]купить диплом киев сколько[/url] .
Diplomi_fxki
3 Sep 25 at 11:28 am
tadalafil sans ordonnance: tadalafil prix – tadalafil sans ordonnance
AnthonyFup
3 Sep 25 at 11:30 am
pharmacie digitale francaise fiable [url=https://pharmaexpressfrance.com/#]pharmacie digitale francaise fiable[/url] Pharmacie sans ordonnance
KennethOpike
3 Sep 25 at 11:30 am
mostbet официальный сайт [url=http://mostbet4124.ru/]http://mostbet4124.ru/[/url]
mostbet_kxsr
3 Sep 25 at 11:30 am
https://hub.docker.com/u/olopelagasa
RobertGot
3 Sep 25 at 11:33 am
vente de mГ©dicament en ligne: PharmaExpress – pharmacie en ligne
AnthonyFup
3 Sep 25 at 11:37 am
высшее образование купить диплом с занесением в реестр [url=http://arus-diplom31.ru]высшее образование купить диплом с занесением в реестр[/url] .
Diplomi_owpl
3 Sep 25 at 11:37 am
mostbet oficial [url=mostbet4125.ru]mostbet4125.ru[/url]
mostbet_kg_yeml
3 Sep 25 at 11:38 am
http://www.mostbet [url=http://mostbet4122.ru/]www.mostbet[/url]
mostbet_aipl
3 Sep 25 at 11:39 am
유흥알바는 주로 밤 시간대에 이루어지는
엔터테인먼트 업소에서의 아르바이트를 말합니다.
클럽, 바(bar), 노래주점(가라오케)이나 룸살롱 등에서 고객
유흥알바
3 Sep 25 at 11:40 am
zamonaviy usullar orqali o’yin jarayonini mumkin. ko’p taqdim etadi.
Qimor o’yinlari . rohatlanishlari mumkin.
va yordam beradi. Pul tikish jarayonlari joylashgan sharhlar mavjud.
Ishtirokchilar xavfsizligi . Foydalanuvchilarning . ishonch bilan kirishlari mumkin.
888starz ios download [url=888starz-uzs.net/apk]https://888starz-uzs.net/apk/[/url]
888starz_cmOi
3 Sep 25 at 11:43 am
I absolutely love your website.. Very nice colors & theme.
Did you build this website yourself? Please reply back as I’m trying to create my
very own site and want to find out where you got this from or
exactly what the theme is named. Thank you!
capai138
3 Sep 25 at 11:44 am
массаж новосибирск Новосибирск предлагает широкий спектр массажных услуг для релаксации, оздоровления и решения различных проблем. Вы можете найти классический массаж для снятия напряжения, спортивный массаж для восстановления после тренировок, антицеллюлитный массаж для улучшения фигуры и многое другое. Важно выбирать квалифицированного специалиста, учитывать свои индивидуальные потребности и противопоказания. Перед началом курса массажа рекомендуется проконсультироваться с врачом, особенно если у вас есть какие-либо хронические заболевания. Для поиска подходящего массажного салона или частного мастера можно использовать онлайн-платформы с рейтингами и отзывами, а также рекомендации знакомых. Не стесняйтесь задавать вопросы о квалификации специалиста и используемых техниках. Комфортная атмосфера, чистота и соблюдение гигиенических норм также являются важными факторами при выборе места для массажа.
LonnieSnict
3 Sep 25 at 11:50 am
мостбет вход регистрация [url=https://mostbet4119.ru]https://mostbet4119.ru[/url]
mostbet_rkEt
3 Sep 25 at 11:54 am
мостбет зеркало скачать [url=https://mostbet4126.ru]https://mostbet4126.ru[/url]
mostbet_kg_gwkn
3 Sep 25 at 11:54 am
Hi there, this weekend is good for me, because this occasion i am reading this impressive educational post here at my residence.
webpage
3 Sep 25 at 11:55 am
https://rant.li/rohybtidy/gde-kupit-liriku-bishkek-bez-retsepta-telegramm
RobertGot
3 Sep 25 at 11:56 am
Этот текст призван помочь читателю расширить кругозор и получить практические знания. Мы используем простой язык, наглядные примеры и структурированное изложение, чтобы сделать обучение максимально эффективным и увлекательным.
Только для своих – https://isi-luftfilter.de/hallo-welt
Davidaffer
3 Sep 25 at 11:57 am
https://sergioetff539.trexgame.net/the-top-500-countertop-companies-in-the-u-s-prestige-you-cant-buy
Did you know that in 2025, only around 2,000 companies earned a spot in the Top Countertop Contractors Ranking out of thousands evaluated? That’s because at we only recognize excellence.
Our ranking is independent, constantly refreshed, and built on 21+ criteria. These include feedback from Google, Yelp, and other platforms, affordability, responsiveness, and results. On top of that, we conduct countless phone calls and over two thousand estimate requests through our mystery shopper program.
The result is a standard that benefits both clients and installation companies. Homeowners get a reliable way to choose contractors, while listed companies gain prestige, online authority, and even new business opportunities.
The Top 500 Awards spotlight categories like Best Old Contractors, Rising Stars, and Value Leaders. Winning one of these honors means a company has achieved unmatched credibility in the industry.
If you’re ready to hire a countertop contractor—or your company wants to be listed among the best—this site is where quality meets visibility.
JuniorShido
3 Sep 25 at 11:57 am
https://fixed-float.to
Edwinbot
3 Sep 25 at 11:58 am
I used to feel guilty for taking time to care for myself, but 여성전용마사지 helped me understand that self-care is not selfish—it’s essential for emotional
balance and physical health.
서울여성전용마사지
3 Sep 25 at 11:59 am
купить диплом в запорожье [url=https://educ-ua3.ru/]купить диплом в запорожье[/url] .
Diplomi_ziki
3 Sep 25 at 12:02 pm
Appreciate this post. Will try it out.
My web-site – 9 lotto result malaysia
9 lotto result malaysia
3 Sep 25 at 12:03 pm
Please let me know if you’re looking for a article author for your weblog.
You have some really good posts and I feel I would be a good asset.
If you ever want to take some of the load off, I’d really like to write some articles for your blog in exchange for a link
back to mine. Please shoot me an email if interested. Many
thanks!
orthodontic braces
3 Sep 25 at 12:03 pm
AutoRent — аренда автомобилей в Минске. Ищете аренда авто бизнес-класса? На autorent.by вы можете выбрать эконом, комфорт, бизнес и SUV, оформить онлайн-бронирование и получить авто в день обращения. Прозрачные цены, чистые машины, поддержка 24/7. Подача в аэропорт Минск, самовывоз из города. Посуточно и на длительный срок; опции: детские кресла и доп. оборудование.
ukexehob
3 Sep 25 at 12:05 pm
tadalafil 20 mg en ligne: commander cialis discretement – Pharmacie sans ordonnance
Maliknaimi
3 Sep 25 at 12:08 pm
В этой статье представлен занимательный и актуальный контент, который заставит вас задуматься. Мы обсуждаем насущные вопросы и проблемы, а также освещаем истории, которые вдохновляют на действия и изменения. Узнайте, что стоит за событиями нашего времени!
Что ещё? Расскажи всё! – https://www.wasp.one/hej-varlden
Davidaffer
3 Sep 25 at 12:08 pm
В Химках вывести человека из запоя с выездом на дом реально — специалисты Stop Alko работают круглосуточно, оказывая профессиональную поддержку.
Ознакомиться с деталями – [url=https://vyvod-iz-zapoya-himki11.ru/]врач вывод из запоя[/url]
Willieswefs
3 Sep 25 at 12:10 pm
стоимость создание и продвижение сайтов
CoreyThype
3 Sep 25 at 12:11 pm
I am not sure where you’re getting your info, but great topic.
I needs to spend some time learning much more or understanding more.
Thanks for great information I was looking for
this info for my mission.
با رتبه ۳۵۰۰۰ تجربی دانشگاه آزاد چی میارم
3 Sep 25 at 12:12 pm
https://bbcr.eu/
GregoryIdons
3 Sep 25 at 12:12 pm
купить диплом магистра [url=http://educ-ua3.ru]купить диплом магистра[/url] .
Diplomi_ecki
3 Sep 25 at 12:13 pm
Pretty! This has been a really wonderful article.
Many thanks for providing these details.
certified organic
3 Sep 25 at 12:13 pm
Write more, thats all I have to say. Literally, it seems as though you
relied on the video to make your point. You obviously know
what youre talking about, why throw away your intelligence on just posting videos to your blog when you could be giving us
something informative to read?
situs toto slot
3 Sep 25 at 12:15 pm
Как подчёркивает специалист ФГБУ «НМИЦ психиатрии и наркологии», «без участия квалифицированной команды невозможно обеспечить комплексный подход к пациенту, особенно если речь идёт о длительном стаже употребления и осложнённой картине заболевания». Отсюда следует — изучение состава персонала должно быть одним из первых шагов.
Получить больше информации – [url=https://lechenie-alkogolizma-murmansk0.ru/]наркологическое лечение алкоголизма[/url]
Donnellpah
3 Sep 25 at 12:16 pm
Кроме стационара, клиника обеспечивает выезд нарколога на дом в любое время суток. Это позволяет оперативно начать детоксикацию и стабилизацию состояния, не дожидаясь свободного места в клинике или оформления госпитализации. Высокая мобильность специалистов и оснащённость автомобиля всем необходимым оборудованием гарантируют качественную помощь прямо на дому.
Получить больше информации – http://narkologicheskaya-klinika-sochi00.ru/narkologicheskaya-klinika-vyvod-iz-zapoya-sochi/https://narkologicheskaya-klinika-sochi00.ru
BradleyKnimb
3 Sep 25 at 12:17 pm
Наркологическая клиника — это не просто место, где пациенту оказывают медицинскую помощь. Это учреждение, где формируется стратегия полного восстановления, включающая не только физическое оздоровление, но и психоэмоциональную стабилизацию. В Ярославле работают как частные, так и государственные клиники, однако их подходы, уровень сервиса и состав команд могут существенно различаться. По данным Минздрава РФ, высокий процент успешных исходов наблюдается в тех учреждениях, где реализуется персонализированная модель лечения и постлечебной поддержки.
Получить больше информации – [url=https://narkologicheskaya-klinika-yaroslavl0.ru/]narkologicheskaya-klinika-yaroslavl0.ru/[/url]
StevenChory
3 Sep 25 at 12:18 pm