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!
Hmm is anyone else experiencing problems with the images on this blog loading?
I’m trying to determine if its a problem on my
end or if it’s the blog. Any suggestions would be greatly appreciated.
toket
30 Aug 25 at 6:11 pm
Looking for a sports betting site in Nigeria? Visit https://nairabet-play.com/ and check out NairaBet – where you will find reliable betting services and exciting offers. Find out more on the site – how to play, how to deposit and withdraw money and other useful information.
MedupeAgrig
30 Aug 25 at 6:12 pm
Казино Pokerdom
RichardKap
30 Aug 25 at 6:13 pm
диплом высшего образования проведенный купить [url=https://arus-diplom33.ru/]диплом высшего образования проведенный купить[/url] .
Diplomi_oaSa
30 Aug 25 at 6:13 pm
preman69: preman69 slot – preman69 login
LouisJoync
30 Aug 25 at 6:14 pm
Hi there, There’s no doubt that your web site might be
having browser compatibility problems. When I look at your web
site in Safari, it looks fine however when opening in IE, it’s got some overlapping issues.
I merely wanted to give you a quick heads
up! Aside from that, excellent blog!
https://git.malls.iformall.com/
30 Aug 25 at 6:24 pm
An impressive share! I’ve just forwarded this onto a friend who
was conducting a little homework on this. And he in fact bought me breakfast simply because I discovered
it for him… lol. So allow me to reword this….
Thank YOU for the meal!! But yeah, thanks for spending time to talk about this topic here on your blog.
Major Model Agência de Modelos
30 Aug 25 at 6:25 pm
The Pineal Guardian really caught my attention – I like how it’s designed to support pineal gland health and overall mental
clarity. A lot of people overlook this aspect of wellness, so it’s refreshing to see a supplement that focuses
on balance, sleep quality, and higher focus. Definitely seems worth exploring for those interested
in natural brain and body support.
The Pineal Guardian
30 Aug 25 at 6:26 pm
Запой — это опасное состояние, при котором организм человека подвергается сильной алкогольной интоксикации, а внутренние органы, такие как печень, сердце и почки, начинают работать в аварийном режиме. В такой момент самостоятельное лечение становится невозможным, и необходима оперативная помощь специалистов. Наркологическая клиника «Детоксика» в Сочи предлагает комплексный вывод из запоя с использованием современных методов терапии и индивидуального подхода, что позволяет быстро восстановить здоровье пациента и предотвратить серьезные осложнения.
Получить дополнительные сведения – [url=https://vyvod-iz-zapoya-sochi7.ru/]нарколог на дом вывод из запоя[/url]
JimmyOmify
30 Aug 25 at 6:26 pm
Luxury1288
Luxury1288
30 Aug 25 at 6:28 pm
купить медицинский диплом с занесением в реестр [url=http://arus-diplom33.ru/]купить медицинский диплом с занесением в реестр[/url] .
Diplomi_juSa
30 Aug 25 at 6:31 pm
Приобрести диплом ВУЗа!
Мы предлагаембыстро и выгодно приобрести диплом, который выполняется на оригинальной бумаге и заверен печатями, штампами, подписями должностных лиц. Данный документ способен пройти лубую проверку, даже с применением специального оборудования. Достигайте свои цели быстро и просто с нашими дипломами- [url=http://ageon.ph/author/bessierason753/]ageon.ph/author/bessierason753[/url]
Jariorvaw
30 Aug 25 at 6:32 pm
https://form.jotform.com/252386323055051
DavidVef
30 Aug 25 at 6:33 pm
Вавада Казино зеркало
AntioneHaG
30 Aug 25 at 6:34 pm
можно ли купить диплом о высшем образовании [url=http://educ-ua2.ru]можно ли купить диплом о высшем образовании[/url] .
Diplomi_voOt
30 Aug 25 at 6:36 pm
купить аттестат 11 классов ставрополь [url=arus-diplom25.ru]купить аттестат 11 классов ставрополь[/url] .
Diplomi_jnot
30 Aug 25 at 6:40 pm
Запускаете новый проект и хотите сэкономить время на расчетах и гипотезах? Мы подготовили готовые бизнес-планы с расчетами, таблицами и прогнозами по разным нишам — от кафе и автосервиса до медицины и фермерства. Ищете бизнес план компьютерного клуба? Ознакомьтесь с ассортиментом и выберите формат под вашу цель: financial-project.ru Сразу после покупки вы рассчитаете бюджет, проверите окупаемость и убедительно представите проект партнерам или инвесторам.
Qilyrepich
30 Aug 25 at 6:46 pm
купить аттестат 11 класс красноярск [url=https://arus-diplom24.ru/]купить аттестат 11 класс красноярск[/url] .
Diplomi_zsKn
30 Aug 25 at 6:47 pm
Приобрести диплом ВУЗа!
Наши специалисты предлагаютвыгодно заказать диплом, который выполнен на бланке ГОЗНАКа и заверен мокрыми печатями, штампами, подписями должностных лиц. Документ способен пройти любые проверки, даже с использованием профессионального оборудования. Решайте свои задачи быстро с нашими дипломами- [url=http://krasnozovodsk.flybb.ru/viewtopic.php?f=2&t=693/]krasnozovodsk.flybb.ru/viewtopic.php?f=2&t=693[/url]
Jariorcvr
30 Aug 25 at 6:49 pm
ростест сертификат
RobertKEd
30 Aug 25 at 6:54 pm
напольный горшок для цветов высокий [url=www.kashpo-napolnoe-moskva.ru/]напольный горшок для цветов высокий[/url] .
kashpo napolnoe _sdOi
30 Aug 25 at 6:55 pm
https://www.metooo.io/u/68b19948544a26303c071235
DavidVef
30 Aug 25 at 6:55 pm
Book of Ra Deluxe slot online Italia: recensioni Book of Ra Deluxe slot – giri gratis Book of Ra Deluxe
Ramonatowl
30 Aug 25 at 6:55 pm
Depending on the instructions, potatoes nebrdecor.com are kept in the solution before planting or it is poured into the soil.
Cesargef
30 Aug 25 at 6:56 pm
Lo strumento offre un’ampia gamma di opzioni di personalizzazione
per le didascalie, tra cui font, colori e posizionamento.
zeemo
30 Aug 25 at 6:57 pm
Ищете крыса с большими ушами? Pet4home.ru здесь вы найдете полезные советы, обзоры пород, лайфхаки по уходу и подбору кормов, чтобы ваш хвостик был здоров и счастлив. Мы объединяем проверенные материалы, помогаем новичкам и становимся опорой для опытных владельцев. Понятная навигация, экспертные советы и частые обновления — заходите, вдохновляйтесь идеями, подбирайте аксессуары и уверенно заботьтесь о своих любимцах.
satewDrids
30 Aug 25 at 6:59 pm
Казино ПинАп слот Admiral X Fruit Machine
Jorgegrect
30 Aug 25 at 7:01 pm
I have read so many articles or reviews about the blogger lovers however this
piece of writing is actually a pleasant piece of writing, keep it up.
Belvars Platform
30 Aug 25 at 7:02 pm
купить в сургуте аттестат за 11 класс [url=https://arus-diplom25.ru/]купить в сургуте аттестат за 11 класс[/url] .
Diplomi_nuot
30 Aug 25 at 7:03 pm
Unquestionably believe that which you said. Your favorite justification appeared
to be on the net the easiest thing to be aware of. I say to you,
I certainly get irked while people think about worries that they
plainly don’t know about. You managed to hit the nail upon the top as well as defined out the whole thing without having side effect , people can take a signal.
Will likely be back to get more. Thanks
git.fishze.com
30 Aug 25 at 7:03 pm
Just want to say your article is as astonishing. The clarity in your post
is simply nice and i could assume you’re an expert on this
subject. Well with your permission allow me to grab your RSS feed to keep updated with forthcoming post.
Thanks a million and please keep up the gratifying work.
https://datahktercepat.com/
Data Hk 2024
30 Aug 25 at 7:05 pm
купить проведенный аттестат за 11 [url=http://arus-diplom24.ru]купить проведенный аттестат за 11[/url] .
Diplomi_bbKn
30 Aug 25 at 7:09 pm
Например, если речь идет о выводе из запоя, врач проведет тщательное обследование пациента, чтобы определить общее состояние здоровья и наличие возможных осложнений. На основе диагностики будет назначена инфузионная терапия, которая включает введение растворов, витаминов и препаратов для снятия абстиненции.
Узнать больше – [url=https://narcolog-na-dom-v-krasnoyarske55.ru/]выезд нарколога на дом в красноярске[/url]
CurtisUsalk
30 Aug 25 at 7:09 pm
Каждый день запоя увеличивает риск для жизни. Не рискуйте — специалисты в Самаре приедут на дом и окажут экстренную помощь. Без боли, стресса и ожидания.
Получить дополнительную информацию – [url=https://vyvod-iz-zapoya-v-stacionare-samara16.ru/]срочный вывод из запоя в самаре[/url]
Pablotug
30 Aug 25 at 7:11 pm
купить диплом о среднем профессиональном образовании с занесением в реестр [url=http://arus-diplom32.ru]купить диплом о среднем профессиональном образовании с занесением в реестр[/url] .
Diplomi_yfpi
30 Aug 25 at 7:13 pm
If some one wants to be updated with most recent technologies after that
he must be pay a quick visit this site and be up to date
daily.
seo toronto expert
30 Aug 25 at 7:15 pm
В Самаре решение есть — наркологическая клиника. Здесь помогают людям выйти из запоя без страха и осуждения. Всё анонимно, грамотно и с заботой о каждом пациенте.
Углубиться в тему – [url=https://vyvod-iz-zapoya-v-stacionare-samara15.ru/]вывод из запоя круглосуточно в самаре[/url]
Michaelamoma
30 Aug 25 at 7:17 pm
https://bio.site/nihpahug
DavidVef
30 Aug 25 at 7:17 pm
Агентство Digital-рекламы в Санкт-Петербурге. Полное сопровозжение под ключ, от разработки до маркетинга https://webwhite.ru/
Ronaldhield
30 Aug 25 at 7:23 pm
купить подлинный аттестат за 11 класс [url=http://arus-diplom25.ru/]купить подлинный аттестат за 11 класс[/url] .
Diplomi_mgot
30 Aug 25 at 7:27 pm
Hello my family member! I wish to say that this article is awesome, great written and include almost all significant infos.
I’d like to look more posts like this .
Veltrex Core GPT
30 Aug 25 at 7:28 pm
This is really interesting, You’re a very skilled blogger.
I have joined your feed and look forward to seeking
more of your fantastic post. Also, I have shared your site in my social networks!
therapeutic properties
30 Aug 25 at 7:30 pm
Yes! Finally something about 호빠.
호빠
30 Aug 25 at 7:30 pm
можно купить аттестат 11 классов [url=http://arus-diplom24.ru/]http://arus-diplom24.ru/[/url] .
Diplomi_zfKn
30 Aug 25 at 7:31 pm
Hmm is anyone else having problems with the pictures on this blog loading?
I’m trying to find out if its a problem on my end or if it’s the blog.
Any responses would be greatly appreciated.
ดูซีรีย์
30 Aug 25 at 7:33 pm
Meds information. What side effects?
propranolol effects on blood pressure
Everything trends of medicine. Get information now.
propranolol effects on blood pressure
30 Aug 25 at 7:33 pm
Hey there! This is my 1st comment here so I just wanted to give a quick shout
out and tell you I genuinely enjoy reading through your
posts. Can you suggest any other blogs/websites/forums that cover the same
topics? Many thanks!
best online slots
30 Aug 25 at 7:33 pm
Ищете мобильные автоматизированные комплексы для производства качественных арболитовых блоков? Посетите сайт https://arbolit.com/ и вы найдете надежные комплексы для производства, отличающиеся своими качественными характеристиками. Ознакомьтесь на сайте со всеми преимуществами нашей продукции и уникальностью оборудования для производства арболитовых блоков.
Sumanamimpof
30 Aug 25 at 7:39 pm
https://www.grepmed.com/dqyfyhkcefuo
DavidVef
30 Aug 25 at 7:39 pm
all the time i used to read smaller articles or reviews which as well clear their motive, and that is also
happening with this article which I am reading at this
place.
Trade 1.9 Folex
30 Aug 25 at 7:42 pm