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!
бонусный счет 1win [url=1win12011.ru]1win12011.ru[/url]
1win_kvOl
14 Sep 25 at 10:41 am
It’s amazing designed for me to have a website, which is useful for my knowledge. thanks admin
Cleobetra Casino
ShaneDrync
14 Sep 25 at 10:42 am
Hi there, just wanted to mention, I loved this post. It was funny.
Keep on posting!
кейсы кс
14 Sep 25 at 10:48 am
Verry good post. I’m going through a few of
these issues as well..
Finn
14 Sep 25 at 10:56 am
buying detrol
order detrol online
14 Sep 25 at 11:01 am
что будет если купить диплом о высшем образовании с занесением в реестр [url=http://arus-diplom33.ru/]что будет если купить диплом о высшем образовании с занесением в реестр[/url] .
Diplomi_dkSa
14 Sep 25 at 11:02 am
Узнайте все подробности о дилере Автомикс — официальном дилере Honda, техническая поддержка, ремонт кузова и фирменные комплектующие! Посетите [url=https://avtomiks-smolensk.ru/]https://avtomiks-smolensk.ru/[/url] и ознакомьтесь модельный ряд. Хотите комфорт и надёжность — дилер предлагает пробную поездку, фирменное обслуживание, брендовые решения, а также техническое обслуживание, послегарантийный ремонт и гибкие предложения. Ищете Honda — здесь найдёте лучшие варианты и профессиональную поддержку.
Spravkimxa
14 Sep 25 at 11:04 am
how can i get cheap accupril online
buy cheap accupril pills
14 Sep 25 at 11:08 am
1вин мобильная версия [url=http://1win12011.ru]http://1win12011.ru[/url]
1win_maOl
14 Sep 25 at 11:14 am
1win ракета [url=http://1win12010.ru/]1win ракета[/url]
1win_qfEl
14 Sep 25 at 11:16 am
indian pharmacy online [url=http://curabharatusa.com/#]pharmacy india[/url] online medicine india
Michaelphype
14 Sep 25 at 11:16 am
Thanks for a marvelous posting! I really enjoyed
reading it, you’re a great author. I will make certain to bookmark your blog and will eventually
come back in the future. I want to encourage one to continue your great posts,
have a nice evening!
IDD file application
14 Sep 25 at 11:18 am
indian chemist: india pharmacy – adderall online india
Teddyroowl
14 Sep 25 at 11:19 am
как использовать бонусный счет на 1win [url=https://www.1win12011.ru]https://www.1win12011.ru[/url]
1win_sbOl
14 Sep 25 at 11:20 am
купить диплом легальный о высшем образовании [url=https://arus-diplom33.ru]https://arus-diplom33.ru[/url] .
Diplomi_rdSa
14 Sep 25 at 11:24 am
мостбет казино зеркало [url=https://mostbet12013.ru]https://mostbet12013.ru[/url]
mostbet_yika
14 Sep 25 at 11:26 am
Good replies in return of this matter with real arguments and describing everything about that.
article source
14 Sep 25 at 11:29 am
kra ссылка kraken onion, kraken onion ссылка, kraken onion зеркала, kraken рабочая ссылка onion, сайт kraken onion, kraken darknet, kraken darknet market, kraken darknet ссылка, сайт kraken darknet, kraken актуальные ссылки, кракен ссылка kraken, kraken официальные ссылки, kraken ссылка тор, kraken ссылка зеркало, kraken ссылка на сайт, kraken онион, kraken онион тор, кракен онион, кракен онион тор, кракен онион зеркало, кракен даркнет маркет, кракен darknet, кракен onion, кракен ссылка onion, кракен onion сайт, kra ссылка, kraken сайт, kraken актуальные ссылки, kraken зеркало, kraken ссылка зеркало, kraken зеркало рабочее, актуальные зеркала kraken, kraken сайт зеркала, kraken маркетплейс зеркало, кракен ссылка, кракен даркнет
RichardPep
14 Sep 25 at 11:29 am
купить диплом о среднем специальном образовании с занесением в реестр [url=www.arus-diplom33.ru]купить диплом о среднем специальном образовании с занесением в реестр[/url] .
Diplomi_kcSa
14 Sep 25 at 11:30 am
купить настоящий диплом о высшем образовании [url=www.educ-ua18.ru]купить настоящий диплом о высшем образовании[/url] .
Diplomi_kmPi
14 Sep 25 at 11:33 am
Hello there! This post could not be written much better!
Looking through this article reminds me of my previous roommate!
He constantly kept talking about this. I most certainly will forward this post to
him. Fairly certain he will have a good read. Thanks for sharing!
Immediate Bitwave
14 Sep 25 at 11:35 am
At this moment I am ready to do my breakfast, after having my breakfast coming yet again to read further
news.
bk888
14 Sep 25 at 11:36 am
https://connerwwob601.wpsuo.com/controles-antidoping-en-empresas-chilenas-derechos-y-obligaciones
Gestionar un test antidoping puede ser un momento critico. Por eso, se desarrollo un metodo de enmascaramiento con respaldo internacional.
Su formula premium combina carbohidratos, lo que estimula tu organismo y disimula temporalmente los rastros de THC. El resultado: una muestra limpia, lista para entregar tranquilidad.
Lo mas destacado es su capacidad inmediata de respuesta. A diferencia de metodos caseros, no promete resultados permanentes, sino una solucion temporal que responde en el momento justo.
Miles de trabajadores ya han comprobado su rapidez. Testimonios reales mencionan paquetes 100% confidenciales.
Si necesitas asegurar tu resultado, esta solucion te ofrece seguridad.
JuniorShido
14 Sep 25 at 11:37 am
промокод для 1win [url=https://1win12010.ru]https://1win12010.ru[/url]
1win_ocEl
14 Sep 25 at 11:37 am
Mijn belevenissen hebben me van de virtuele slots naar de fysieke pokertafels gebracht.
Ik fuseer het beste van beide werelden in mijn analyses.
Lucille
14 Sep 25 at 11:43 am
speed n cash лайфак [url=1win12010.ru]1win12010.ru[/url]
1win_fvEl
14 Sep 25 at 11:47 am
mostbet official [url=http://mostbet12012.ru]http://mostbet12012.ru[/url]
mostbet_ciSl
14 Sep 25 at 11:49 am
Medicine information for patients. Drug Class.
order cheap nortriptyline without insurance
Everything about medication. Get now.
order cheap nortriptyline without insurance
14 Sep 25 at 11:50 am
купить диплом магистра дешево [url=http://educ-ua1.ru/]купить диплом магистра дешево[/url] .
Diplomi_zkei
14 Sep 25 at 11:51 am
Вывод из запоя — это управляемая медицинская процедура, а не «волшебная капля» или крепкий чай с рассолом. «Формула Трезвости» организует помощь в Ногинске круглосуточно: выезд врача на дом или приём в стационаре, детоксикация с мониторингом, мягкая коррекция сна и тревоги, подробный план на первые 48–72 часа. Мы действуем безопасно, конфиденциально и без «мелкого шрифта» — объясняем, что и зачем делаем, согласовываем схему и фиксируем смету до начала процедур.
Выяснить больше – [url=https://vyvod-iz-zapoya-noginsk7.ru/]вывод из запоя на дому[/url]
Richardbug
14 Sep 25 at 11:54 am
https://bpr-work.ru/
Charlesbor
14 Sep 25 at 12:00 pm
купить проведенный диплом о высшем образовании [url=arus-diplom33.ru]купить проведенный диплом о высшем образовании[/url] .
Diplomi_ekSa
14 Sep 25 at 12:01 pm
Услуги платной наркологии, это необходимый шаг в процессе восстановления. В специальной наркологической клинике, такой как vivod-iz-zapoya-vladimir018.ru, пациентам предоставляется профессиональная помощь, включая помощь при наркомании и алкоголизме. Программа восстановления включает детоксикационные процедуры и психологическую поддержку. Консультация нарколога позволяет создать персонализированную программу к конкретной ситуации. Клиники предлагают анонимную помощь и помощь в кризисных ситуациях. Поддержка родственников также имеет огромное значение. Групповые занятия помогают делиться впечатлениями, а медицинская поддержка обеспечивает безопасность лечения. Коммерческие услуги позволяют достигать лучших результатов и внимание специалистов, что способствует эффективному выздоровлению.
alkogolizmvladimirNeT
14 Sep 25 at 12:10 pm
В «РостовМедЦентре» лечение начинается с подробной оценки факторов риска и мотивации. Клиническая команда анализирует стаж употребления, тип вещества, эпизоды срывов, соматический фон, лекарства, которые пациент принимает постоянно, и уровень социальной поддержки. Уже на первой встрече составляется «дорожная карта» на ближайшие 72 часа: диагностический минимум, объём медицинских вмешательств, пространство для психологической работы и точки контроля. Безопасность — не абстракция: скорости инфузий рассчитываются в инфузомате, седацию подбирают по шкалам тревоги и с обязательным контролем сатурации, а лекарственные взаимодействия сверяет клинический фармаколог. Пациент получает прозрачные цели на день, на неделю и на месяц — без обещаний мгновенных чудес и без стигмы.
Выяснить больше – https://narkologicheskaya-klinika-rostov-na-donu14.ru/narkolog-rostov-na-donu/
Jackiemoips
14 Sep 25 at 12:16 pm
купить диплом специалиста недорого [url=http://educ-ua18.ru/]купить диплом специалиста недорого[/url] .
Diplomi_bcPi
14 Sep 25 at 12:19 pm
Анонимность — важнейшее условие обращения за помощью. В клинике действуют не декларации, а конкретные технологические и организационные меры, которые защищают пациента и его близких от стигмы и лишнего обсуждения.
Исследовать вопрос подробнее – [url=https://narkologicheskaya-klinika-rostov-na-donu14.ru/]частная наркологическая клиника[/url]
Jackiemoips
14 Sep 25 at 12:19 pm
A motivating discussion is worth comment. I do believe that you ought
to publish more about this topic, it may not be a
taboo matter but typically people do not discuss these issues.
To the next! Many thanks!!
https://github.com/valyse-executors/valyse
14 Sep 25 at 12:23 pm
Everything is very open with a really clear explanation of the challenges.
It was really informative. Your website is extremely helpful.
Many thanks for sharing!
My web-site: Superman Pills Online Canada
Superman Pills Online Canada
14 Sep 25 at 12:25 pm
After looking into a number of the articles on your web
site, I seriously like your way of blogging. I saved as a
favorite it to my bookmark webpage list and will be checking back in the near future.
Please check out my web site too and let me know how you feel.
Here is my blog post Buy Superman Pills Canada
Buy Superman Pills Canada
14 Sep 25 at 12:26 pm
мастбет [url=https://www.mostbet12011.ru]https://www.mostbet12011.ru[/url]
mostbet_wtOt
14 Sep 25 at 12:26 pm
Этап
Разобраться лучше – [url=https://vyvod-iz-zapoya-noginsk7.ru/]vrach-vyvod-iz-zapoya[/url]
Richardbug
14 Sep 25 at 12:26 pm
мостеб [url=http://mostbet12012.ru]http://mostbet12012.ru[/url]
mostbet_kkSl
14 Sep 25 at 12:27 pm
купить диплом в одессе [url=https://www.educ-ua1.ru]купить диплом в одессе[/url] .
Diplomi_yyei
14 Sep 25 at 12:28 pm
Sou louco pela vibe de AFun Casino, oferece uma aventura de cassino que gira como um carrossel enlouquecido. Tem uma enxurrada de jogos de cassino irados, oferecendo sessoes de cassino ao vivo que pulsam como batidas. A equipe do cassino entrega um atendimento que e puro carnaval, dando solucoes na hora e com precisao. Os ganhos do cassino chegam voando como serpentinas, mesmo assim mais giros gratis no cassino seria uma loucura. No fim das contas, AFun Casino e um cassino online que e uma explosao de alegria para os viciados em emocoes de cassino! E mais o design do cassino e um espetaculo visual de purpurina, eleva a imersao no cassino ao ritmo de uma festa.
codigo indicacao afun|
zappyglitterkoala8zef
14 Sep 25 at 12:28 pm
Pills information for patients. Effects of Drug Abuse.
where to get atomoxetine without rx
All what you want to know about drug. Read now.
where to get atomoxetine without rx
14 Sep 25 at 12:30 pm
легально купить диплом о [url=https://arus-diplom33.ru/]легально купить диплом о[/url] .
Diplomi_ytSa
14 Sep 25 at 12:31 pm
Nice post. I learn something new and challenging on websites I stumbleupon everyday.
It will always be exciting to read through articles from other writers and use a little something from their sites.
Unavex Platform
14 Sep 25 at 12:32 pm
бк мост бет [url=mostbet12011.ru]mostbet12011.ru[/url]
mostbet_lyOt
14 Sep 25 at 12:34 pm
Sou louco pela energia de BetorSpin Casino, oferece uma aventura de cassino que orbita como um cometa reluzente. A selecao de titulos do cassino e um buraco negro de diversao, com slots de cassino tematicos de espaco sideral. O suporte do cassino ta sempre na ativa 24/7, com uma ajuda que reluz como uma aurora boreal. Os saques no cassino sao velozes como uma viagem interestelar, porem as ofertas do cassino podiam ser mais generosas. No geral, BetorSpin Casino garante uma diversao de cassino que e uma supernova para os amantes de cassinos online! De lambuja a plataforma do cassino brilha com um visual que e puro cosmos, faz voce querer voltar ao cassino como um cometa em orbita.
betorspin sports betting|
glimmerfizzytoad7zef
14 Sep 25 at 12:35 pm
What’s up Dear, are you in fact visiting this website on a regular basis, if so afterward you will definitely take fastidious experience.
Almax Capital
14 Sep 25 at 12:37 pm