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!
аттестат 11 класс купить уфа [url=arus-diplom23.ru]аттестат 11 класс купить уфа[/url] .
Diplomi_mwol
19 Jul 25 at 4:41 am
Hmm is anyone else experiencing problems with the
images on this blog loading? I’m trying to figure out if its a problem on my end or if it’s the blog.
Any responses would be greatly appreciated.
coupon codes
19 Jul 25 at 4:43 am
онлайн оценка наручных часов [url=www.ocenka-chasov-onlajn9.ru]www.ocenka-chasov-onlajn9.ru[/url] .
ocenka chasov onlain_pvMn
19 Jul 25 at 4:49 am
«СочиМед» предлагает комплексный подход: диагностика, детоксикация, терапия сопутствующих состояний, психологическая и социальная поддержка. В стационаре доступны:
Получить дополнительные сведения – http://narkologicheskaya-klinika-sochi00.ru
MichaelCrumn
19 Jul 25 at 4:50 am
Заказать дипломную работу http://diplomikon.ru недорого и без стресса. Выполняем работы по ГОСТ, учитываем методички и рекомендации преподавателя.
diplomikon-u
19 Jul 25 at 4:57 am
Заказать дипломную работу diplomikon.ru недорого и без стресса. Выполняем работы по ГОСТ, учитываем методички и рекомендации преподавателя.
diplomikon-l
19 Jul 25 at 4:57 am
пансионат для престарелых людей
pansionat-msk003.ru
пансионат после инсульта
zapojkrasnodarNeT
19 Jul 25 at 4:59 am
Шариковый подшипник Подшипники для пищевой промышленности Подшипники для пищевой промышленности должны соответствовать высоким гигиеническим требованиям и быть устойчивыми к воздействию агрессивных сред.
BrendonMaync
19 Jul 25 at 4:59 am
После вашего звонка нарколог выезжает на дом в течение 30–60 минут. Прибыв на место, специалист проводит всесторонний медицинский осмотр, включая измерение артериального давления, пульса и уровня кислорода в крови, а также собирает анамнез для определения степени интоксикации.
Ознакомиться с деталями – [url=https://narcolog-na-dom-voronezh0.ru/]vrach-narkolog-na-dom voronezh[/url]
Lancenep
19 Jul 25 at 4:59 am
Как подчёркивает заведующая отделением клинической психологии ФГБУН «НМИЦ психиатрии и наркологии» Минздрава России, наличие в команде специалистов с опытом работы в области зависимости — это основа качественной помощи.
Углубиться в тему – [url=https://narkologicheskaya-klinika-nizhnij-tagil11.ru/]наркологическая клиника нижний тагил.[/url]
Keithgek
19 Jul 25 at 5:05 am
mostbet aviator haqida [url=https://www.mostbet4072.ru]https://www.mostbet4072.ru[/url]
mostbet_doot
19 Jul 25 at 5:06 am
где купить не поддельные аттестаты 11 класс [url=http://arus-diplom23.ru/]где купить не поддельные аттестаты 11 класс[/url] .
Diplomi_sgol
19 Jul 25 at 5:07 am
прогноз ставок на сегодня [url=http://stavki-na-sport-prognozy1.ru/]http://stavki-na-sport-prognozy1.ru/[/url] .
stavki na sport prognozi _mpMa
19 Jul 25 at 5:18 am
Алкоголизм является хроническим заболеванием, требующим комплексного и профессионального подхода к лечению. Лечение алкоголизма в Сочи направлено на полное восстановление физического и психоэмоционального состояния пациента с помощью современных медицинских технологий и индивидуально подобранных программ терапии.
Подробнее можно узнать тут – [url=https://lechenie-alkogolizma-sochi00.ru/]клиника лечения алкоголизма краснодарский край[/url]
MichaelTum
19 Jul 25 at 5:20 am
Формирование цены на вызов нарколога с проведением капельничного вывода из запоя зависит от нескольких ключевых параметров:
Получить дополнительные сведения – https://vyvod-iz-zapoya-vladimir00.ru/srochnyj-vyvod-iz-zapoya-vladimir/
TimothyEvema
19 Jul 25 at 5:20 am
https://indiamedshub.shop/# IndiaMedsHub
RobertEmard
19 Jul 25 at 5:23 am
IndiaMedsHub [url=https://indiamedshub.com/#]best india pharmacy[/url] reputable indian online pharmacy
DavidRhinc
19 Jul 25 at 5:33 am
If you’re looking for a powerful WhatsApp hash extractor
or WhatsApp WART extractor, you need a reliable tool that
can efficiently extract WhatsApp account details from Android devices.
Whether you’re a digital marketer, researcher, or
developer, our WhatsApp account extractor software provides seamless extraction of WhatsApp protocol numbers, hash keys, and more.
WhatsApp forensic extraction tool
19 Jul 25 at 5:39 am
https://expresscarerx.org/# ExpressCareRx
Vernonhon
19 Jul 25 at 5:45 am
Undeniably believe that which you stated. Your favorite reason seemed to be at the internet
the simplest factor to keep in mind of. I say
to you, I definitely get irked while folks think about issues that they plainly don’t understand about.
You managed to hit the nail upon the top and defined out the entire
thing without having side-effects , people could take
a signal. Will probably be back to get more. Thank you
Here is my site; https://carinsuranceagents5.z21.web.core.windows.net/car-insurance-agent-index-278.html
https://carinsuranceagents5.z21.web.core.windows.net/car-insurance-agent-index-278.html
19 Jul 25 at 5:51 am
mostbet az aviator [url=https://mostbet4055.ru]mostbet az aviator[/url]
mostbet_laKi
19 Jul 25 at 5:51 am
finasteride mexico pharmacy: trusted mexican pharmacy – MediMexicoRx
BobbyAcany
19 Jul 25 at 5:52 am
прогнозы хоккей [url=http://prognozy-na-khokkej-segodnya.ru]http://prognozy-na-khokkej-segodnya.ru[/url] .
prognozi na hokkei segodnya_wgmr
19 Jul 25 at 5:53 am
Ключевым этапом является снятие интоксикации и устранение абстинентного синдрома. Применяются препараты, направленные на нормализацию работы внутренних органов и поддержание общего состояния здоровья. Медикаментозная терапия включает назначение антидепрессантов, препаратов, блокирующих тягу к алкоголю, что подтверждается исследованиями, опубликованными на научном портале PubMed. Актуальные рекомендации по медикаментозному лечению алкоголизма доступны на Национальном центре здоровья.
Получить больше информации – http://lechenie-alkogolizma-krasnodar00.ru/
Virgilcic
19 Jul 25 at 6:01 am
мелбет скачать на айфон [url=https://melbet3005.com]https://melbet3005.com[/url]
melbet_gtPl
19 Jul 25 at 6:03 am
Миссия клиники “Обновление” заключается в предоставлении качественной и всесторонней помощи людям, страдающим от различных форм зависимости. Мы понимаем, что успешное лечение невозможно без индивидуального подхода, поэтому каждый пациент проходит детальную диагностику, после которой разрабатывается персонализированный план терапии. В процессе работы мы акцентируем внимание на следующих аспектах:
Изучить вопрос глубже – https://kapelnica-ot-zapoya-irkutsk.ru/kapelnica-ot-zapoya-anonimno-v-irkutske/
Josephshoow
19 Jul 25 at 6:16 am
частный пансионат для пожилых людей
pansionat-msk003.ru
дом престарелых
vivodkrasnodarNeT
19 Jul 25 at 6:19 am
Незамедлительно после вызова нарколог прибывает на дом для проведения тщательного осмотра. На данном этапе специалист собирает анамнез, измеряет жизненно важные показатели — пульс, артериальное давление, температуру — и оценивает степень интоксикации. Эти данные являются основой для составления индивидуального плана лечения.
Изучить вопрос глубже – http://vyvod-iz-zapoya-vladimir000.ru
MichaelBrees
19 Jul 25 at 6:27 am
https://giphy.com/channel/Zzz12389
wonkarphu
19 Jul 25 at 6:28 am
купить диплом занесенный в реестр [url=http://www.arus-diplom35.ru]купить диплом занесенный в реестр[/url] .
Diplomi_krOn
19 Jul 25 at 6:37 am
вывод из запоя иркутск
vivod-iz-zapoya-irkutsk003.ru
лечение запоя
vivodirkutskNeT
19 Jul 25 at 6:40 am
Специалист выясняет, как долго продолжается запой, какие симптомы наблюдаются, а также наличие сопутствующих заболеваний. Эти данные позволяют сформировать индивидуальный план лечения и выбрать оптимальные методы детоксикации.
Подробнее можно узнать тут – https://vyvod-iz-zapoya-vladimir0.ru
TerryAcith
19 Jul 25 at 6:42 am
https://ukvd43.ru
Lesteretedy
19 Jul 25 at 6:42 am
Цилиндрический подшипник Подшипники для авиационной промышленности Подшипники для авиационной промышленности должны обладать высокой надежностью и устойчивостью к экстремальным условиям.
BrendonMaync
19 Jul 25 at 6:47 am
Алкогольная зависимость — хроническое заболевание, требующее комплексного подхода. В клинике «КубаньМед» в Краснодаре разработаны авторские методики, направленные на полное преодоление зависимости и возвращение пациента к полноценной жизни. Мы предлагаем индивидуальные программы лечения, сочетающие медикаментозную детоксикацию, специализированные реабилитационные процедуры и профессиональные психологические консультации. Всё это в условиях полного комфорта и абсолютной конфиденциальности.
Разобраться лучше – [url=https://lechenie-alkogolizma-krasnodar0.ru/]лечение алкоголизма цена[/url]
DonaldWrava
19 Jul 25 at 6:51 am
Москва после заката бодрствует, и мы тоже: частная центр лечения алкоголизма и наркомании клиника https://mcnl.ru/ работает 24/7. Без записей и формальностей — вызов доктора на дом за 39 минут, мягкий детокс под контролем, экспресс- капельница, психотерапия у вас, бессрочное сопровождение. Тайно, анонимно, точно — вернём трезвость без страха.
Dichaelwaw
19 Jul 25 at 6:55 am
купить диплом без занесения в реестр [url=www.arus-diplom35.ru/]купить диплом без занесения в реестр[/url] .
Diplomi_pzOn
19 Jul 25 at 6:59 am
Good article. I am experiencing a few of these issues as well..
News.concordnewsnow.com
19 Jul 25 at 7:03 am
Мегаполис ночью не спит, и мы аналогично: частная центр лечения алкоголизма и наркомании клиника https://mcnl.ru/ работает 24/7. Без очередей и документов — вызов врача по адресу за 40 минут, мягкий детокс под контролем, ультрабыстрая капельница, психологическая поддержка на месте, бессрочное сопровождение. Без шума, конфиденциально, эффективно — вернём трезвость без боли.
LewisGuatt
19 Jul 25 at 7:06 am
Мы понимаем, что лечение от алкогольной зависимости — это только первый шаг на пути к восстановлению. Профилактика рецидивов — важная часть нашего подхода. Мы проводим тренинги и курсы, направленные на развитие навыков борьбы с соблазнами и стрессом. Психотерапевтическая поддержка помогает пациентам справиться с эмоциональными трудностями, а также укрепляет мотивацию для сохранения трезвости.
Получить дополнительные сведения – [url=https://kapelnica-ot-zapoya-irkutsk3.ru/]капельница от запоя цена иркутск.[/url]
PatrickCrymn
19 Jul 25 at 7:12 am
Для начала комплексного лечения в наркологической клинике в Краснодаре проводится тщательная диагностика состояния пациента. Врач-нарколог назначает необходимые лабораторные и инструментальные исследования, среди которых общий анализ крови, биохимический анализ, ЭКГ, УЗИ внутренних органов, а также психодиагностические тесты. Такой комплексный подход позволяет выявить сопутствующие заболевания и оценить степень зависимости, что важно для выбора оптимальной терапии.
Получить дополнительные сведения – [url=https://narkologicheskaya-klinika-krasnodar0.ru/]бесплатная наркологическая клиника краснодар[/url]
ThomasIdeaf
19 Jul 25 at 7:17 am
точные прогнозы на спорт [url=www.prognozy-na-sport-3.ru]точные прогнозы на спорт[/url] .
prognozi na sport_mzen
19 Jul 25 at 7:19 am
gabapentin mexican pharmacy: gabapentin mexican pharmacy – MediMexicoRx
LewisSoump
19 Jul 25 at 7:22 am
Москва в ночь не дремлет, и мы вдобавок: частная центр лечения алкоголизма и наркомании клиника https://mcnl.ru/ работает 24/7. Без очередей и документов — вызов доктора на дом за 39 минут, щадящий детокс в сне, ультрабыстрая капельница, психологическая поддержка на дому, долговечное сопровождение. Тайно, анонимно, результативно — вернем вам трезвость без боли.
GichardMam
19 Jul 25 at 7:23 am
Инфузионная терапия при запое основывается на принципе постепенной и контролируемой доставки лекарственных препаратов и питательных смесей непосредственно в кровеносное русло. Это позволяет:
Получить дополнительную информацию – http://kapelnica-ot-zapoya-voronezh2.ru/vyezd-na-dom-kapelnicza-ot-zapoya-v-voronezhe/
JerryRag
19 Jul 25 at 7:25 am
safe mexican online pharmacy: buy from mexico pharmacy – safe mexican online pharmacy
LewisSoump
19 Jul 25 at 7:30 am
купить официальный диплом с занесением в реестр [url=http://www.arus-diplom35.ru]купить официальный диплом с занесением в реестр[/url] .
Diplomi_wyOn
19 Jul 25 at 7:32 am
My partner and I stumbled over here coming from a different web address and thought I should check things out.
I like what I see so now i am following you.
Look forward to looking at your web page for a second time.
Cheap prescription drugs without a prescription
19 Jul 25 at 7:33 am
голодание Голодание – это практика воздержания от пищи на определенный период времени. Оно может быть полным, когда человек не употребляет никакой пищи, или частичным, когда ограничивается определенная группа продуктов. Лечебное голодание – это форма голодания, которая проводится под наблюдением врача или другого квалифицированного медицинского специалиста с целью улучшения здоровья и лечения различных заболеваний. Голодание на воде – это одна из форм лечебного голодания, при которой разрешается употреблять только воду. Считается, что такой вид голодания позволяет организму очиститься от токсинов и запустить процессы самовосстановления.
BrianBaw
19 Jul 25 at 7:34 am
Реабилитация включает как амбулаторные, так и стационарные программы, адаптированные под индивидуальные потребности пациента. Применяется когнитивно-поведенческая терапия и групповые занятия, что способствует формированию устойчивой мотивации и предотвращению рецидивов. Подробнее о методах реабилитации доступно на портале Всемирной организации здравоохранения.
Углубиться в тему – [url=https://narkologicheskaya-klinika-sochi0.ru/]платная наркологическая клиника[/url]
DarwinGeada
19 Jul 25 at 7:47 am