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!
WOW just what I was searching for. Came here by searching
for expert education benefits
premium insurance benefits
22 Oct 25 at 11:19 pm
перевод научно технических текстов [url=https://teletype.in/@alexd78/HN462R01hzy/]https://teletype.in/@alexd78/HN462R01hzy/[/url] .
Vidi perevodov v buro Perevod i Pravo_cast
22 Oct 25 at 11:20 pm
createandgrow.click – Found unique resources here I hadn’t seen elsewhere, really impressed.
Genevieve Netley
22 Oct 25 at 11:21 pm
globaltrendmarket.click – Quality of the product impressed me; exactly as described and arrived on time.
Edward Schildknecht
22 Oct 25 at 11:22 pm
newseasoncollection.shop – Nice variety of colours and cuts, made my shopping fun and easy.
Tomasa Ebberts
22 Oct 25 at 11:22 pm
theperfectgiftshop.click – Highly recommend this store for anyone looking to pick meaningful and well-designed gifts.
Juliane Elefritz
22 Oct 25 at 11:24 pm
I couldn’t resist commenting. Very well written!
Equiloompro
22 Oct 25 at 11:26 pm
купить диплом вуза диплом техникума пять плюс [url=http://frei-diplom7.ru]купить диплом вуза диплом техникума пять плюс[/url] .
Diplomi_snei
22 Oct 25 at 11:28 pm
https://www.leonidastacticalss.com/profile/mdraselminhaj31044525/profile
Kevinfup
22 Oct 25 at 11:28 pm
smartchoiceoutlet.click – Highly recommend this store for anyone looking for trustworthiness and great value.
Ramiro Novara
22 Oct 25 at 11:28 pm
Капельница от запоя в Нижнем Новгороде — процедура, направленная на детоксикацию организма и восстановление нормального самочувствия. Она включает в себя введение препаратов, способствующих выведению токсинов и восстановлению функций органов.
Выяснить больше – [url=https://vyvod-iz-zapoya-nizhnij-novgorod12.ru/]vyvod-iz-zapoya-nizhnij-novgorod12.ru/[/url]
CharlesDof
22 Oct 25 at 11:29 pm
uniquetrendstore.click – Good quality for the price, really satisfied with my purchase.
Sharonda Kazmierski
22 Oct 25 at 11:29 pm
I think the admin of this site is genuinely working hard for his web page,
as here every information is quality based data.
Moonlight Cushion Cover
22 Oct 25 at 11:30 pm
dreamcreateinspire.click – Every piece of content feels meaningful and well-designed for growth.
Cliff Castelum
22 Oct 25 at 11:31 pm
медицинский перевод на английский [url=http://www.telegra.ph/Medicinskij-perevod-tochnost-kak-vopros-zhizni-i-zdorovya-10-16]http://www.telegra.ph/Medicinskij-perevod-tochnost-kak-vopros-zhizni-i-zdorovya-10-16[/url] .
Medicinskii perevod_ygEr
22 Oct 25 at 11:32 pm
http://bluepeakmeds.com/# discreet shipping for ED medication
LanceHek
22 Oct 25 at 11:32 pm
технический перевод требования [url=http://dzen.ru/a/aPFFa3ZMdGVq1wVQ/]http://dzen.ru/a/aPFFa3ZMdGVq1wVQ/[/url] .
Tehnicheskii perevod_npml
22 Oct 25 at 11:33 pm
inspireeverydaylife.shop – Prompt customer service, resolved my issue quickly and efficiently.
Griselda Mcgunnis
22 Oct 25 at 11:35 pm
kombiwetten bonus
My web-site … Wetten Quote erkläRung
Wetten Quote erkläRung
22 Oct 25 at 11:36 pm
перевод научно технических текстов [url=http://www.teletype.in/@alexd78/HN462R01hzy]http://www.teletype.in/@alexd78/HN462R01hzy[/url] .
Vidi perevodov v buro Perevod i Pravo_szst
22 Oct 25 at 11:37 pm
I am curious to find out what blog system you are working
with? I’m having some minor security problems with
my latest site and I’d like to find something more safe.
Do you have any solutions?
bs2best at
22 Oct 25 at 11:38 pm
купить диплом химика [url=https://rudik-diplom13.ru/]купить диплом химика[/url] .
Diplomi_ogon
22 Oct 25 at 11:38 pm
где купить диплом техникума если [url=http://frei-diplom7.ru/]где купить диплом техникума если[/url] .
Diplomi_khei
22 Oct 25 at 11:39 pm
Joined $MTAUR rush—prizes await. ICO’s tokenomics sound. Mazes challenging.
minotaurus coin
WilliamPargy
22 Oct 25 at 11:45 pm
технический перевод [url=https://teletype.in/@alexd78/HN462R01hzy]https://teletype.in/@alexd78/HN462R01hzy[/url] .
Vidi perevodov v buro Perevod i Pravo_vpst
22 Oct 25 at 11:46 pm
диплом техникума купить дешево пять плюс [url=frei-diplom7.ru]диплом техникума купить дешево пять плюс[/url] .
Diplomi_xgei
22 Oct 25 at 11:47 pm
wetten immer gewinnen
my web-site; gratis guthaben ohne einzahlung sportwetten (Edith)
Edith
22 Oct 25 at 11:49 pm
I’ll right away grab your rss feed as I can not find your email subscription link or newsletter
service. Do you have any? Please permit me recognise so that I may
just subscribe. Thanks.
Purchase Magic mushrooms online
22 Oct 25 at 11:49 pm
thinkcreategrow – Bookmarking this one, I know I’ll be back later this week.
Jay Tchakian
22 Oct 25 at 11:51 pm
Я хорошо разбираюсь в этом. Могу помочь в решении вопроса. Вместе мы сможем найти решение.
At the [url=https://pin-up-azerbaycan1.com/main-page/]https://pin-up-azerbaycan1.com/main-page/[/url] no less in demand card games table games role-playing and fans can spend a lot of time in Texas Hold’em, seven-card stud-poker and many others board games.
MattWew
22 Oct 25 at 11:53 pm
перевод медицинский на русский язык [url=www.teletype.in/@alexd78/HN462R01hzy]www.teletype.in/@alexd78/HN462R01hzy[/url] .
Vidi perevodov v buro Perevod i Pravo_wtst
22 Oct 25 at 11:53 pm
Привет всем!
Вы можете купить виртуальный номер для смс навсегда в любое время. Мы поможем купить виртуальный номер для смс навсегда без лишних данных. Надёжность и удобство — вот почему стоит купить виртуальный номер для смс навсегда. Закажите услугу и успейте купить виртуальный номер для смс навсегда уже сегодня. Умный выбор — купить виртуальный номер для смс навсегда.
Полная информация по ссылке – [url=https://car-profy.ru/avtomatizatsiya-biznesa-kak-virtualnyj-nomer-uproshhaet-kommunikatsiyu/]купить белорусский номер для смс[/url]
купить постоянный виртуальный номер, купить виртуальный номер, купить постоянный виртуальный номер
виртуальный номер навсегда, постоянный виртуальный номер, купить виртуальный номер для смс навсегда
Удачи и комфорта в общении!
Nomerassok
22 Oct 25 at 11:53 pm
Heya! I’m at work browsing your blog from my new iphone 4!
Just wanted to say I love reading your blog and look forward
to all your posts! Keep up the fantastic work!
Axiron Ai TEST
22 Oct 25 at 11:53 pm
Je suis totalement ensorcele par Monte Cryptos Casino, ca procure une sensation numerique unique. Les options sont vastes comme un reseau, avec des slots aux themes modernes. Le bonus d’accueil est eclatant. Les agents repondent comme une comete, joignable a tout moment. Les transferts sont fiables, parfois plus de promos regulieres dynamiseraient l’experience. Dans l’ensemble, Monte Cryptos Casino vaut une plongee numerique pour ceux qui parient avec des cryptos ! En bonus la plateforme est visuellement eblouissante, donne envie de prolonger l’aventure. Un avantage notable les evenements communautaires innovants, propose des avantages uniques.
Commencer Г lire|
StarBitX2zef
22 Oct 25 at 11:55 pm
медицинский перевод справок [url=https://www.telegra.ph/Medicinskij-perevod-tochnost-kak-vopros-zhizni-i-zdorovya-10-16]https://www.telegra.ph/Medicinskij-perevod-tochnost-kak-vopros-zhizni-i-zdorovya-10-16[/url] .
Medicinskii perevod_ftEr
22 Oct 25 at 11:55 pm
технический перевод в машиностроении [url=https://dzen.ru/a/aPFFa3ZMdGVq1wVQ/]https://dzen.ru/a/aPFFa3ZMdGVq1wVQ/[/url] .
Tehnicheskii perevod_eeml
22 Oct 25 at 11:56 pm
joinourcreativeworld.click – The tone is friendly and encouraging—makes you feel you can accomplish something big.
Freeman Rozzelle
22 Oct 25 at 11:56 pm
The Minotaurus presale vesting is flexible genius. Token’s DAO influence key. Gaming market ripe.
mtaur token
WilliamPargy
22 Oct 25 at 11:56 pm
https://bluepeakmeds.shop/# how generic Viagra works in the body
LanceHek
22 Oct 25 at 11:57 pm
Клиника «Похмельная служба» в Нижнем Новгороде предлагает капельницу от запоя с выездом на дом. Наши специалисты обеспечат вам комфортное и безопасное лечение в привычной обстановке.
Разобраться лучше – [url=https://vyvod-iz-zapoya-nizhnij-novgorod11.ru/]вывод из запоя клиника нижний новгород[/url]
JessiesoYmn
22 Oct 25 at 11:57 pm
discovernewworld.click – Quality of the product exceeded my expectations, very pleased with purchase.
Walker Alioto
22 Oct 25 at 11:58 pm
J’adore l’ambiance numerique de Monte Cryptos Casino, il offre une odyssee chiffree. Le repertoire est riche et varie, incluant des paris en direct dynamiques. Boostant votre portefeuille initial. Le suivi est d’une efficacite redoutable, offrant des reponses claires. Les gains arrivent sans delai, neanmoins des offres plus genereuses ajouteraient du prestige. Au final, Monte Cryptos Casino vaut une exploration numerique pour les joueurs en quete d’innovation ! Ajoutons que la plateforme est visuellement futuriste, amplifie le plaisir de jouer. Particulierement captivant les evenements communautaires innovants, garantit des transactions fiables.
DГ©couvrir maintenant|
QuantumRiserB7zef
23 Oct 25 at 12:03 am
NHS Viagra cost alternatives: ED medication online UK – NHS Viagra cost alternatives
AnthonySep
23 Oct 25 at 12:03 am
https://factava.com.ua/karta-pervomayska/
JessieVinge
23 Oct 25 at 12:03 am
Diving into Minotaurus token details, the 60% presale allocation ensures fair launch. Vesting up to 14 months with 10% bonuses? That’s holder-friendly. Game’s endless runner vibe is pure fun.
minotaurus token
WilliamPargy
23 Oct 25 at 12:04 am
купить диплом в вольске [url=https://www.rudik-diplom12.ru]https://www.rudik-diplom12.ru[/url] .
Diplomi_fbPi
23 Oct 25 at 12:06 am
перевод английской научно технической литературы [url=https://teletype.in/@alexd78/HN462R01hzy]https://teletype.in/@alexd78/HN462R01hzy[/url] .
Vidi perevodov v buro Perevod i Pravo_lest
23 Oct 25 at 12:08 am
I’m not sure where you are getting your information, but great
topic. I needs to spend some time learning more or understanding more.
Thanks for fantastic info I was looking for this information for
my mission.
Claro Dexeris Análise
23 Oct 25 at 12:13 am
медицинский перевод с английского [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_uaEr
23 Oct 25 at 12:14 am
что такое технические перевод [url=https://dzen.ru/a/aPFFa3ZMdGVq1wVQ/]https://dzen.ru/a/aPFFa3ZMdGVq1wVQ/[/url] .
Tehnicheskii perevod_himl
23 Oct 25 at 12:14 am