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!
buy corticosteroids without prescription UK: cheap prednisolone in UK – buy prednisolone
Brettesofe
13 Oct 25 at 12:24 am
I’ve learn a few just right stuff here. Certainly price bookmarking for revisiting.
I wonder how much effort you place to make this kind of fantastic
informative web site.
https://gardenhouse24.uk/what-is-floor-waterproofing.html
13 Oct 25 at 12:24 am
как купить диплом с реестром [url=http://frei-diplom2.ru/]как купить диплом с реестром[/url] .
Diplomi_beEa
13 Oct 25 at 12:25 am
1win az bonus 500 [url=https://www.1win5004.com]https://www.1win5004.com[/url]
1win_tdoi
13 Oct 25 at 12:25 am
https://soundcloud.com/candetoxblend
Pasar un test antidoping puede ser arriesgado. Por eso, se ha creado un suplemento innovador con respaldo internacional.
Su mezcla eficaz combina nutrientes esenciales, lo que ajusta tu organismo y disimula temporalmente los metabolitos de alcaloides. El resultado: una orina con parametros normales, lista para entregar tranquilidad.
Lo mas destacado es su accion rapida en menos de 2 horas. A diferencia de otros productos, no promete resultados permanentes, sino una herramienta puntual que responde en el momento justo.
Estos fórmulas están diseñados para facilitar a los consumidores a purgar su cuerpo de sustancias no deseadas, especialmente esas relacionadas con el ingesta de cannabis u otras drogas.
El buen detox para examen de fluido debe brindar resultados rápidos y efectivos, en particular cuando el tiempo para prepararse es limitado. En el mercado actual, hay muchas variedades, pero no todas prometen un proceso seguro o rápido.
Qué funciona un producto detox? En términos simples, estos suplementos funcionan acelerando la expulsión de metabolitos y residuos a través de la orina, reduciendo su presencia hasta quedar por debajo del límite de detección de algunos tests. Algunos actúan en cuestión de horas y su efecto puede durar entre 4 a seis horas.
Parece fundamental combinar estos productos con adecuada hidratación. Beber al menos 2 litros de agua diariamente antes y después del ingesta del detox puede mejorar los efectos. Además, se recomienda evitar alimentos grasos y bebidas procesadas durante el proceso de desintoxicación.
Los mejores productos de purga para orina incluyen ingredientes como extractos de plantas, vitaminas del tipo B y minerales que favorecen el funcionamiento de los órganos y la función hepática. Entre las marcas más vendidas, se encuentran aquellas que presentan certificaciones sanitarias y estudios de eficacia.
Para usuarios frecuentes de cannabis, se recomienda usar detoxes con tiempos de acción largas o iniciar una preparación anticipada. Mientras más larga sea la abstinencia, mayor será la eficacia del producto. Por eso, combinar la organización con el uso correcto del detox es clave.
Un error común es suponer que todos los detox actúan igual. Existen diferencias en formulación, sabor, método de toma y duración del resultado. Algunos vienen en envase líquido, otros en cápsulas, y varios combinan ambos.
Además, hay productos que incluyen fases de preparación o purga previa al día del examen. Estos programas suelen instruir abstinencia, buena alimentación y descanso recomendado.
Por último, es importante recalcar que ningún detox garantiza 100% de éxito. Siempre hay variables personales como metabolismo, historial de consumo, y tipo de examen. Por ello, es vital seguir las instrucciones del fabricante y no descuidarse.
Miles de estudiantes ya han validado su discrecion. Testimonios reales mencionan resultados exitosos en pruebas preocupacionales.
Si necesitas asegurar tu resultado, esta alternativa te ofrece confianza.
JuniorShido
13 Oct 25 at 12:25 am
Great work! This is the kind of info that are supposed to be shared around the internet.
Shame on the seek engines for not positioning
this submit upper! Come on over and seek advice from my site
. Thank you =)
PENIS BOOBS
13 Oct 25 at 12:26 am
https://faberlic-pokupki.ru
RandyEluse
13 Oct 25 at 12:26 am
Located in the heart of Sukhumvit,
[url=https://www.nurumassagevip.com/]nuru massage Bangkok[/url] brings an exclusive erotic massage experience close to Bangkok’s luxury hotels and nightlife.
Louishet
13 Oct 25 at 12:28 am
Bitcoin wird in vielen Online-Casinos akzeptiert. Es bietet Anonymitat, birgt aber auch Sicherheitsrisiken.
Zyloprim
ThomasInvag
13 Oct 25 at 12:28 am
Located in the heart of Sukhumvit,
[url=https://www.nurumassagevip.com/]Nuru massage[/url] brings an exclusive erotic massage experience close to Bangkok’s luxury hotels and nightlife.
Louishet
13 Oct 25 at 12:29 am
диплом медицинского колледжа купить [url=https://frei-diplom8.ru]https://frei-diplom8.ru[/url] .
Diplomi_kjsr
13 Oct 25 at 12:29 am
Мир архитектуры https://vineyardartdecor.com и дизайна в одном месте! Лучшие идеи, проекты и вдохновение для дома, офиса и города. Узнай, как создаются красивые и функциональные пространства.
AnthonyGog
13 Oct 25 at 12:30 am
перепланировка нежилого помещения [url=mymoscow.forum24.ru/?1-6-0-00034012-000-0-0-1759746919]mymoscow.forum24.ru/?1-6-0-00034012-000-0-0-1759746919[/url] .
pereplanirovka v nejilom zdanii_cnKi
13 Oct 25 at 12:34 am
легальный диплом купить [url=frei-diplom3.ru]легальный диплом купить[/url] .
Diplomi_igKt
13 Oct 25 at 12:36 am
можно купить диплом медсестры [url=http://www.frei-diplom14.ru]можно купить диплом медсестры[/url] .
Diplomi_leoi
13 Oct 25 at 12:36 am
купить диплом химика [url=www.rudik-diplom7.ru]купить диплом химика[/url] .
Diplomi_gnPl
13 Oct 25 at 12:37 am
Клиника «АлкоНарко» специализируется на лечении алкоголизма и наркомании. Опытные врачи проводят вывод из запоя, ставят капельницы от запоя на дому и обеспечивают круглосуточную наркологическую помощь как в стационаре, так и на выезде.
Подробнее – [url=https://alko-narko.info/vliyanie-na-zdorove/alkogolnyy-deliriy.html]что такое алкогольный делирий простыми словами[/url]
LoreneDyela
13 Oct 25 at 12:39 am
перепланировка нежилого помещения [url=http://forumsilverstars.forum24.ru/?1-10-0-00001559-000-0-0]http://forumsilverstars.forum24.ru/?1-10-0-00001559-000-0-0[/url] .
pereplanirovka v nejilom zdanii_mxKi
13 Oct 25 at 12:40 am
купить диплом техникума в нальчике [url=frei-diplom9.ru]купить диплом техникума в нальчике[/url] .
Diplomi_uuea
13 Oct 25 at 12:42 am
What’s up to all, how is everything, I think every one is
getting more from this web page, and your views are good for new
users.
gps tracker for dogs
13 Oct 25 at 12:43 am
prednisone online
prednisone online
13 Oct 25 at 12:43 am
Hi, i think that i noticed you visited my web site
so i got here to go back the desire?.I am trying to in finding issues to
improve my web site!I assume its adequate to make use of some of your concepts!!
spot on collar
13 Oct 25 at 12:45 am
Maligayang pagdating sa DAGA 88 Pilipinas — simulan ang iyong panalo ngayon! Kumuha ng
kaakit-akit na bonus, maglaro ng top games, at maranasan ang patas, ligtas,
at komportableng online na pagtaya.
Ganap na Binabayaran
13 Oct 25 at 12:46 am
купить диплом пту в реестре [url=http://frei-diplom1.ru/]купить диплом пту в реестре[/url] .
Diplomi_hnOi
13 Oct 25 at 12:48 am
prednisone online
prednisone online
13 Oct 25 at 12:48 am
купить диплом техникума в нальчике [url=http://www.frei-diplom9.ru]купить диплом техникума в нальчике[/url] .
Diplomi_sqea
13 Oct 25 at 12:50 am
купить диплом в череповце [url=http://rudik-diplom7.ru/]http://rudik-diplom7.ru/[/url] .
Diplomi_xePl
13 Oct 25 at 12:51 am
https://marwapremium.ru
RandyEluse
13 Oct 25 at 12:53 am
купить диплом о высшем образовании легально [url=www.frei-diplom1.ru]купить диплом о высшем образовании легально[/url] .
Diplomi_ycOi
13 Oct 25 at 12:55 am
перепланировка нежилого помещения [url=https://www.cah.forum24.ru/?1-13-0-00002795-000-0-0]https://www.cah.forum24.ru/?1-13-0-00002795-000-0-0[/url] .
pereplanirovka v nejilom zdanii_ogKi
13 Oct 25 at 12:56 am
купить диплом о высшем образовании с занесением в реестр в калуге [url=https://frei-diplom1.ru]купить диплом о высшем образовании с занесением в реестр в калуге[/url] .
Diplomi_nhOi
13 Oct 25 at 1:00 am
диплом настоящий купить с занесением в реестр [url=http://www.frei-diplom3.ru]http://www.frei-diplom3.ru[/url] .
Diplomi_kpKt
13 Oct 25 at 1:01 am
هی کاربران، در وبسایتهای شرطبندی ذهن نکنید؛ چنین سایتها آکنده از ریسکها مالی، ذهنی و اجتماعی هستند.
من از یک ورود سرمایهام
را باخت نمودم. سوءاستفاده نسبت به این شرطها سریعتر از امری که
فکر میکنید پیشرفت مینماید.
اصلاً مشغول نخواهید شد!
سایت scam شرط بندی
13 Oct 25 at 1:01 am
ufafat หรือ ยูฟ่าแฟด
เว็บเดิมพันออนไลน์มาตรฐาน
UFABET เล่นง่าย จ่ายจริง ระบบอัตโนมัติรวดเร็ว ครบทุกเกมดังในเว็บเดียว สมัครฟรีวันนี้!
ยูฟ่าแฟด
13 Oct 25 at 1:07 am
I do accept as true with all the ideas you’ve introduced
in your post. They’re really convincing and will certainly work.
Nonetheless, the posts are too brief for
beginners. May just you please extend them a bit from next time?
Thank you for the post.
Orthodontist near me
13 Oct 25 at 1:07 am
유흥알바는 술집, 클럽, 노래방 등 유흥업소에서 하는 다양한 아르바이트를 통칭합니다.
주로 야간에 이뤄지며 룸알바, 밤알바,
여성알바 등 여러 이름으로 불립니다.
유흥알바
13 Oct 25 at 1:08 am
перепланировка нежилого помещения [url=www.forumsilverstars.forum24.ru/?1-10-0-00001559-000-0-0]www.forumsilverstars.forum24.ru/?1-10-0-00001559-000-0-0[/url] .
pereplanirovka v nejilom zdanii_yqKi
13 Oct 25 at 1:09 am
https://a-bsme.at
Hermannalia
13 Oct 25 at 1:10 am
диплом о высшем образовании с проводкой купить [url=https://frei-diplom2.ru/]диплом о высшем образовании с проводкой купить[/url] .
Diplomi_xjEa
13 Oct 25 at 1:12 am
как купить легально диплом о высшем образовании [url=frei-diplom3.ru]как купить легально диплом о высшем образовании[/url] .
Diplomi_yjKt
13 Oct 25 at 1:12 am
купить диплом ссср [url=http://www.rudik-diplom2.ru]купить диплом ссср[/url] .
Diplomi_jzpi
13 Oct 25 at 1:12 am
This piece of writing gives clear idea for the new visitors of blogging, that actually how to do blogging.
gps dog collar
13 Oct 25 at 1:12 am
медсестра которая купила диплом врача [url=www.frei-diplom14.ru/]www.frei-diplom14.ru/[/url] .
Diplomi_bjoi
13 Oct 25 at 1:13 am
Мир архитектуры https://vineyardartdecor.com и дизайна в одном месте! Лучшие идеи, проекты и вдохновение для дома, офиса и города. Узнай, как создаются красивые и функциональные пространства.
AnthonyGog
13 Oct 25 at 1:14 am
перепланировка в нежилом здании [url=https://aktivnoe.forum24.ru/?1-9-0-00001303-000-0-0]https://aktivnoe.forum24.ru/?1-9-0-00001303-000-0-0[/url] .
pereplanirovka v nejilom zdanii_mkKi
13 Oct 25 at 1:15 am
This post is truly a pleasant one it helps new net viewers, who
are wishing in favor of blogging.
phising
13 Oct 25 at 1:16 am
Мир архитектуры https://vineyardartdecor.com и дизайна в одном месте! Лучшие идеи, проекты и вдохновение для дома, офиса и города. Узнай, как создаются красивые и функциональные пространства.
AnthonyGog
13 Oct 25 at 1:18 am
https://raspilservice.ru
RandyEluse
13 Oct 25 at 1:19 am
купить диплом владимирского техникума [url=http://frei-diplom8.ru/]купить диплом владимирского техникума[/url] .
Diplomi_xssr
13 Oct 25 at 1:19 am
Rocephin ist ein starkes injizierbares Antibiotikum. Es wird oft in Krankenhausern bei schweren Infektionen verwendet.
Aldactone
ThomasInvag
13 Oct 25 at 1:20 am