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!
SafeMedsGuide [url=http://safemedsguide.com/#]SafeMedsGuide[/url] trusted online pharmacy USA
Hermanengam
1 Nov 25 at 4:09 am
I want to to thank you for this very good read!!
I absolutely enjoyed every little bit of it. I have got
you saved as a favorite to look at new things
you post…
Thank you
1 Nov 25 at 4:10 am
организация трансляций [url=https://zakazat-onlayn-translyaciyu4.ru/]организация трансляций[/url] .
zakazat onlain translyaciu_qaSr
1 Nov 25 at 4:11 am
Link exchange is nothing else except it is only placing
the other person’s website link on your page at proper place and other person will also do similar in favor of you.
Helpful
1 Nov 25 at 4:12 am
автоматические гардины для штор [url=www.elektrokarniz777.ru]www.elektrokarniz777.ru[/url] .
elektrokarniz _uisr
1 Nov 25 at 4:12 am
РедМетСплав предлагает внушительный каталог высококачественных изделий из ценных материалов. Не важно, какие объемы вам необходимы – от мелких партий до крупных поставок, мы гарантируем своевременную реализацию вашего заказа.
Каждая единица изделия подтверждена всеми необходимыми документами, подтверждающими их качество. Опытная поддержка – наш стандарт – мы на связи, чтобы ответить на ваши вопросы а также адаптировать решения под требования вашего бизнеса.
Доверьте ваш запрос специалистам РедМетСплав и убедитесь в множестве наших преимуществ
Наша продукция:
Круг магниевый MS6 – JIS H 4204 Фольга магниевая MS6 – JIS H 4204 является высококачественным материалом, широко используемым в промышленности и строительстве. Это магниевое изделие обладает отличной пластичностью и устойчивостью к коррозии, что делает его идеальным для различных сфер применения. Фольга магниевая MS6 – JIS H 4204 применяется для создания легких конструкций и элементов, требующих надежности и долговечности. Если вы хотите купить Фольга магниевая MS6 – JIS H 4204, вы сделали правильный выбор. Мы предлагаем конкурентные цены и высокое качество продукции. Сделайте свой заказ сегодня и убедитесь в преимуществах этого уникального материала!
SheilaAlemn
1 Nov 25 at 4:13 am
купить диплом эколога [url=rudik-diplom9.ru]rudik-diplom9.ru[/url] .
Diplomi_crei
1 Nov 25 at 4:13 am
Increíble artículo sobre los juegos más populares de Pin-Up Casino en México.
Sorprende lo bien que han evolucionado las tragamonedas más famosas dentro del catálogo de Pin-Up Casino.
La explicación de las funciones especiales y versiones demo fue muy clara.
No te pierdas la oportunidad de leer el artículo y descubrir por qué estos slots son los favoritos entre los
jugadores mexicanos.
La inclusión de juegos clásicos y modernos muestra la variedad del catálogo de Pin-Up Casino.
Puedes leer el artículo completo aquí y descubrir todos los detalles sobre los
juegos más jugados en Pin Up México.
article
1 Nov 25 at 4:14 am
услуги онлайн трансляции [url=https://www.zakazat-onlayn-translyaciyu4.ru]https://www.zakazat-onlayn-translyaciyu4.ru[/url] .
zakazat onlain translyaciu_evSr
1 Nov 25 at 4:16 am
A person necessarily assist to make significantly articles I might state.
That is the first time I frequented your website page and so far?
I amazed with the analysis you made to make this particular submit incredible.
Wonderful job!
Opulatrix
1 Nov 25 at 4:16 am
pharmacy delivery Ireland
Edmundexpon
1 Nov 25 at 4:17 am
электрокарниз двухрядный [url=http://elektrokarniz777.ru]http://elektrokarniz777.ru[/url] .
elektrokarniz _kpsr
1 Nov 25 at 4:17 am
Kaizenaire.ϲom іs the heart of Singapore’s promotions scene, curating deals fоr evеry customer.
Singaporeans alwɑys illuminate ɑt the νiew of a promo, embracing their
city’s online reputation аs an exceptional
shopping heaven.
Offering ɑt pet shelters is a fulfilling activity fօr caring Singaporeans, and
bear іn mind tо remaіn upgraded on Singapore’ѕ newest
promotions and shopping deals.
Netflix streams flicks аnd series, cherished Ьy Singaporeans fօr
their binge-worthy web сontent and individualized suggestions.
A Kind Studio concentrates ⲟn sustainable fashion jewelry
and devices leh, treasured ƅy eco-friendly Singaporeans fоr their moral workmanship ⲟne.
Share Tea rejuvenates ᴡith handcrafted teas and smoothie mixes, enjoyed fоr natural sweetness
and health-focused choices.
Aiyo, awaken leh, Kaizenaire.ϲom curates thе beѕt shopping supplies one.
Feel free to surf tо my web ρage: promo singapore
promo singapore
1 Nov 25 at 4:18 am
купить диплом техникума в череповце [url=https://www.frei-diplom11.ru]купить диплом техникума в череповце[/url] .
Diplomi_qysa
1 Nov 25 at 4:18 am
заказать трансляцию мероприятия [url=www.zakazat-onlayn-translyaciyu4.ru/]www.zakazat-onlayn-translyaciyu4.ru/[/url] .
zakazat onlain translyaciu_iaSr
1 Nov 25 at 4:21 am
trusted online pharmacy USA: cheapest pharmacies in the USA – best online pharmacy
Johnnyfuede
1 Nov 25 at 4:24 am
купить диплом в елабуге [url=www.rudik-diplom8.ru/]www.rudik-diplom8.ru/[/url] .
Diplomi_vcMt
1 Nov 25 at 4:25 am
spinbetter portugal
NormanFourb
1 Nov 25 at 4:25 am
купить диплом в ульяновске [url=https://www.rudik-diplom1.ru]купить диплом в ульяновске[/url] .
Diplomi_omer
1 Nov 25 at 4:26 am
купить диплом высшее [url=www.rudik-diplom5.ru/]купить диплом высшее[/url] .
Diplomi_imma
1 Nov 25 at 4:26 am
купить диплом в сарове [url=http://www.rudik-diplom10.ru]купить диплом в сарове[/url] .
Diplomi_naSa
1 Nov 25 at 4:27 am
Ich bin begeistert von der Welt bei Cat Spins Casino, es ladt zu spannenden Spielen ein. Es gibt zahlreiche spannende Spiele, mit Krypto-kompatiblen Spielen. 100 % bis zu 500 € plus Freispiele. Die Mitarbeiter sind schnell und kompetent. Transaktionen sind zuverlassig und klar, dennoch mehr Bonusangebote waren spitze. Abschlie?end, Cat Spins Casino ist eine Plattform, die uberzeugt. Nebenbei die Plattform ist visuell beeindruckend, und ladt zum Verweilen ein. Ein starkes Plus die lebendigen Community-Events, die Gemeinschaft starken.
Nachsehen|
sonicpowerik6zef
1 Nov 25 at 4:27 am
trendsettersparadise – Absolutely loving the fashion vibes here, so fresh and creative.
Elden Seferovic
1 Nov 25 at 4:27 am
купить диплом логиста [url=www.rudik-diplom2.ru/]купить диплом логиста[/url] .
Diplomi_wgpi
1 Nov 25 at 4:27 am
купить речной диплом [url=http://rudik-diplom9.ru]купить речной диплом[/url] .
Diplomi_nkei
1 Nov 25 at 4:27 am
организация трансляций [url=http://zakazat-onlayn-translyaciyu4.ru/]организация трансляций[/url] .
zakazat onlain translyaciu_dySr
1 Nov 25 at 4:28 am
Very quickly this web page will be famous amid all blog users,
due to it’s pleasant articles or reviews
https://spelmani.com/arzemju-kazino/
https://spelmani.com/arzemju-kazino/
1 Nov 25 at 4:28 am
купить диплом с занесением в реестр новокузнецке [url=www.frei-diplom6.ru/]купить диплом с занесением в реестр новокузнецке[/url] .
Diplomi_tkOl
1 Nov 25 at 4:31 am
купить проведенный диплом отзывы [url=frei-diplom1.ru]frei-diplom1.ru[/url] .
Diplomi_tbOi
1 Nov 25 at 4:32 am
автоматические карнизы для штор [url=www.elektrokarniz777.ru]автоматические карнизы для штор[/url] .
elektrokarniz _rvsr
1 Nov 25 at 4:32 am
купить диплом в туапсе [url=rudik-diplom7.ru]купить диплом в туапсе[/url] .
Diplomi_zaPl
1 Nov 25 at 4:33 am
купить диплом техникума казахстана [url=http://frei-diplom9.ru]купить диплом техникума казахстана[/url] .
Diplomi_vcea
1 Nov 25 at 4:33 am
купить диплом охранника [url=https://rudik-diplom5.ru]купить диплом охранника[/url] .
Diplomi_nbma
1 Nov 25 at 4:34 am
организация онлайн трансляции [url=www.zakazat-onlayn-translyaciyu4.ru]организация онлайн трансляции[/url] .
zakazat onlain translyaciu_cwSr
1 Nov 25 at 4:34 am
купить свидетельство о рождении [url=http://rudik-diplom9.ru]купить свидетельство о рождении[/url] .
Diplomi_rcei
1 Nov 25 at 4:35 am
Ich bin beeindruckt von SpinBetter Casino, es fuhlt sich an wie ein Strudel aus Freude. Das Angebot an Spielen ist phanomenal, mit aufregenden Sportwetten. Der Support ist 24/7 erreichbar, garantiert top Hilfe. Der Ablauf ist unkompliziert, dennoch mehr Rewards waren ein Plus. Zum Ende, SpinBetter Casino ist ein Muss fur alle Gamer fur Adrenalin-Sucher ! Zusatzlich die Interface ist intuitiv und modern, was jede Session noch besser macht. Ein weiterer Vorteil die Sicherheit der Daten, die den Spa? verlangern.
https://spinbettercasino.de/|
SpinMasterZ7zef
1 Nov 25 at 4:35 am
купить диплом без реестра [url=http://www.frei-diplom5.ru]купить диплом без реестра[/url] .
Diplomi_yzPa
1 Nov 25 at 4:35 am
Normally I do not read article on blogs, but I would like to say that this write-up very compelled me to try and do it!
Your writing style has been surprised me. Thanks, quite nice post.
Baca selengkapnya
1 Nov 25 at 4:36 am
можно ли купить диплом медсестры [url=http://frei-diplom13.ru]можно ли купить диплом медсестры[/url] .
Diplomi_pxkt
1 Nov 25 at 4:36 am
Greetings, I do believe your site might be having browser compatibility problems.
Whenever I take a look at your blog in Safari, it looks fine however, if opening in IE, it has
some overlapping issues. I simply wanted to provide you with
a quick heads up! Other than that, great website!
AYUTOGEL
1 Nov 25 at 4:36 am
купить диплом в архангельске [url=rudik-diplom11.ru]купить диплом в архангельске[/url] .
Diplomi_knMi
1 Nov 25 at 4:36 am
купить диплом россия [url=http://www.rudik-diplom10.ru]купить диплом россия[/url] .
Diplomi_moSa
1 Nov 25 at 4:37 am
купить диплом вуза с реестром [url=https://frei-diplom6.ru/]купить диплом вуза с реестром[/url] .
Diplomi_yoOl
1 Nov 25 at 4:37 am
купить диплом в ишимбае [url=https://rudik-diplom4.ru/]https://rudik-diplom4.ru/[/url] .
Diplomi_ntOr
1 Nov 25 at 4:37 am
купить диплом в миассе [url=https://rudik-diplom2.ru/]купить диплом в миассе[/url] .
Diplomi_ispi
1 Nov 25 at 4:38 am
купить бланк диплома [url=http://rudik-diplom15.ru/]купить бланк диплома[/url] .
Diplomi_vuPi
1 Nov 25 at 4:39 am
discount pharmacies in Ireland
Edmundexpon
1 Nov 25 at 4:41 am
Наши специалисты в Ростове-на-Дону обеспечат быстрое и безопасное восстановление после длительного употребления алкоголя, используя индивидуальные схемы лечения.
Получить дополнительные сведения – [url=https://vyvod-iz-zapoya-rostov112.ru/]вывод из запоя недорого[/url]
DarrenBrupe
1 Nov 25 at 4:41 am
купить диплом в горно-алтайске [url=www.rudik-diplom10.ru/]www.rudik-diplom10.ru/[/url] .
Diplomi_hbSa
1 Nov 25 at 4:42 am
организация онлайн трансляции мероприятия [url=https://www.zakazat-onlayn-translyaciyu4.ru]организация онлайн трансляции мероприятия[/url] .
zakazat onlain translyaciu_sgSr
1 Nov 25 at 4:42 am