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!
узнать интернет по адресу
inernetvkvartiru-krasnodar005.ru
провайдеры интернета по адресу
inernetkrdelini
9 Sep 25 at 9:21 pm
https://meditrustuk.com/# ivermectin cheap price online UK
Miltonbus
9 Sep 25 at 9:21 pm
Авто портал https://diesel.kyiv.ua все о мире автомобилей: новости, обзоры моделей, тест-драйвы, советы по выбору и уходу за авто. Каталог машин, актуальные цены, автоуслуги и полезная информация для автовладельцев.
OrlandoBoich
9 Sep 25 at 9:21 pm
Автомобильный портал https://auto-club.pl.ua онлайн-площадка для автолюбителей. Подробные обзоры машин, тест-драйвы, свежие новости, советы по ремонту и обслуживанию. Удобный поиск и актуальные материалы.
Gregoryciz
9 Sep 25 at 9:22 pm
Все для автомобилистов https://k-moto.com.ua на авто портале: новости, обзоры, статьи, каталоги и цены на автомобили. Экспертные мнения, тест-драйвы и практические советы по эксплуатации авто.
BillyTem
9 Sep 25 at 9:22 pm
http://www.pageorama.com/?p=yheigici
AllenGop
9 Sep 25 at 9:23 pm
играть авиатор [url=www.aviator-igra-1.ru/]играть авиатор[/url] .
aviator igra_gaOn
9 Sep 25 at 9:26 pm
Hi there i am kavin, its my first occasion to commenting anyplace, when i read this post i thought i could
also make comment due to this sensible article.
toto togel
9 Sep 25 at 9:32 pm
viagra discreet delivery UK https://meditrustuk.com/# MediTrust
StuartDop
9 Sep 25 at 9:32 pm
https://mykredit-online.ru/
Travistug
9 Sep 25 at 9:33 pm
Mikigaming ✈︎ Situs Slot Indonesia Gampang
Maxwin Tahun Ini
Mikigaming
9 Sep 25 at 9:34 pm
darkmarket link darknet websites darknet markets onion address [url=https://privatedarknetmarket.com/ ]darknet links [/url]
Robertalima
9 Sep 25 at 9:35 pm
Обращение за экстренной помощью требуется в ситуациях, когда симптомы ломки становятся невыносимыми и ухудшают общее состояние пациента. Основными показаниями для вызова специалиста являются:
Углубиться в тему – [url=https://snyatie-lomki-ekb8.ru/]снятие наркотической ломки[/url]
Danielgaugh
9 Sep 25 at 9:36 pm
plane money game [url=www.aviator-igra-1.ru]www.aviator-igra-1.ru[/url] .
aviator igra_dfOn
9 Sep 25 at 9:38 pm
Приобрести диплом на заказ возможно используя официальный портал компании. [url=http://forum54.4adm.ru/ucp.php?mode=resend_act&sid=35d7d9702b00c260b99da0969186ab20/]forum54.4adm.ru/ucp.php?mode=resend_act&sid=35d7d9702b00c260b99da0969186ab20[/url]
Sazrckg
9 Sep 25 at 9:40 pm
This is my first time visit at here and i am actually impressed to read everthing at single place.
Chat vidéo filles
9 Sep 25 at 9:40 pm
Нужен автобусный билет? заказ билетов на автобус удобный сервис поиска и бронирования. Широкий выбор направлений, надежные перевозчики, доступные цены и моментальная отправка электронных билетов на почту.
Ronnieler
9 Sep 25 at 9:41 pm
Stay connected to real players and genuine updates from shbet – official Instagram hub
shbet-755
9 Sep 25 at 9:44 pm
Attractive portion of content. I just stumbled upon your weblog and in accession capital to say that
I get actually enjoyed account your blog posts.
Any way I will be subscribing to your feeds or even I achievement you get admission to constantly rapidly.
http://xx69.de/member.php?action=viewpro&member=WilburJull
9 Sep 25 at 9:44 pm
Нужен автобусный билет? probilets.com удобный сервис поиска и бронирования. Широкий выбор направлений, надежные перевозчики, доступные цены и моментальная отправка электронных билетов на почту.
Ronnieler
9 Sep 25 at 9:44 pm
лечение запоя минск
vivod-iz-zapoya-minsk009.ru
лечение запоя
vivodminskNeT
9 Sep 25 at 9:45 pm
Нужен автобусный билет? билеты на автобус удобный сервис поиска и бронирования. Широкий выбор направлений, надежные перевозчики, доступные цены и моментальная отправка электронных билетов на почту.
Ronnieler
9 Sep 25 at 9:45 pm
Рабочие дни отсчитываются со дня оплаты, а не заказа на сайте, разница порой месяц между тем когда человек создал заказ и когда оплатил его.
https://www.divephotoguide.com/user/baudladyfoc
Спасибо, будем работать тогда тоже )
TravisGowly
9 Sep 25 at 9:47 pm
авиатор игра [url=http://aviator-igra-1.ru]авиатор игра[/url] .
aviator igra_ndOn
9 Sep 25 at 9:48 pm
I got this site from my pal who told me regarding this web page and now
this time I am browsing this web page and reading very informative content at this time.
xxx
9 Sep 25 at 9:52 pm
http://intimacareuk.com/# buy ED pills online discreetly UK
Miltonbus
9 Sep 25 at 9:52 pm
plane game money [url=http://aviator-igra-1.ru/]http://aviator-igra-1.ru/[/url] .
aviator igra_fpOn
9 Sep 25 at 9:54 pm
Explore premium content with shbet – verified updates and safe community interaction
shbet-353
9 Sep 25 at 9:54 pm
MediTrust: MediTrust UK – trusted online pharmacy ivermectin UK
Jamesmit
9 Sep 25 at 9:56 pm
Автомобильный портал https://auto-club.pl.ua онлайн-площадка для автолюбителей. Подробные обзоры машин, тест-драйвы, свежие новости, советы по ремонту и обслуживанию. Удобный поиск и актуальные материалы.
Gregoryciz
9 Sep 25 at 9:59 pm
Авто портал https://diesel.kyiv.ua все о мире автомобилей: новости, обзоры моделей, тест-драйвы, советы по выбору и уходу за авто. Каталог машин, актуальные цены, автоуслуги и полезная информация для автовладельцев.
OrlandoBoich
9 Sep 25 at 9:59 pm
Все для автомобилистов https://k-moto.com.ua на авто портале: новости, обзоры, статьи, каталоги и цены на автомобили. Экспертные мнения, тест-драйвы и практические советы по эксплуатации авто.
BillyTem
9 Sep 25 at 10:00 pm
https://www.autobazar.eu/images/pages/?1xbet_promo_code_14.html
Matthewfoony
9 Sep 25 at 10:00 pm
aviator money game [url=http://aviator-igra-1.ru]http://aviator-igra-1.ru[/url] .
aviator igra_gyOn
9 Sep 25 at 10:00 pm
I think this is among the most important information for me.
And i’m glad reading your article. But should remark on some general things, The site style is
wonderful, the articles is really great : D. Good
job, cheers
Price Chiropractic and Rehabilitation knee pain relief near me
9 Sep 25 at 10:00 pm
Авто портал https://diesel.kyiv.ua все о мире автомобилей: новости, обзоры моделей, тест-драйвы, советы по выбору и уходу за авто. Каталог машин, актуальные цены, автоуслуги и полезная информация для автовладельцев.
OrlandoBoich
9 Sep 25 at 10:01 pm
Автомобильный портал https://auto-club.pl.ua онлайн-площадка для автолюбителей. Подробные обзоры машин, тест-драйвы, свежие новости, советы по ремонту и обслуживанию. Удобный поиск и актуальные материалы.
Gregoryciz
9 Sep 25 at 10:01 pm
Запой становится критическим, когда организм не справляется с постоянным поступлением алкоголя и начинает накапливать токсины. Если состояние пациента ухудшается, появляются такие симптомы, как сильная рвота, головокружение, спутанность сознания, судороги, резкие колебания артериального давления, а также проявления тяжелого абстинентного синдрома (дрожь, панические атаки, бессонница, тревожность), вызов нарколога становится необходимым. Также экстренная помощь требуется при наличии психических нарушений — галлюцинациях, агрессивном поведении или алкогольном психозе. Своевременное вмешательство позволяет стабилизировать состояние, предотвратить развитие осложнений и снизить риск для жизни.
Получить дополнительную информацию – [url=https://vyvod-iz-zapoya-novosibirsk00.ru/]наркологический вывод из запоя новосибирск[/url]
Lesliemum
9 Sep 25 at 10:02 pm
Все для автомобилистов https://k-moto.com.ua на авто портале: новости, обзоры, статьи, каталоги и цены на автомобили. Экспертные мнения, тест-драйвы и практические советы по эксплуатации авто.
BillyTem
9 Sep 25 at 10:02 pm
Авто портал https://diesel.kyiv.ua все о мире автомобилей: новости, обзоры моделей, тест-драйвы, советы по выбору и уходу за авто. Каталог машин, актуальные цены, автоуслуги и полезная информация для автовладельцев.
OrlandoBoich
9 Sep 25 at 10:03 pm
Автомобильный портал https://auto-club.pl.ua онлайн-площадка для автолюбителей. Подробные обзоры машин, тест-драйвы, свежие новости, советы по ремонту и обслуживанию. Удобный поиск и актуальные материалы.
Gregoryciz
9 Sep 25 at 10:03 pm
как купить диплом о высшем образовании с занесением в реестр [url=educ-ua13.ru]как купить диплом о высшем образовании с занесением в реестр[/url] .
Diplomi_gmpn
9 Sep 25 at 10:03 pm
Все для автомобилистов https://k-moto.com.ua на авто портале: новости, обзоры, статьи, каталоги и цены на автомобили. Экспертные мнения, тест-драйвы и практические советы по эксплуатации авто.
BillyTem
9 Sep 25 at 10:04 pm
nexus darknet shop nexus market darknet markets [url=https://darkmarketsdirectory.com/ ]dark web drug marketplace [/url]
BrianWeX
9 Sep 25 at 10:07 pm
Join the entertainment journey with shbet – trusted source of authentic gaming experiences
shbet-749
9 Sep 25 at 10:08 pm
BluePill UK [url=http://bluepilluk.com/#]generic sildenafil UK pharmacy[/url] order viagra online safely UK
Albertmoone
9 Sep 25 at 10:08 pm
заказывал уже недельку назад, все пришло качество хорошее делал 250 1 к 9ти вполне на час полтора хорошего эфекта
https://pixelfed.tokyo/qcajvez942
Жалко конечно что убрали покупку от грамма
TravisGowly
9 Sep 25 at 10:11 pm
Купить диплом вы сможете используя сайт компании. [url=http://slagerijaarse.nl/kupit-diplom-oficialno-i-bez-riska-129/]slagerijaarse.nl/kupit-diplom-oficialno-i-bez-riska-129[/url]
Sazrhxz
9 Sep 25 at 10:12 pm
I read this post completely concerning the comparison of
hottest and preceding technologies, it’s awesome article.
live draw hk
9 Sep 25 at 10:14 pm
Кешбэк — возврат части потраченных
на игру денег возвращается в Коинах.
7k казино
9 Sep 25 at 10:16 pm