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!
www pharmacyonline: TrueMeds Pharmacy – wholesale pharmacy
Frankelova
3 Sep 25 at 3:58 am
кракен онион тор
RichardPep
3 Sep 25 at 4:02 am
купить диплом с реестром спб [url=www.arus-diplom34.ru]купить диплом с реестром спб[/url] .
Diplomi_xher
3 Sep 25 at 4:03 am
Многие недооценивают последствия запоя, особенно если речь идёт о человеке, который ранее не испытывал серьёзных проблем со здоровьем. Однако даже несколько дней непрерывного употребления алкоголя способны вызвать тяжёлые системные сбои. Нарушается кислотно-щелочной и водно-солевой баланс, кровь становится густой, затрудняется работа сердца. Печень перестаёт эффективно обезвреживать токсины, и продукты распада этанола поступают в мозг, вызывая когнитивные и поведенческие нарушения.
Детальнее – [url=https://kapelnica-ot-zapoya-moskva2.ru/]врача капельницу от запоя[/url]
ElbertLooda
3 Sep 25 at 4:03 am
где можно купить диплом [url=https://www.educ-ua4.ru]где можно купить диплом[/url] .
Diplomi_xxPl
3 Sep 25 at 4:04 am
мос бет [url=http://mostbet4126.ru/]http://mostbet4126.ru/[/url]
mostbet_kg_vakn
3 Sep 25 at 4:06 am
mostbet sikachat [url=https://mostbet4125.ru]https://mostbet4125.ru[/url]
mostbet_kg_dvml
3 Sep 25 at 4:06 am
Hey! Do you know if they make any plugins to protect against
hackers? I’m kinda paranoid about losing everything
I’ve worked hard on. Any recommendations?
Dewayne
3 Sep 25 at 4:10 am
купить кашпо для цветов напольное высокое пластиковое [url=http://kashpo-napolnoe-krasnodar.ru]купить кашпо для цветов напольное высокое пластиковое[/url] .
kashpo napolnoe _anel
3 Sep 25 at 4:16 am
Кажется, вашему дому не хватает уюта и живого дыхания природы? В «Цветущем Доме» вы найдете идеи и простые решения для комнатного озеленения: от суккулентов до орхидей, с понятными советами по уходу. Ищете королевская бегония? Подробные гиды, свежие подборки и проверенные рекомендации ждут вас на cvetochnik-doma.ru С нашим гидом вы без труда создадите зеленый уголок: подскажем, что выбрать, как ухаживать и с чего начать, чтобы растения радовали весь год.
datobser
3 Sep 25 at 4:18 am
I have fun with, cause I found just what I was looking for.
You have ended my 4 day lengthy hunt! God Bless
you man. Have a nice day. Bye
check
3 Sep 25 at 4:18 am
купить диплом с реестром красноярск [url=http://arus-diplom34.ru]купить диплом с реестром красноярск[/url] .
Diplomi_zqer
3 Sep 25 at 4:22 am
Greetings from Florida! I’m bored to death at work
so I decided to check out your website on my iphone during lunch break.
I love the info you provide here and can’t wait to take
a look when I get home. I’m amazed at how quick your blog
loaded on my cell phone .. I’m not even using WIFI, just 3G
.. Anyways, excellent blog!
Lexiron Platform
3 Sep 25 at 4:23 am
купить диплом об окончании техникума [url=www.educ-ua4.ru/]купить диплом об окончании техникума[/url] .
Diplomi_dePl
3 Sep 25 at 4:25 am
I was able to find good info from your articles.
Buy Amazon Prime Accounts
3 Sep 25 at 4:27 am
Apple Crush Game KZ
Darwinlix
3 Sep 25 at 4:27 am
Магазин тут! Отзывы, Качество. kokain gash mefedron alfa-pvp
Jessiereimb
3 Sep 25 at 4:29 am
kraken onion ссылка
RichardPep
3 Sep 25 at 4:30 am
https://brooksjrsr891.raidersfanteamshop.com/5-red-flags-to-watch-out-for-when-hiring-a-countertop-company
It’s every homeowner’s wish of having a high-quality countertop that adds value their kitchen or bathroom.
Did you know that in this year, only around 2,000 companies earned a spot in the Top Countertop Contractors Ranking out of over ten thousand evaluated? That’s because at we set a very high bar.
Our ranking is independent, constantly refreshed, and built on dozens of criteria. These include feedback from Google, Yelp, and other platforms, pricing, responsiveness, and results. On top of that, we conduct countless phone calls and 2,000 estimate requests through our mystery shopper program.
The result is a trusted guide that benefits both clients and contractors. Homeowners get a reliable way to choose contractors, while listed companies gain prestige, digital exposure, and even new business opportunities.
The Top 500 Awards spotlight categories like Best Old Contractors, Emerging Leaders, and Most Affordable Contractors. Winning one of these honors means a company has achieved elite credibility in the industry.
If you’re looking for a countertop contractor—or your company wants to stand out—this site is where trust meets opportunity.
JuniorShido
3 Sep 25 at 4:30 am
купить аттестат о среднем [url=https://educ-ua4.ru/]купить аттестат о среднем[/url] .
Diplomi_phPl
3 Sep 25 at 4:30 am
Миссия нашего учреждения заключается в комплексной помощи людям, которые столкнулись с проблемами зависимости. Основные цели нашего центра включают:
Детальнее – http://alko-lechebnica.ru
Georgecem
3 Sep 25 at 4:30 am
Hello! This post could not be written any better!
Reading this post reminds me of my old room mate! He always kept talking about
this. I will forward this write-up to him. Fairly certain he will have a good read.
Thanks for sharing!
git.akarpov.ru
3 Sep 25 at 4:31 am
букмекерские конторы кыргызстана [url=https://mostbet4123.ru/]https://mostbet4123.ru/[/url]
mostbet_gyKa
3 Sep 25 at 4:36 am
https://p-shpora.ru
Garthtoild
3 Sep 25 at 4:37 am
как зарегистрироваться в мостбет [url=https://mostbet4119.ru]как зарегистрироваться в мостбет[/url]
mostbet_qoEt
3 Sep 25 at 4:38 am
https://vitalcorepharm.com/# VitalCore Pharmacy
Danieldix
3 Sep 25 at 4:40 am
Вывод из запоя в Химках возможен без госпитализации — достаточно обратиться в Stop Alko, чтобы получить помощь на дому.
Подробнее можно узнать тут – [url=https://vyvod-iz-zapoya-himki11.ru/]скорая вывод из запоя[/url]
Willieswefs
3 Sep 25 at 4:40 am
купить аттестат 11 класс 2014 [url=www.arus-diplom21.ru]купить аттестат 11 класс 2014[/url] .
Diplomi_ilPr
3 Sep 25 at 4:40 am
купить аттестат за 11 класс в мурманске [url=arus-diplom22.ru]купить аттестат за 11 класс в мурманске[/url] .
Diplomi_psKt
3 Sep 25 at 4:42 am
мостбет войти [url=www.mostbet4122.ru]www.mostbet4122.ru[/url]
mostbet_odpl
3 Sep 25 at 4:43 am
Excellent beat ! I would like to apprentice while you amend
your site, how can i subscribe for a blog site?
The account helped me a acceptable deal. I had been tiny bit acquainted of this your broadcast offered bright clear idea
emergency roofers in Lehigh Valley
3 Sep 25 at 4:45 am
Medication information for patients. What side effects?
can i get tadacip tablets
Actual information about medication. Read information now.
can i get tadacip tablets
3 Sep 25 at 4:46 am
букмекерская контора теннесси скачать [url=mostbet4124.ru]mostbet4124.ru[/url]
mostbet_cjsr
3 Sep 25 at 4:48 am
האומץ שלך לא ידע גבולות. חיבקת אותי ואת החברה שלי, נישקת את שניהם. ואז לקח את הידיים שלנו והניח הפטמות התנפחו בבוגדנות ובלטו ללא בושה. – בסדר. ידו שכבה לי את הערווה, ופרשה את הכניסה, מיהרה דירות דיסקרטיות חיפה
Danielarins
3 Sep 25 at 4:49 am
Great post. I used to be checking constantly this weblog
and I am inspired! Very helpful information specifically the closing phase 🙂 I deal
with such info a lot. I used to be seeking this certain info for a very
long time. Thank you and best of luck.
View more
3 Sep 25 at 4:53 am
купить аттестаты за 11 классов в микуне [url=www.arus-diplom24.ru]купить аттестаты за 11 классов в микуне[/url] .
Diplomi_dksa
3 Sep 25 at 4:55 am
https://open.substack.com/pub/celenaslau/p/why-local-rankings-matter-finding?r=6d5s9z&utm_campaign=post&utm_medium=web&showWelcomeOnShare=true
Did you know that in this year, 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 transparent, kept current, and built on dozens of criteria. These include ratings from Google, Yelp, and other platforms, affordability, customer service, and craftsmanship. On top of that, we conduct 5,000+ phone calls and multiple estimate requests through our mystery shopper program.
The result is a trusted guide that benefits both property owners and installation companies. Homeowners get a safe way to choose contractors, while listed companies gain recognition, SEO visibility, and even more inquiries.
The Top 500 Awards spotlight categories like Best Old Contractors, Best Young Companies, and Most Affordable Contractors. Winning one of these honors means a company has achieved elite credibility in the industry.
If you’re searching for a countertop contractor—or your company wants to stand out—this site is where trust meets visibility.
JuniorShido
3 Sep 25 at 4:57 am
сайт kraken darknet
RichardPep
3 Sep 25 at 4:57 am
kraken актуальные ссылки
RichardPep
3 Sep 25 at 4:59 am
купить диплом специалиста недорого [url=www.educ-ua4.ru]купить диплом специалиста недорого[/url] .
Diplomi_tfPl
3 Sep 25 at 5:01 am
https://vk.com/foka_doka
CoreyThype
3 Sep 25 at 5:10 am
I used to be able to find good advice from your content.
vape flavoured
3 Sep 25 at 5:10 am
купить диплом реестр [url=www.arus-diplom31.ru]купить диплом реестр[/url] .
Diplomi_dvpl
3 Sep 25 at 5:10 am
kraken сайт зеркала
RichardPep
3 Sep 25 at 5:13 am
Very energetic article, I liked that bit.
Will there be a part 2?
MaxgenBit
3 Sep 25 at 5:16 am
hey there and thank you for your information – I’ve definitely picked up something new from right here.
I did however expertise several technical points using this site,
as I experienced to reload the site lots of times previous to I could get it to load properly.
I had been wondering if your web hosting is OK? Not that I am
complaining, but sluggish loading instances times will often affect your placement in google
and could damage your high-quality score if ads and marketing with Adwords.
Well I’m adding this RSS to my e-mail and can look out for much more of your respective intriguing content.
Ensure that you update this again very soon.
https://raspithekgit.srv64.de/guadalupevarne/guadalupe1994/wiki/Clean-Label-Metabolic-Supplements:-The-Key-to-a-Healthy-Lifestyle
3 Sep 25 at 5:16 am
купить аттестат за 11 класс 2000 года [url=http://www.arus-diplom24.ru]http://www.arus-diplom24.ru[/url] .
Diplomi_ursa
3 Sep 25 at 5:17 am
What’s up to every one, the contents present at this site are really remarkable for people experience, well, keep up the good work fellows.
Hildred
3 Sep 25 at 5:19 am
купить диплом в николаеве [url=www.educ-ua4.ru]купить диплом в николаеве[/url] .
Diplomi_ksPl
3 Sep 25 at 5:20 am
https://olimpstom.ru
Garthtoild
3 Sep 25 at 5:21 am