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=rudik-diplom9.ru]купить диплом повара[/url] .
Diplomi_aeei
1 Nov 25 at 3:04 am
Sian Weibo — еще одна китайская социальная сеть, изначально запущенная как сайт для
микроблогов, но с тех пор она превратилась в третью по популярности социальную сеть
в Китае.
Узнать больше
1 Nov 25 at 3:05 am
Fascinating blog! Is your theme custom made or did you download
it from somewhere? A theme like yours with a few simple tweeks would really make my blog jump out.
Please let me know where you got your theme. Appreciate it
SmartBit Boost
1 Nov 25 at 3:05 am
thebestvalue – Love how this site delivers both quality and affordability in one place.
Marsha Ohern
1 Nov 25 at 3:06 am
электрокарниз купить в москве [url=http://elektrokarniz777.ru]электрокарниз купить в москве[/url] .
elektrokarniz _btsr
1 Nov 25 at 3:07 am
Me encantó este contenido sobre las casino tragamonedas
más destacadas en Pin-Up México. Me sorprendió ver cómo títulos como Gates of Olympus y Sweet Bonanza siguen dominando entre los jugadores mexicanos.
La explicación de las funciones especiales y versiones demo fue muy clara.
Para quienes buscan conocer los slots más populares de
Pin Up México, este texto es una lectura obligada.
La inclusión de juegos clásicos y modernos muestra la variedad del catálogo de Pin-Up Casino.
No dudes en leer la nota completa y descubrir por qué estos juegos son tendencia en los casinos online de México.
article
1 Nov 25 at 3:07 am
заказать трансляцию конференции [url=http://zakazat-onlayn-translyaciyu4.ru]http://zakazat-onlayn-translyaciyu4.ru[/url] .
zakazat onlain translyaciu_pzSr
1 Nov 25 at 3:08 am
электрические карнизы купить [url=http://elektrokarniz777.ru]http://elektrokarniz777.ru[/url] .
elektrokarniz _jssr
1 Nov 25 at 3:09 am
non-prescription medicines UK: best UK pharmacy websites – non-prescription medicines UK
Johnnyfuede
1 Nov 25 at 3:09 am
бамбуковые электрожалюзи [url=http://www.elektricheskie-zhalyuzi97.ru]http://www.elektricheskie-zhalyuzi97.ru[/url] .
elektricheskie jaluzi_efet
1 Nov 25 at 3:10 am
Если состояние тяжёлое либо есть серьёзные сопутствующие заболевания, оптимален стационар. Здесь доступны расширенная диагностика (ЭКГ, лаборатория, оценка электролитов, функции печени и почек), усиленные схемы инфузии, противорвотная, седативная и кардиопротективная поддержка. Круглосуточный мониторинг позволяет своевременно корректировать терапию, предотвращать обезвоживание и электролитные нарушения. Для пациентов из Реутова организуем аккуратную транспортировку и обратный трансфер после стабилизации.
Подробнее можно узнать тут – [url=https://vyvod-iz-zapoya-reutov7.ru/]vyvod-iz-zapoya-deshev-reutove[/url]
Michaeldoove
1 Nov 25 at 3:10 am
Перед таблицей коротко поясним логику: мы выбираем самый безопасный маршрут именно для вашей ситуации, а при изменении состояния оперативно переключаемся на другой формат без пауз.
Подробнее – https://vyvod-iz-zapoya-pushkino7.ru/vyvedenie-iz-zapoya-v-pushkino/
Davidbok
1 Nov 25 at 3:11 am
https://b.cari.com.my/home.php?mod=space&uid=2506516&do=blog&quickforward=1&id=552550
Lloydinick
1 Nov 25 at 3:12 am
Irish Pharma Finder [url=http://irishpharmafinder.com/#]Irish Pharma Finder[/url] affordable medication Ireland
Hermanengam
1 Nov 25 at 3:12 am
trusted online pharmacy Ireland: irishpharmafinder – buy medicine online legally Ireland
Johnnyfuede
1 Nov 25 at 3:15 am
алюминиевые электрожалюзи [url=http://www.elektricheskie-zhalyuzi97.ru]http://www.elektricheskie-zhalyuzi97.ru[/url] .
elektricheskie jaluzi_lket
1 Nov 25 at 3:15 am
карниз с приводом для штор [url=https://elektrokarniz777.ru]https://elektrokarniz777.ru[/url] .
elektrokarniz _ewsr
1 Nov 25 at 3:17 am
электрожалюзи на заказ [url=www.elektricheskie-zhalyuzi97.ru/]www.elektricheskie-zhalyuzi97.ru/[/url] .
elektricheskie jaluzi_ppet
1 Nov 25 at 3:20 am
Its like you learn my mind! You seem to know so much about
this, like you wrote the book in it or something. I think that you can do with a few % to force the message home
a bit, but other than that, that is fantastic blog.
An excellent read. I’ll definitely be back.
888P
1 Nov 25 at 3:21 am
организация трансляций [url=https://www.zakazat-onlayn-translyaciyu4.ru]организация трансляций[/url] .
zakazat onlain translyaciu_izSr
1 Nov 25 at 3:21 am
online pharmacy reviews and ratings: top rated online pharmacies – SafeMedsGuide
Johnnyfuede
1 Nov 25 at 3:22 am
онлайн трансляции заказать [url=http://zakazat-onlayn-translyaciyu4.ru/]http://zakazat-onlayn-translyaciyu4.ru/[/url] .
zakazat onlain translyaciu_ovSr
1 Nov 25 at 3:23 am
купить оригинальный диплом колледжа [url=https://www.frei-diplom11.ru]https://www.frei-diplom11.ru[/url] .
Diplomi_yzsa
1 Nov 25 at 3:24 am
Does your blog have a contact page? I’m having problems locating it but, I’d like to shoot
you an email. I’ve got some ideas for your blog you might be interested in hearing.
Either way, great site and I look forward to seeing it improve over time.
Baca selengkapnya
1 Nov 25 at 3:24 am
карниз с приводом [url=https://www.elektrokarniz777.ru]https://www.elektrokarniz777.ru[/url] .
elektrokarniz _rzsr
1 Nov 25 at 3:25 am
В Новокузнецке команда «РеабКузбасс» организовала круглосуточный выезд наркологов, что позволяет оказывать помощь даже в сложных ситуациях. Пациенты часто обращаются после многодневного употребления алкоголя, когда нарушен сон, давление нестабильно, а организм истощён. В таких случаях врач выезжает в течение часа, проводит осмотр, определяет степень интоксикации и подбирает оптимальную терапию.
Детальнее – [url=https://vyvod-iz-zapoya-v-novokuzneczke17.ru/]вывод из запоя недорого[/url]
Robertmow
1 Nov 25 at 3:27 am
Своевременное обращение в клинику снижает риск развития алкогольного психоза, судорог и тяжёлых осложнений со стороны сердца и печени.
Выяснить больше – [url=https://vyvod-iz-zapoya-v-ryazani17.ru/]вывод из запоя в стационаре[/url]
PedroAcaph
1 Nov 25 at 3:28 am
карниз для штор с электроприводом [url=https://www.elektrokarniz777.ru]карниз для штор с электроприводом[/url] .
elektrokarniz _mzsr
1 Nov 25 at 3:29 am
жалюзи для пластиковых окон с электроприводом [url=https://elektricheskie-zhalyuzi97.ru/]elektricheskie-zhalyuzi97.ru[/url] .
elektricheskie jaluzi_diet
1 Nov 25 at 3:29 am
организация онлайн трансляции [url=www.zakazat-onlayn-translyaciyu4.ru]организация онлайн трансляции[/url] .
zakazat onlain translyaciu_rnSr
1 Nov 25 at 3:29 am
http://irishpharmafinder.com/# top-rated pharmacies in Ireland
Haroldovaph
1 Nov 25 at 3:30 am
Как работает
Подробнее тут – [url=https://kodirovanie-ot-alkogolizma-vidnoe7.ru/]kodirovanie-ot-alkogolizma-ceny[/url]
RobertMoina
1 Nov 25 at 3:30 am
3 шелкография спб [url=http://www.dzen.ru/a/aP_ExCFsrTEIVLyn]http://www.dzen.ru/a/aP_ExCFsrTEIVLyn[/url] .
Vidi pechati na syvenirnoi prodykcii_piPr
1 Nov 25 at 3:31 am
Hi there are using WordPress for your site platform?
I’m new to the blog world but I’m trying to get started
and set up my own. Do you require any coding expertise
to make your own blog? Any help would be really appreciated!
Trade Edge AI
1 Nov 25 at 3:31 am
Ориентир по времени
Исследовать вопрос подробнее – [url=https://narkolog-na-dom-zhukovskij7.ru/]narkolog-na-dom-kruglosutochno-zhukovskij[/url]
Frankperge
1 Nov 25 at 3:31 am
discount pharmacies in Ireland
Edmundexpon
1 Nov 25 at 3:32 am
организация онлайн трансляций москва [url=https://zakazat-onlayn-translyaciyu4.ru/]zakazat-onlayn-translyaciyu4.ru[/url] .
zakazat onlain translyaciu_auSr
1 Nov 25 at 3:33 am
brightstylecorner – Super easy to explore, everything loads fast and looks fantastic.
Corey Mcgeough
1 Nov 25 at 3:34 am
online pharmacy australia: Aussie Meds Hub – pharmacy online
HaroldSHems
1 Nov 25 at 3:34 am
What we’re covering
• Zelensky in Washington: European leaders will join Ukrainian President Volodymyr Zelensky at the White House, as he meets with US President Donald Trump this afternoon. Trump said Zelensky must agree to some of Russia’s conditions — including that Ukraine cede Crimea and agree never to join NATO — for the war to end.
[url=https://kra-35-at.cc]kra31 at[/url]
• Potential security guarantees: At last week’s summit with Trump, Russian President Vladimir Putin agreed to allow security guarantees for Ukraine and made concessions on “land swaps” as part of a potential peace deal, US envoy Steve Witkoff told CNN. Zelensky suggested that such guarantees would need to be stronger than those that “didn’t work” in the past. Russia has yet to mention such agreements.
[url=https://kraken35-at.com]kra40 cc[/url]
• On the ground: Zelensky condemned Russia’s latest strikes across Ukraine, which killed at least 10 people, saying the Kremlin intends to “humiliate diplomatic efforts” and underscores “why reliable security guarantees are required.”
kra32 at
https://kra39cc.com
JorgeKesia
1 Nov 25 at 3:34 am
электрокарниз купить в москве [url=https://elektrokarniz777.ru/]электрокарниз купить в москве[/url] .
elektrokarniz _hgsr
1 Nov 25 at 3:34 am
бамбуковые электрожалюзи [url=https://elektricheskie-zhalyuzi97.ru/]https://elektricheskie-zhalyuzi97.ru/[/url] .
elektricheskie jaluzi_pyet
1 Nov 25 at 3:35 am
Appreciating the hard work you put into your blog and in depth information you present.
It’s awesome to come across a blog every once in a while
that isn’t the same unwanted rehashed material. Excellent
read! I’ve bookmarked your site and I’m including your RSS feeds to my Google account.
PG88
1 Nov 25 at 3:36 am
Listen up, Singapore parents, maths remɑіns prоbably the extremely essential primary topic,
fostering creativity fߋr issue-resolving foг creative careers.
Anglo-Chinese School (Independent) Junior College ᧐ffers ɑ faith-inspired education tһat
balances intellectual pyrsuits ѡith ethical worths, empowering trainees
tо end up being compassionate worldwide citizens.
Ӏts International Baccalaureate program motivates
critical thinking ɑnd query, supported ƅy wⲟrld-class resources ɑnd dedicated educators.
Trainees master ɑ broad variety ߋf с᧐-curricular activities,
from robotiics to music, building versatility ɑnd imagination. Тhe school’s focus on service knowing instills ɑ sense ⲟf duty and neighborhood engagement from an early
stage. Graduates ɑre wеll-prepared for distinguished universities, Ьring forward a
tradition of quality and stability.
Nanyang Junior College stands out іn championing multilingual proficiency ɑnd cultural
excellence, masterfully weaving tօgether abundant Chinese heritage ԝith contemporary global education tߋ shape confident,
culturally nimble residents ᴡho are poised tⲟ
lead in multicultural contexts. Ꭲhe college’ѕ sophisticated centers, including specialized STEM labs, performing
arts theaters, аnd language immersion centers, assistance robust programs
іn science, innovation, engineering, mathematics, arts, ɑnd humanities tһat encourage
development, crucial thinking, and creative expression. Ιn a vibrant
and inclusive community, trainees engage іn leadership
chances ѕuch as trainee governance roles аnd global exchange programs ѡith partner
organizations abroad, whіch expand their perspectives and
develop іmportant international proficiencies.
Ƭһe emphasis on core worths like stability ɑnd
resilience іs incorporated into everу ɗay life tһrough mentorship schemes, community service initiatives,
аnd health care tһat foster emotional intelligence and individual development.
Graduates ⲟf Nanyang Junior College regularly stand οut іn admissions
tօ top-tier universities, supporting a prouⅾ tradition of
impressive accomplishments, cultural gratitude, аnd ɑ deep-seated passion f᧐r constant self-improvement.
Folks, fearful ߋf losing approach engaged lah,
strong primary maths results in improved STEM grasp ɑnd tech dreams.
Folks, fearful of losing mode engaged lah, robust primary math leads іn bеtter STEM comprehension аnd engineering dreams.
Hey hey, Singapore moms аnd dads, maths proves pгobably the highly essential primary discipline, promoting
innovation іn pгoblem-solving tߋ creative jobs.
Kiasu study apps fⲟr Math make Ꭺ-level prep efficient.
Wah lao, reɡardless though iinstitution іs fancy,
math is the maке-or-break topic to cultivates poise ѡith figures.
Тake a ⅼߋⲟk аt my web-site Singapore Sports School JC
Singapore Sports School JC
1 Nov 25 at 3:36 am
Somebody essentially assist to make severely articles I’d state.
This is the very first time I frequented your website page and to this point?
I amazed with the analysis you made to make this actual publish extraordinary.
Great activity!
Immediate App Ai
1 Nov 25 at 3:37 am
услуги онлайн трансляции [url=https://zakazat-onlayn-translyaciyu4.ru]https://zakazat-onlayn-translyaciyu4.ru[/url] .
zakazat onlain translyaciu_enSr
1 Nov 25 at 3:38 am
findbetteropportunities – I like how every post gives me a reason to keep growing.
Normand Tuchy
1 Nov 25 at 3:38 am
Very nice blog post. I definitely love this website.
Keep writing!
kmspico 11 activator 2023
1 Nov 25 at 3:39 am
trusted online pharmacy UK: affordable medications UK – trusted online pharmacy UK
HaroldSHems
1 Nov 25 at 3:39 am
everydaychoicehub – The design is clean and the tone is friendly, keeps me coming back.
Darcey Fonteno
1 Nov 25 at 3:40 am