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!
наркологическая клиника в москве [url=https://www.narkologicheskaya-klinika-23.ru]https://www.narkologicheskaya-klinika-23.ru[/url] .
narkologicheskaya klinika_tret
26 Oct 25 at 3:22 pm
кракен онлайн
кракен тор
JamesDaync
26 Oct 25 at 3:23 pm
1xbet lite [url=http://1xbet-14.com]http://1xbet-14.com[/url] .
1xbet_aoet
26 Oct 25 at 3:23 pm
J’adore l’energie de Ruby Slots Casino, il propose une aventure palpitante. Il y a un eventail de titres captivants, comprenant des jeux compatibles avec les cryptos. Il donne un elan excitant. Les agents sont rapides et pros. Les gains arrivent sans delai, par contre des bonus plus varies seraient un plus. Pour conclure, Ruby Slots Casino assure un fun constant. Pour ajouter le design est tendance et accrocheur, amplifie l’adrenaline du jeu. Particulierement attrayant le programme VIP avec des recompenses exclusives, propose des avantages sur mesure.
Poursuivre la lecture|
cybercodeon9zef
26 Oct 25 at 3:23 pm
Je suis epate par Ruby Slots Casino, ca transporte dans un monde d’excitation. La selection est riche et diversifiee, incluant des paris sportifs pleins de vie. Le bonus de depart est top. Le suivi est d’une fiabilite exemplaire. Les transactions sont toujours fiables, de temps a autre quelques spins gratuits en plus seraient top. Pour conclure, Ruby Slots Casino est une plateforme qui fait vibrer. A mentionner le site est rapide et engageant, incite a rester plus longtemps. Un element fort le programme VIP avec des niveaux exclusifs, renforce la communaute.
Essayer ceci|
Swiftpulseok9zef
26 Oct 25 at 3:24 pm
https://mediuomo.shop/# farmaci per potenza maschile
JamesSlilk
26 Oct 25 at 3:24 pm
Generally I do not learn article on blogs, however I would like to say
that this write-up very forced me to try and do it! Your writing style
has been surprised me. Thank you, quite great article.
Tubidy musica
26 Oct 25 at 3:24 pm
кракен клиент
кракен Москва
JamesDaync
26 Oct 25 at 3:24 pm
J’adore le dynamisme de Ruby Slots Casino, il propose une aventure palpitante. Les options sont aussi vastes qu’un horizon, proposant des jeux de table classiques. Avec des depots rapides et faciles. Le service d’assistance est au point. Le processus est transparent et rapide, cependant des recompenses en plus seraient un bonus. Globalement, Ruby Slots Casino est un choix parfait pour les joueurs. En complement le design est moderne et attrayant, booste l’excitation du jeu. A mettre en avant les options de paris sportifs variees, offre des recompenses continues.
Visiter pour plus|
urbanforceix3zef
26 Oct 25 at 3:26 pm
поставка медицинского оборудования [url=http://medoborudovanie-postavka.ru]поставка медицинского оборудования[/url] .
postavka medicinskogo oborydovaniya_xesn
26 Oct 25 at 3:27 pm
медицинская техника [url=medicinskaya-tehnika.ru]медицинская техника[/url] .
medicinskaya tehnika_hbEi
26 Oct 25 at 3:29 pm
This is a topic that is near to my heart… Thank you!
Exactly where are your contact details though?
match three puzzle
26 Oct 25 at 3:29 pm
1xbet giri? linki [url=https://1xbet-10.com/]https://1xbet-10.com/[/url] .
1xbet_tcea
26 Oct 25 at 3:30 pm
1xbet spor bahislerinin adresi [url=1xbet-13.com]1xbet spor bahislerinin adresi[/url] .
1xbet_ddKa
26 Oct 25 at 3:31 pm
Incredible points. Sound arguments. Keep up the great spirit.
backlink
26 Oct 25 at 3:31 pm
мед оборудование [url=http://medicinskoe–oborudovanie.ru]мед оборудование[/url] .
medicinskoe oborydovanie_alei
26 Oct 25 at 3:32 pm
клиника наркология [url=https://narkologicheskaya-klinika-23.ru/]narkologicheskaya-klinika-23.ru[/url] .
narkologicheskaya klinika_hiet
26 Oct 25 at 3:32 pm
Sildenafil-tabletter pris: apotek online utan recept – Sildenafil utan recept
Jesuskax
26 Oct 25 at 3:32 pm
kraken
кракен даркнет маркет
JamesDaync
26 Oct 25 at 3:35 pm
Нужна дезинсекция ресторана от вирусов, особенно сейчас.
обработка от запахов
KennethceM
26 Oct 25 at 3:36 pm
После обработка от клопов стоимость насекомые исчезли навсегда!
обработка от клопов частного дома
KennethceM
26 Oct 25 at 3:37 pm
Где купить Марки лсд в Звенигороде?Что думаете, можно доверять на https://k833.ru
? Цены привлекательные, доставка работает. Но хочется узнать про реальное качество.
Stevenref
26 Oct 25 at 3:40 pm
поставщик медицинского оборудования [url=medoborudovanie-postavka.ru]поставщик медицинского оборудования[/url] .
postavka medicinskogo oborydovaniya_ndsn
26 Oct 25 at 3:40 pm
наркологическая помощь [url=http://narkologicheskaya-klinika-23.ru]http://narkologicheskaya-klinika-23.ru[/url] .
narkologicheskaya klinika_diet
26 Oct 25 at 3:42 pm
Oһ no, primary math teaches real-world uses lіke financial planning, tһerefore ensure your kid masters it rіght starting young.
Listen up, calm pom ρi pi, maths is рart ᧐f thе hiցhest subjects ɑt Junior College, building foundation fοr A-Level advanced math.
St. Joseph’s Institution Junior College embodies Lasallian customs, highlighying faith, service,
ɑnd intellectual pursuit. Integrated programs offer
smooth progression ᴡith focus οn bilingualissm and development.
Facilities ⅼike carrying оut arts centers improve creative expression. Global immersions aand rexearch study opportunities expand viewpoints.
Graduates ɑге compassionate achievers, mastering universities ɑnd
careers.
Hwa Chong Institution Junior College іѕ commemorated fоr іtѕ seamless integrated program tһɑt masterfully combines extensive scholastic
difficulties ѡith profound character advancement, cultivating а new generation ߋf global scholars
ɑnd ethical leaders ᴡho are equipped tо deal with complicated international
рroblems. Ƭhe organization boasts ᴡorld-class facilities, including
innovative proving ground, bilingual libraries, аnd innovation incubators, ᴡһere highly certified professors guide trainees tоward excellence
іn fields ⅼike clinical rеsearch study, entrepreneurial ventures,
аnd cultural studies. Trainees ցet vital experiences tһrough comprehensive global exchange programs, global competitions
іn mathematics and sciences, ɑnd collective tasks that broaden tһeir horizons аnd refine tһeir analytical and interpersonal skills.
Вy emphasizing development tһrough initiatives
ⅼike student-led startups ɑnd technology workshops, alⲟng witһ
service-oriented activities tһat promote social duty, tһе
college constructs strength, flexibility, аnd а strong moral foundation іn itss students.
Ƭhе vast alumni network of Hwa Chong Institution Junior College ߋpens paths tߋ elite universities and influential professions ɑround the world, highlighting the school’s sustaining legacy
ⲟf promoting intellectual prowess аnd principled management.
Іn addition to establishment facilities, emlhasize օn mathematics to aᴠoid common errors including inattentive blunders ɑt tests.
Mums and Dads, kiasu style ⲟn lah, strong primary maths rеsults for improved science understanding рlus engineering
goals.
Hey hey, Singapore parents, maths гemains lіkely the highly essential primary topic,
promoting imagination іn issue-resolving іn groundbreaking
careers.
Parents, worry ɑbout the gap hor, maths foundation proves critical Ԁuring Junior College іn understanding figures, crucial wіtһin modern tech-driven market.
Kiasu mindset in JC pushes уoս to conquer Math, unlocking doors
tο data science careers.
Ɗon’t mess around lah, combine a reputable Junior College alongside math excellence іn οrder tо guarantee superior Ꭺ
Levels marks and smooth changes.
Folks, dread the difference hor, mathematics foundation proves critical іn Junior College fоr
grasping figures, essential witһin modern tech-driven ѕystem.
Feel free to visit my page :: math tuition agency singapore
math tuition agency singapore
26 Oct 25 at 3:42 pm
handicap wette unentschieden
my web site: internet wetten live [Raina]
Raina
26 Oct 25 at 3:42 pm
поставщик медоборудования [url=https://www.medoborudovanie-postavka.ru]https://www.medoborudovanie-postavka.ru[/url] .
postavka medicinskogo oborydovaniya_rwsn
26 Oct 25 at 3:42 pm
наркологический центр москва [url=http://narkologicheskaya-klinika-24.ru/]http://narkologicheskaya-klinika-24.ru/[/url] .
narkologicheskaya klinika_akSr
26 Oct 25 at 3:44 pm
1xbet yeni giri? [url=1xbet-14.com]1xbet yeni giri?[/url] .
1xbet_nvet
26 Oct 25 at 3:44 pm
1xbet ?ye ol [url=www.1xbet-13.com/]www.1xbet-13.com/[/url] .
1xbet_jjKa
26 Oct 25 at 3:44 pm
Can I simply say what a relief to uncover an individual who actually understands what
they are talking about on the net. You certainly understand how to bring an issue to light and
make it important. More people have to read this and understand this side of the story.
I was surprised that you aren’t more popular since you surely
have the gift.
PRclanky.biz
26 Oct 25 at 3:47 pm
кракен
кракен Москва
JamesDaync
26 Oct 25 at 3:48 pm
обработка от клопов в отеле для офиса, посоветуйте проверенных.
обработка от запахов
KennethceM
26 Oct 25 at 3:48 pm
поставщик медицинского оборудования [url=https://www.medoborudovanie-postavka.ru]поставщик медицинского оборудования[/url] .
postavka medicinskogo oborydovaniya_vssn
26 Oct 25 at 3:50 pm
Howdy, There’s no doubt that your web site could be having internet browser compatibility issues.
When I take a look at your site in Safari, it looks fine but when opening
in Internet Explorer, it has some overlapping issues.
I merely wanted to give you a quick heads up!
Aside from that, great website!
my site zinnat02
zinnat02
26 Oct 25 at 3:52 pm
Way cool! Some extremely valid points! I appreciate you writing this post and the rest of the website is extremely good.
buôn bán nội tạng
26 Oct 25 at 3:55 pm
1xbet resmi sitesi [url=https://1xbet-14.com/]1xbet-14.com[/url] .
1xbet_gdet
26 Oct 25 at 3:56 pm
one x bet [url=https://1xbet-10.com/]https://1xbet-10.com/[/url] .
1xbet_ihea
26 Oct 25 at 3:57 pm
click through the up coming document
PHP hook, building hooks in your application – Sjoerd Maessen blog at Sjoerd Maessen blog
click through the up coming document
26 Oct 25 at 3:58 pm
медоборудование [url=http://www.medicinskoe–oborudovanie.ru]медоборудование[/url] .
medicinskoe oborydovanie_xwei
26 Oct 25 at 3:59 pm
наркология клиника [url=http://www.narkologicheskaya-klinika-23.ru]http://www.narkologicheskaya-klinika-23.ru[/url] .
narkologicheskaya klinika_hret
26 Oct 25 at 3:59 pm
1xbet tr giri? [url=www.1xbet-13.com/]www.1xbet-13.com/[/url] .
1xbet_omKa
26 Oct 25 at 4:00 pm
закодироваться в москве [url=https://narkologicheskaya-klinika-24.ru/]https://narkologicheskaya-klinika-24.ru/[/url] .
narkologicheskaya klinika_hySr
26 Oct 25 at 4:01 pm
Сколько стоит обработка от клопов для квартиры? Интересуют цены.
уничтожение тараканов в кафе
KennethceM
26 Oct 25 at 4:02 pm
1xbet resmi giri? [url=https://www.1xbet-14.com]1xbet resmi giri?[/url] .
1xbet_ttet
26 Oct 25 at 4:02 pm
Usually I don’t learn post on blogs, however I wish to say that this write-up very pressured me to check out and do so!
Your writing style has been amazed me. Thank you, quite nice article.
how to make antrax
26 Oct 25 at 4:03 pm
Hi there to every single one, it’s in fact
a fastidious for me to visit this website, it consists of
useful Information.
kra40
26 Oct 25 at 4:04 pm
кракен
кракен вход
JamesDaync
26 Oct 25 at 4:05 pm
купить диплом медсестры [url=www.frei-diplom15.ru]купить диплом медсестры[/url] .
Diplomi_nloi
26 Oct 25 at 4:05 pm
поставщик медоборудования [url=medoborudovanie-postavka.ru]medoborudovanie-postavka.ru[/url] .
postavka medicinskogo oborydovaniya_nasn
26 Oct 25 at 4:06 pm