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!
seo продвижение сайта агентство [url=www.seo-prodvizhenie-reiting-kompanij.ru]seo продвижение сайта агентство[/url] .
seo prodvijenie reiting kompanii_nist
22 Oct 25 at 3:34 pm
https://cgmood.com/betpromo-codes
zfzzdwe
22 Oct 25 at 3:36 pm
нету. в ближайшее время не будет.
https://gorlovkazn.ru
продукт – прет дико и жестко, но по сути ничего интересного, цена в 2 тыр себя полностью оправдывает. Эдакий бычий кайф. Если вам нравится трястись и стучать зубами – вы попали по адресу. Во всех остальных случаях – нахер-нахер. Слабенькая 3/5
Jaysonjutle
22 Oct 25 at 3:37 pm
купить диплом легально [url=http://frei-diplom1.ru/]купить диплом легально[/url] .
Diplomi_vuOi
22 Oct 25 at 3:37 pm
технический английский перевод [url=https://www.dzen.ru/a/aPFFa3ZMdGVq1wVQ]https://www.dzen.ru/a/aPFFa3ZMdGVq1wVQ[/url] .
Tehnicheskii perevod_dfml
22 Oct 25 at 3:38 pm
купить диплом в брянске [url=https://www.rudik-diplom7.ru]купить диплом в брянске[/url] .
Diplomi_srPl
22 Oct 25 at 3:39 pm
The Inheritance Games Canada: A thrilling mystery game where players unravel secrets, solve puzzles, and compete for a billionaire’s fortune. Perfect for fans of strategy and suspense: Inheritance Games fan theories
GabrielLyday
22 Oct 25 at 3:39 pm
можно ли купить диплом медсестры [url=https://frei-diplom14.ru]можно ли купить диплом медсестры[/url] .
Diplomi_dhoi
22 Oct 25 at 3:39 pm
Hi all, here every person is sharing these knowledge, so it’s fastidious to
read this weblog, and I used to visit this weblog everyday.
bokep
22 Oct 25 at 3:40 pm
медицинский перевод [url=https://telegra.ph/Medicinskij-perevod-tochnost-kak-vopros-zhizni-i-zdorovya-10-16/]https://telegra.ph/Medicinskij-perevod-tochnost-kak-vopros-zhizni-i-zdorovya-10-16/[/url] .
Medicinskii perevod_kbEr
22 Oct 25 at 3:41 pm
чому собака виє вдень прикмети
JessieVinge
22 Oct 25 at 3:43 pm
купить диплом в нефтекамске [url=http://rudik-diplom2.ru/]купить диплом в нефтекамске[/url] .
Diplomi_lwpi
22 Oct 25 at 3:44 pm
Great info. Lucky me I recently found your site by
chance (stumbleupon). I have book marked it for later!
씨알리스 구매
22 Oct 25 at 3:44 pm
купить диплом по реестру [url=https://frei-diplom1.ru/]купить диплом по реестру[/url] .
Diplomi_seOi
22 Oct 25 at 3:46 pm
купить диплом в перми [url=rudik-diplom7.ru]купить диплом в перми[/url] .
Diplomi_bjPl
22 Oct 25 at 3:46 pm
Hey there! This is kind of off topic but I need some guidance from an established blog.
Is it very difficult to set up your own blog? I’m not very
techincal but I can figure things out pretty quick. I’m thinking about making my own but I’m not sure where
to begin. Do you have any points or suggestions?
Thank you
adam and eve offer code
22 Oct 25 at 3:47 pm
https://demo.devs.mx/journal3/blog/another-blog-post/
qwgnuhy
22 Oct 25 at 3:48 pm
https://factava.com.ua/diyety/diieta-pry-lypomatoz-pidshlunkovoi-zalozy-kliuchovi-porady-dlia-zdorovia-i-pokrashchennia-samopochuttia/
JessieVinge
22 Oct 25 at 3:48 pm
технический перевод это [url=http://www.dzen.ru/a/aPFFa3ZMdGVq1wVQ]http://www.dzen.ru/a/aPFFa3ZMdGVq1wVQ[/url] .
Tehnicheskii perevod_heml
22 Oct 25 at 3:48 pm
The $MTAUR token presale is a steal at current rates. Audited contracts and vesting smart. Minotaur adventures await.
mtaur token
WilliamPargy
22 Oct 25 at 3:49 pm
Зачисление средств после оплаты счета от казино производится моментально, достаточно обновить страницу профиля для проверки.
казино аркада скачать
22 Oct 25 at 3:50 pm
интернет агентство продвижение сайтов [url=https://seo-prodvizhenie-reiting-kompanij.ru]https://seo-prodvizhenie-reiting-kompanij.ru[/url] .
seo prodvijenie reiting kompanii_jost
22 Oct 25 at 3:51 pm
купить диплом в брянске [url=https://www.rudik-diplom2.ru]купить диплом в брянске[/url] .
Diplomi_ctpi
22 Oct 25 at 3:51 pm
купить диплом в сургуте [url=https://www.rudik-diplom3.ru]купить диплом в сургуте[/url] .
Diplomi_sxei
22 Oct 25 at 3:51 pm
купить диплом биолога [url=http://rudik-diplom12.ru]купить диплом биолога[/url] .
Diplomi_jiPi
22 Oct 25 at 3:51 pm
медицинский перевод на английский [url=www.telegra.ph/Medicinskij-perevod-tochnost-kak-vopros-zhizni-i-zdorovya-10-16]www.telegra.ph/Medicinskij-perevod-tochnost-kak-vopros-zhizni-i-zdorovya-10-16[/url] .
Medicinskii perevod_atEr
22 Oct 25 at 3:52 pm
Говорить по этому вопросу можно долго.
When this is reduced indicator the [url=https://tradingturkey.net/]tradestation turkiye[/url] and balance may be limited. despite the fact that salaries are not most liberal, margin insight recognized the first of the best.
DianaOresk
22 Oct 25 at 3:52 pm
Подробная инструкция по активации бонусов и типам предложений — от фрибетов до подарков на День Рождения; в тексте естественно вставлена ссылка на 1хБет промокод на сегодня, дабы читатель мог сразу перейти к источнику. Статья также рассказывает о верификации и минимальных требованиях для вывода средств.
Anthonykit
22 Oct 25 at 3:52 pm
Разнообразие Игрового Мира: Казино Гама
и Ваша Победа https://safezone.com.ua/
https://safezone.com.ua/
22 Oct 25 at 3:53 pm
If some one wishes to be updated with latest technologies
then he must be go to see this web site and be up to date daily.
adam and eve promo code
22 Oct 25 at 3:53 pm
Potenzmittel rezeptfrei kaufen [url=https://medivertraut.com/#]sichere Online-Apotheke Deutschland[/url] sichere Online-Apotheke Deutschland
CharlesNeono
22 Oct 25 at 3:54 pm
виды технического перевода [url=https://dzen.ru/a/aPFFa3ZMdGVq1wVQ/]https://dzen.ru/a/aPFFa3ZMdGVq1wVQ/[/url] .
Tehnicheskii perevod_rlml
22 Oct 25 at 3:59 pm
купить диплом в ялте [url=rudik-diplom2.ru]купить диплом в ялте[/url] .
Diplomi_ttpi
22 Oct 25 at 4:01 pm
*%BuyBlackhat-SEO-Hidden-LinkTelegram @buycasinolink
BuyBlackhat-SEO-Hidden-LinkTelegram @buycasinolink
22 Oct 25 at 4:02 pm
seo компания [url=https://seo-prodvizhenie-reiting-kompanij.ru/]seo компания[/url] .
seo prodvijenie reiting kompanii_ihst
22 Oct 25 at 4:02 pm
Bonus exclusif 1xBet pour 2026 : obtenez un bonus de 100% jusqu’a 130€ lors de votre inscription. Une promotion reservee aux nouveaux joueurs de paris sportifs, incluant des paris gratuits. Rejoignez 1xBet avant le 31 decembre 2026. Le lien ci-dessous vous menera vers le code promo officiel 1xBet — Code Promo Gratuit. Le code promo 1xBet vous permet d’activer un bonus d’inscription 1xBet exclusif et de commencer a parier avec un avantage. Le code promotionnel 1xBet 2026 est valable pour les paris sportifs, le casino en ligne et les tours gratuits. Decouvrez des aujourd’hui le meilleur code promo 1xBet et profitez du bonus de bienvenue 1xBet sans depot initial.
Marvinspaft
22 Oct 25 at 4:03 pm
Oh man, reputable schools deliver management programs, developing upocoming CEOs ɑnd business owners.
Guardians, Ьetter stay vigilant leh, tⲟp
establishments develop writing abilities, vital fⲟr reporting or judicial professions.
Ⲟh man, no matter tһough school гemains atas, arithmetic acts ⅼike thе critical
subject іn developing poise in figures.
Wah lao, no matter іf establishment remains high-end, math
іs thhe maкe-or-break subject for cultivates assurance ѡith numbers.
Don’t play play lah, link а excellent primary school рlus math excellence іn оrder to ensure elevated PSLE scores ɑnd effortless ϲhanges.
Besides beyond school resources, focus ᧐n arithmetic in ߋrder to
stop typical mistakes including inattentive errors ɑt exams.
Listen ᥙр, steady pom pi ρi, mathematics remаins paгt
off the top disciplines іn primary school, establishing
base fоr A-Level calculus.
Seng Kang Primary School ⅽreates a lively ɑrea concentrated on holistic
development.
Devoted instructors motivate achievement аnd character building.
Singapore Chinese Girls’ Primary School empowers ladies ѡith bilingual excellence.
The school promotes cultural competence.
Ιt’s perfect fοr heritage-focused education.
Feel free to visit my һomepage :: Northbrooks Secondary School
Northbrooks Secondary School
22 Oct 25 at 4:04 pm
Система промокодов при регистрации даёт возможность новым игрокам получать бонусы к первому депозиту; мы описываем, как правильно заполнить регистрационную форму и где указать данные, а в середине примера даём ссылку на https://bergkompressor.ru/news/artcles/?1xbet_promokod_pri_registracii_bonus_5.html для удобства. Важно, что бонусные условия могут отличаться в зависимости от региона.
Anthonykit
22 Oct 25 at 4:04 pm
купить диплом в белгороде [url=https://www.rudik-diplom3.ru]купить диплом в белгороде[/url] .
Diplomi_vcei
22 Oct 25 at 4:05 pm
pharmacie en ligne fiable France [url=https://santehommefrance.shop/#]pharmacie en ligne fiable France[/url] SanteHommeFrance
CharlesNeono
22 Oct 25 at 4:07 pm
медицинский перевод на английский [url=http://telegra.ph/Medicinskij-perevod-tochnost-kak-vopros-zhizni-i-zdorovya-10-16/]http://telegra.ph/Medicinskij-perevod-tochnost-kak-vopros-zhizni-i-zdorovya-10-16/[/url] .
Medicinskii perevod_taEr
22 Oct 25 at 4:11 pm
Вместо отзывы Вы можете проголосовать, и повлиять на рейтинг своим решением.
бонусный код joycasino
22 Oct 25 at 4:14 pm
With havin so much content and articles do you
ever run into any issues of plagorism or copyright violation? My website
has a lot of completely unique content I’ve either authored myself or
outsourced but it looks like a lot of it is popping it
up all over the web without my authorization. Do you know any methods to
help protect against content from being stolen? I’d truly appreciate it.
play-zula.casino
22 Oct 25 at 4:15 pm
купить диплом маркетолога [url=http://rudik-diplom3.ru]купить диплом маркетолога[/url] .
Diplomi_djei
22 Oct 25 at 4:16 pm
перевод технической документации [url=http://www.dzen.ru/a/aPFFa3ZMdGVq1wVQ]http://www.dzen.ru/a/aPFFa3ZMdGVq1wVQ[/url] .
Tehnicheskii perevod_ymml
22 Oct 25 at 4:18 pm
Nice post. I was checking continuously this blog and I am impressed!
Extremely useful information specifically the last part 🙂 I care for such info
much. I was seeking this certain info for a long time.
Thank you and good luck.
website mua bán ma túy
22 Oct 25 at 4:19 pm
https://business-guide.com.ua/about/articles_bg?id=1315
Jamiecat
22 Oct 25 at 4:21 pm
медсестра которая купила диплом врача [url=frei-diplom13.ru]frei-diplom13.ru[/url] .
Diplomi_mlkt
22 Oct 25 at 4:22 pm
kraken Безопасность Транзакций: Баланс Анонимности и Риска Использование “kraken” предполагает определенный уровень риска, связанный с анонимностью транзакций. Хотя сохранение конфиденциальности является одним из ключевых преимуществ платформы, оно же затрудняет разрешение споров и защиту от мошенничества. При совершении покупок на “kraken” необходимо тщательно выбирать продавцов, изучать отзывы и использовать эскроу-сервисы для минимизации финансовых потерь. Крайне важно помнить, что стремление к анонимности не должно быть поводом для игнорирования правил безопасности и здравого смысла.
Bryandon
22 Oct 25 at 4:22 pm
Magnificent site. Plenty of useful information here.
I’m sending it to some friends ans additionally sharing in delicious.
And of course, thanks on your effort!
adameve offer code
22 Oct 25 at 4:23 pm