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!
Excellent post. I will be dealing with some of these issues as well..
Cheers
14 Oct 25 at 6:58 am
электрокранизы [url=http://karniz-elektroprivodom.ru]http://karniz-elektroprivodom.ru[/url] .
karniz elektroprivodom shtor kypit_rlei
14 Oct 25 at 6:59 am
купить официальный диплом [url=http://educ-ua7.ru]http://educ-ua7.ru[/url] .
Diplomi_geea
14 Oct 25 at 6:59 am
You can certainly see your expertise within the article you write.
The arena hopes for even more passionate writers such as you who are not afraid to mention how they
believe. Always follow your heart.
mv88 app
14 Oct 25 at 7:00 am
диплом купить реестр [url=http://www.frei-diplom5.ru]диплом купить реестр[/url] .
Diplomi_inPa
14 Oct 25 at 7:01 am
pharmacy online UK: Brit Meds Direct – BritMeds Direct
Brettesofe
14 Oct 25 at 7:01 am
купить диплом в липецке [url=http://www.rudik-diplom8.ru]купить диплом в липецке[/url] .
Diplomi_txMt
14 Oct 25 at 7:01 am
электрические гардины для штор [url=http://karniz-elektroprivodom.ru]http://karniz-elektroprivodom.ru[/url] .
karniz elektroprivodom shtor kypit_pwei
14 Oct 25 at 7:01 am
The buzz on Minotaurus presale is real, surpassing milestones fast. $MTAUR’s tokenomics prioritize sustainability over quick flips. Game’s whimsical elements shine.
minotaurus presale
WilliamPargy
14 Oct 25 at 7:01 am
перепланировка нежилого помещения в нежилом здании законодательство [url=https://www.pereplanirovka-nezhilogo-pomeshcheniya11.ru]перепланировка нежилого помещения в нежилом здании законодательство[/url] .
pereplanirovka nejilogo pomesheniya_pner
14 Oct 25 at 7:02 am
В зависимости от клинической картины и предпочтений возможны следующие виды кодирования:
Подробнее – https://kodirovanie-ot-alkogolizma-ehlektrostal6.ru/kodirovanie-ot-alkogolizma-na-domu-v-ehlektrostali
ScottCet
14 Oct 25 at 7:02 am
перепланировка нежилого помещения в многоквартирном доме [url=pereplanirovka-nezhilogo-pomeshcheniya10.ru]перепланировка нежилого помещения в многоквартирном доме[/url] .
pereplanirovka nejilogo pomesheniya_kgSr
14 Oct 25 at 7:02 am
рулонные шторы на окна недорого [url=http://www.rulonnaya-shtora-s-elektroprivodom.ru]рулонные шторы на окна недорого[/url] .
rylonnaya shtora s elektroprivodom_lqKt
14 Oct 25 at 7:04 am
мини экскаватор в аренду [url=https://arenda-mini-ekskavatora-v-moskve-2.ru/]мини экскаватор в аренду[/url] .
arenda mini ekskavatora v moskve_daKt
14 Oct 25 at 7:05 am
потолочкин ру натяжные потолки отзывы [url=www.stretch-ceilings-samara.ru/]www.stretch-ceilings-samara.ru/[/url] .
natyajnie potolki samara_ntkl
14 Oct 25 at 7:07 am
электрокарниз двухрядный [url=http://www.karniz-shtor-elektroprivodom.ru]http://www.karniz-shtor-elektroprivodom.ru[/url] .
karniz dlya shtor s elektroprivodom_emer
14 Oct 25 at 7:07 am
карниз для штор электрический [url=http://karniz-elektroprivodom.ru/]карниз для штор электрический[/url] .
karniz elektroprivodom shtor kypit_xaei
14 Oct 25 at 7:08 am
J’ai un engouement sincere pour Locowin Casino, il delivre une experience unique. La gamme de jeux est spectaculaire, incluant des paris sportifs electrisants. Le bonus d’accueil est attractif. Le suivi est exemplaire, assurant un support premium. Les operations sont solides et veloces, mais des incitations additionnelles seraient un benefice. Tout compte fait, Locowin Casino merite une exploration approfondie pour les joueurs a la recherche d’aventure ! Par ailleurs la plateforme est esthetiquement remarquable, ce qui eleve chaque session a un niveau superieur. A souligner aussi les evenements communautaires captivants, qui stimule l’engagement.
Lire la suite|
RandomTwistY6zef
14 Oct 25 at 7:08 am
Astronomers have observed a planet that in some ways behaves more like a star — including a massive growth spurt unlike anything witnessed before in a free-floating planet.
[url=https://ms-stroy.ru/stroitelstvo_domov_iz_gazobetonnyh_blokov/]стоимость строительства дома из газобетона под ключ[/url]
The rogue planet, which does not orbit any star, is called Cha 1107-7626 and is outside of our solar system, 620 light-years from Earth in the Chamaeleon constellation. A single light-year, or the distance light travels in one year, is equal to 5.88 trillion miles (9.46 trillion kilometers).
The planet has a mass five to 10 times that of Jupiter, the largest planet in our solar system. And it’s getting bigger every second, according to new research published Thursday in The Astrophysical Journal Letters.
Estimated to be 1 million to 2 million years old, Cha 1107-7626 is still forming, said study coauthor Aleks Scholz, an astronomer at the University of St. Andrews in Scotland. It may sound old, but astronomically speaking, the planet is in its infancy. By contrast, the planets in our solar system are about 4.5 billion years old.
https://ms-stroy.ru/cokolnyj_etazh_chastnogo_doma/
дом построить москва
Cha 1107-7626 is surrounded by a disk of gas and dust, which constantly falls onto the planet and accumulates during a process that astronomers call accretion. But the rate at which the young planet is growing varies, the study authors said.
Observations with the European Southern Observatory’s Very Large Telescope in Chile’s Atacama Desert, along with follow-up views conducted by the James Webb Space Telescope, showed that the planet is adding material about eight times faster than a few months earlier and gobbling up gas and dust at a record rate of 6.6 billion tons (6 billion metric tons) per second.
Related article
The Earth-size exoplanet TRAPPIST-1 e, depicted at the lower right, is silhouetted as it passes in front of its flaring host star in this artist’s concept of the TRAPPIST-1 system.
Earth-like exoplanet could be habitable, and astronomers may know soon
The unusual burst of activity is the strongest growth rate ever recorded for a planet of any kind, said lead study author Victor Almendros-Abad, an astronomer at the Palermo Astronomical Observatory of the National Institute for Astrophysics in Italy, and is shedding light on the tumultuous formation and evolution of planets.
“We’ve caught this newborn rogue planet in the act of gobbling up stuff at a furious pace,” said senior coauthor Ray Jayawardhana, provost and professor of physics and astronomy at Johns Hopkins University, in a statement.
“Monitoring its behavior over the past few months, with two of the most powerful telescopes on the ground and in space, we have captured a rare glimpse into the baby phase of isolated objects not much heftier than Jupiter. Their infancy appears to be much more tumultuous than we had realized.”
PedroHoory
14 Oct 25 at 7:09 am
купить диплом в новочеркасске [url=http://rudik-diplom5.ru]купить диплом в новочеркасске[/url] .
Diplomi_kdma
14 Oct 25 at 7:09 am
купить диплом машиниста [url=https://www.rudik-diplom8.ru]купить диплом машиниста[/url] .
Diplomi_qpMt
14 Oct 25 at 7:09 am
рулонные шторы это [url=http://www.rulonnaya-shtora-s-elektroprivodom.ru]http://www.rulonnaya-shtora-s-elektroprivodom.ru[/url] .
rylonnaya shtora s elektroprivodom_wcKt
14 Oct 25 at 7:10 am
купить диплом регистрацией [url=http://frei-diplom6.ru]купить диплом регистрацией[/url] .
Diplomi_nuOl
14 Oct 25 at 7:10 am
электрокарниз москва [url=www.elektrokarnizy797.ru/]www.elektrokarnizy797.ru/[/url] .
elektrokarnizi_ggMl
14 Oct 25 at 7:11 am
купить диплом в новотроицке [url=https://rudik-diplom11.ru/]купить диплом в новотроицке[/url] .
Diplomi_viMi
14 Oct 25 at 7:11 am
Получить диплом любого ВУЗа можем помочь. Купить диплом бакалавра в Москве – [url=http://diplomybox.com/kupit-diplom-bakalavra-v-moskve/]diplomybox.com/kupit-diplom-bakalavra-v-moskve[/url]
Cazrwwv
14 Oct 25 at 7:11 am
Joined $MTAUR rush—prizes await. ICO’s tokenomics sound. Mazes challenging.
minotaurus presale
WilliamPargy
14 Oct 25 at 7:12 am
карниз с приводом [url=www.karniz-elektroprivodom.ru]www.karniz-elektroprivodom.ru[/url] .
karniz elektroprivodom shtor kypit_dsei
14 Oct 25 at 7:12 am
разрешение на перепланировку нежилого помещения не требуется [url=https://pereplanirovka-nezhilogo-pomeshcheniya11.ru]https://pereplanirovka-nezhilogo-pomeshcheniya11.ru[/url] .
pereplanirovka nejilogo pomesheniya_duer
14 Oct 25 at 7:12 am
купить диплом о среднем специальном образовании с занесением в реестр [url=frei-diplom4.ru]купить диплом о среднем специальном образовании с занесением в реестр[/url] .
Diplomi_cjOl
14 Oct 25 at 7:14 am
купить диплом повара [url=http://rudik-diplom8.ru]купить диплом повара[/url] .
Diplomi_liMt
14 Oct 25 at 7:15 am
купить диплом в троицке [url=www.rudik-diplom11.ru/]www.rudik-diplom11.ru/[/url] .
Diplomi_dqMi
14 Oct 25 at 7:17 am
автоматические рулонные шторы на окна [url=rulonnaya-shtora-s-elektroprivodom.ru]rulonnaya-shtora-s-elektroprivodom.ru[/url] .
rylonnaya shtora s elektroprivodom_crKt
14 Oct 25 at 7:17 am
Take a look at my web-site; High stake poker
High stake poker
14 Oct 25 at 7:18 am
перепланировка нежилых помещений [url=www.pereplanirovka-nezhilogo-pomeshcheniya9.ru/]перепланировка нежилых помещений[/url] .
pereplanirovka nejilogo pomesheniya_fpKl
14 Oct 25 at 7:19 am
электрокарнизы для штор цена [url=http://karniz-elektroprivodom.ru]электрокарнизы для штор цена[/url] .
karniz elektroprivodom shtor kypit_nfei
14 Oct 25 at 7:20 am
согласование перепланировки в нежилом здании [url=http://www.pereplanirovka-nezhilogo-pomeshcheniya11.ru]согласование перепланировки в нежилом здании[/url] .
pereplanirovka nejilogo pomesheniya_uqer
14 Oct 25 at 7:20 am
купить электрические рулонные шторы [url=https://rulonnaya-shtora-s-elektroprivodom.ru]https://rulonnaya-shtora-s-elektroprivodom.ru[/url] .
rylonnaya shtora s elektroprivodom_gpKt
14 Oct 25 at 7:20 am
купить диплом о высшем образовании с занесением в реестр в кемерово [url=https://www.frei-diplom4.ru]купить диплом о высшем образовании с занесением в реестр в кемерово[/url] .
Diplomi_zdOl
14 Oct 25 at 7:21 am
натяжные потолки потолочкин отзывы [url=https://stretch-ceilings-samara-1.ru/]stretch-ceilings-samara-1.ru[/url] .
natyajnie potolki samara_fgsl
14 Oct 25 at 7:21 am
В данной статье вы найдете комплексный подход к изучению насущных тем. Мы комбинируем теоретические сведения с практическими советами, чтобы читатель мог не только понять проблему, но и найти пути её решения.
Следуйте по ссылке – https://dadai-crypto.com/coincheck-accumulation
Rickyslack
14 Oct 25 at 7:21 am
I think this is among the most significant info for me.
And i am glad reading your article. But wanna remark on some general things, The web site style is great, the articles is really
great : D. Good job, cheers
sports jerseys
14 Oct 25 at 7:23 am
Why users still use to read news papers when in this technological globe all is presented on web?
hqd
14 Oct 25 at 7:23 am
oral
Brentsek
14 Oct 25 at 7:24 am
купить диплом в новотроицке [url=https://rudik-diplom1.ru]купить диплом в новотроицке[/url] .
Diplomi_rher
14 Oct 25 at 7:24 am
купить диплом агронома [url=https://rudik-diplom5.ru]купить диплом агронома[/url] .
Diplomi_ksma
14 Oct 25 at 7:25 am
потолочник натяжные потолки самара [url=https://www.natyazhnye-potolki-samara-1.ru]https://www.natyazhnye-potolki-samara-1.ru[/url] .
natyajnie potolki samara_maor
14 Oct 25 at 7:26 am
диплом о высшем образовании с занесением в реестр купить [url=www.frei-diplom6.ru]диплом о высшем образовании с занесением в реестр купить[/url] .
Diplomi_quOl
14 Oct 25 at 7:26 am
автоматический карниз для штор [url=https://www.karniz-elektroprivodom.ru]https://www.karniz-elektroprivodom.ru[/url] .
karniz elektroprivodom shtor kypit_irei
14 Oct 25 at 7:26 am
купить диплом о высшем образовании проведенный [url=www.frei-diplom4.ru/]купить диплом о высшем образовании проведенный[/url] .
Diplomi_diOl
14 Oct 25 at 7:26 am