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=www.rulonnaya-shtora-s-elektroprivodom.ru]www.rulonnaya-shtora-s-elektroprivodom.ru[/url] .
rylonnaya shtora s elektroprivodom_wcKt
14 Oct 25 at 2:09 am
купить диплом с реестром вуза [url=http://frei-diplom2.ru/]купить диплом с реестром вуза[/url] .
Diplomi_enEa
14 Oct 25 at 2:10 am
электрокарниз двухрядный [url=http://www.karniz-elektroprivodom.ru]http://www.karniz-elektroprivodom.ru[/url] .
karniz elektroprivodom shtor kypit_qhei
14 Oct 25 at 2:12 am
Hi i am kavin, its my first occasion to commenting anyplace,
when i read this article i thought i could
also create comment due to this good article.
Vaultraze Fund
14 Oct 25 at 2:12 am
https://britmedsdirect.com/# UK online pharmacy without prescription
HerbertScacy
14 Oct 25 at 2:12 am
рулонные шторы с электроприводом цена [url=http://www.rulonnaya-shtora-s-elektroprivodom.ru]рулонные шторы с электроприводом цена[/url] .
rylonnaya shtora s elektroprivodom_waKt
14 Oct 25 at 2:13 am
В клинике используются современные методы, ориентированные на индивидуальные потребности каждого пациента. Это помогает учитывать как физическое состояние, так и психологические особенности.
Исследовать вопрос подробнее – [url=https://narcologicheskaya-klinika-tver0.ru/]вывод наркологическая клиника[/url]
Franksix
14 Oct 25 at 2:13 am
карниз с электроприводом [url=https://karniz-elektroprivodom.ru/]карниз с электроприводом[/url] .
karniz elektroprivodom shtor kypit_hxei
14 Oct 25 at 2:14 am
https://m-bsme.lat
Hermannalia
14 Oct 25 at 2:14 am
купить диплом с проводкой моих [url=http://www.frei-diplom3.ru]купить диплом с проводкой моих[/url] .
Diplomi_dfKt
14 Oct 25 at 2:15 am
регистрация перепланировки нежилого помещения [url=https://pereplanirovka-nezhilogo-pomeshcheniya11.ru/]регистрация перепланировки нежилого помещения[/url] .
pereplanirovka nejilogo pomesheniya_dler
14 Oct 25 at 2:16 am
купить диплом техникума ссср в кемерово [url=http://frei-diplom9.ru]купить диплом техникума ссср в кемерово[/url] .
Diplomi_bbea
14 Oct 25 at 2:17 am
купить диплом в ейске [url=www.rudik-diplom2.ru]www.rudik-diplom2.ru[/url] .
Diplomi_hopi
14 Oct 25 at 2:18 am
где купить дипломы медсестры [url=http://frei-diplom13.ru/]где купить дипломы медсестры[/url] .
Diplomi_bakt
14 Oct 25 at 2:20 am
best games
Brentsek
14 Oct 25 at 2:20 am
карнизы для штор купить в москве [url=https://karniz-elektroprivodom.ru/]карнизы для штор купить в москве[/url] .
karniz elektroprivodom shtor kypit_sxei
14 Oct 25 at 2:21 am
купить диплом о высшем образовании легально [url=frei-diplom2.ru]купить диплом о высшем образовании легально[/url] .
Diplomi_poEa
14 Oct 25 at 2:23 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/]строительство домов мск[/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/stroitelstvo_domov_iz_keramiki/
купить проект дома со сметой
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.”
KennethbeT
14 Oct 25 at 2:24 am
электрическая беговая дорожка складная Скамья для жима купить — базовый элемент для силовых тренировок. Регулируемые модели с наклоном 0-90° для жима лежа, сидя или под углом. Стальная рама с порошковым покрытием, мягкий банкет шириной 25 см, нагрузка 300-500 кг. Варианты с подставками для штанги или без. Идеальна для груди, трицепсов и плеч. Размеры 120×40 см, вес 15-25 кг. Цены от 5 000 до 20 000 рублей, бренды ATLET или DFC. Скамья помогает в гипертрофии мышц, улучшает силу и форму торса.
JamesDrips
14 Oct 25 at 2:25 am
https://www.giantbomb.com/profile/candetoxblend/
Aprobar un test antidoping puede ser un momento critico. Por eso, se desarrollo una solucion cientifica desarrollada en Canada.
Su mezcla potente combina nutrientes esenciales, lo que prepara tu organismo y oculta temporalmente los rastros de toxinas. El resultado: una prueba sin riesgos, lista para cumplir el objetivo.
Lo mas valioso es su accion rapida en menos de 2 horas. A diferencia de metodos caseros, no promete limpiezas magicas, sino una herramienta puntual que funciona cuando lo necesitas.
Estos productos están diseñados para colaborar a los consumidores a depurar su cuerpo de residuos no deseadas, especialmente esas relacionadas con el consumo de cannabis u otras sustancias ilícitas.
El buen detox para examen de pipí debe ofrecer resultados rápidos y confiables, en particular cuando el tiempo para desintoxicarse es limitado. En el mercado actual, hay muchas opciones, pero no todas garantizan un proceso seguro o fiable.
Qué funciona un producto detox? En términos simples, estos suplementos funcionan acelerando la eliminación de metabolitos y toxinas a través de la orina, reduciendo su presencia hasta quedar por debajo del nivel de detección de algunos tests. Algunos funcionan en cuestión de horas y su impacto puede durar entre 4 a seis horas.
Es fundamental combinar estos productos con correcta hidratación. Beber al menos dos litros de agua diariamente antes y después del uso del detox puede mejorar los efectos. Además, se aconseja evitar alimentos grasos y bebidas azucaradas durante el proceso de uso.
Los mejores productos de detox para orina incluyen ingredientes como extractos de naturales, vitaminas del complejo B y minerales que favorecen el funcionamiento de los sistemas y la función hepática. Entre las marcas más vendidas, se encuentran aquellas que tienen 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 temprana. Mientras más larga sea la abstinencia, mayor será la efectividad del producto. Por eso, combinar la planificación con el uso correcto del detox es clave.
Un error común es pensar que todos los detox actúan idéntico. Existen diferencias en formulación, sabor, método de ingesta y duración del resultado. Algunos vienen en envase líquido, otros en cápsulas, y varios combinan ambos.
Además, hay productos que agregan fases de preparación o limpieza previa al día del examen. Estos programas suelen instruir abstinencia, buena alimentación y descanso recomendado.
Por último, es importante recalcar que todo detox garantiza 100% de éxito. Siempre hay variables individuales como metabolismo, historial de consumo, y tipo de examen. Por ello, es vital seguir las instrucciones del fabricante y no descuidarse.
Miles de profesionales ya han validado su seguridad. Testimonios reales mencionan resultados exitosos en pruebas preocupacionales.
Si no deseas dejar nada al azar, esta solucion te ofrece confianza.
JuniorShido
14 Oct 25 at 2:25 am
купить диплом о техническом образовании с занесением в реестр [url=https://www.frei-diplom3.ru]https://www.frei-diplom3.ru[/url] .
Diplomi_mjKt
14 Oct 25 at 2:25 am
рулонные шторы на пластиковые окна с электроприводом [url=rulonnaya-shtora-s-elektroprivodom.ru]рулонные шторы на пластиковые окна с электроприводом[/url] .
rylonnaya shtora s elektroprivodom_nwKt
14 Oct 25 at 2:26 am
перепланировка офиса согласование [url=https://www.pereplanirovka-nezhilogo-pomeshcheniya11.ru]перепланировка офиса согласование[/url] .
pereplanirovka nejilogo pomesheniya_urer
14 Oct 25 at 2:27 am
карнизы с электроприводом купить [url=http://karniz-shtor-elektroprivodom.ru]карнизы с электроприводом купить[/url] .
karniz dlya shtor s elektroprivodom_ioer
14 Oct 25 at 2:28 am
https://britmedsdirect.shop/# Brit Meds Direct
HerbertScacy
14 Oct 25 at 2:28 am
Spot on with this write-up, I truly feel this site needs much more attention. I’ll probably be back
again to read more, thanks for the information!
کلاهبرداری آنلاین
14 Oct 25 at 2:28 am
купить проведенный диплом кого [url=www.frei-diplom6.ru]купить проведенный диплом кого[/url] .
Diplomi_viOl
14 Oct 25 at 2:29 am
куплю диплом о высшем образовании [url=www.rudik-diplom10.ru/]куплю диплом о высшем образовании[/url] .
Diplomi_atSa
14 Oct 25 at 2:30 am
купить диплом с занесением в реестр тюмень [url=www.frei-diplom2.ru]купить диплом с занесением в реестр тюмень[/url] .
Diplomi_lgEa
14 Oct 25 at 2:31 am
согласование перепланировки нежилых помещений [url=https://www.pereplanirovka-nezhilogo-pomeshcheniya9.ru]https://www.pereplanirovka-nezhilogo-pomeshcheniya9.ru[/url] .
pereplanirovka nejilogo pomesheniya_pvKl
14 Oct 25 at 2:32 am
купить проведенный диплом кого [url=www.frei-diplom3.ru]купить проведенный диплом кого[/url] .
Diplomi_zsKt
14 Oct 25 at 2:32 am
Why people still make use of to read news papers when in this technological world the whole thing
is existing on net?
the wave academy
14 Oct 25 at 2:34 am
купить диплом медсестры [url=https://www.frei-diplom13.ru]купить диплом медсестры[/url] .
Diplomi_mikt
14 Oct 25 at 2:34 am
купить старый диплом техникума в спб [url=http://www.frei-diplom9.ru]купить старый диплом техникума в спб[/url] .
Diplomi_ofea
14 Oct 25 at 2:34 am
рулонные шторы с электроприводом купить в москве [url=http://rulonnaya-shtora-s-elektroprivodom.ru]http://rulonnaya-shtora-s-elektroprivodom.ru[/url] .
rylonnaya shtora s elektroprivodom_euKt
14 Oct 25 at 2:34 am
masturbate
Brentsek
14 Oct 25 at 2:35 am
купить диплом с занесением в реестр в москве [url=www.frei-diplom1.ru]купить диплом с занесением в реестр в москве[/url] .
Diplomi_rhOi
14 Oct 25 at 2:36 am
электрические гардины [url=http://karniz-elektroprivodom.ru/]электрические гардины[/url] .
karniz elektroprivodom shtor kypit_iyei
14 Oct 25 at 2:37 am
купить диплом с занесением в реестры [url=https://www.frei-diplom5.ru]купить диплом с занесением в реестры[/url] .
Diplomi_dsPa
14 Oct 25 at 2:38 am
купить проведенный диплом [url=http://frei-diplom2.ru]купить проведенный диплом[/url] .
Diplomi_zbEa
14 Oct 25 at 2:39 am
карниз моторизованный [url=http://karniz-elektroprivodom.ru]http://karniz-elektroprivodom.ru[/url] .
karniz elektroprivodom shtor kypit_wvei
14 Oct 25 at 2:39 am
автоматические рулонные шторы [url=www.rulonnaya-shtora-s-elektroprivodom.ru]автоматические рулонные шторы[/url] .
rylonnaya shtora s elektroprivodom_ugKt
14 Oct 25 at 2:39 am
I have been exploring for a little bit for any high-quality articles or weblog
posts in this kind of space . Exploring in Yahoo I finally
stumbled upon this site. Reading this info So i’m
satisfied to exhibit that I’ve a very excellent uncanny feeling I
found out exactly what I needed. I so much undoubtedly will make certain to
do not put out of your mind this web site and give
it a look on a constant basis.
Wonderful
14 Oct 25 at 2:39 am
купить диплом с занесением в реестр в красноярске [url=http://frei-diplom3.ru]http://frei-diplom3.ru[/url] .
Diplomi_aaKt
14 Oct 25 at 2:40 am
купить диплом медсестры [url=https://frei-diplom13.ru/]купить диплом медсестры[/url] .
Diplomi_lhkt
14 Oct 25 at 2:40 am
как купить диплом в колледже [url=http://frei-diplom9.ru/]как купить диплом в колледже[/url] .
Diplomi_puea
14 Oct 25 at 2:41 am
best games
Brentsek
14 Oct 25 at 2:42 am
перепланировка нежилого здания [url=https://pereplanirovka-nezhilogo-pomeshcheniya11.ru/]перепланировка нежилого здания[/url] .
pereplanirovka nejilogo pomesheniya_ycer
14 Oct 25 at 2:42 am
Автоматические гаражные ворота давно перестали быть роскошью и стали необходимым элементом комфортной жизни. Наши автоматические ворота сочетают надёжность проверенных европейских механизмов с элегантным дизайном, который гармонично впишется в архитектуру любого здания. Мы предлагаем полный цикл услуг: от профессиональной консультации и точного замера до установки под ключ и гарантийного обслуживания. Доверьте безопасность своего дома профессионалам — получите бесплатный расчёт стоимости уже сегодня: ворота
CraigStaps
14 Oct 25 at 2:42 am
карниз для штор электрический [url=karniz-elektroprivodom.ru]карниз для штор электрический[/url] .
karniz elektroprivodom shtor kypit_ncei
14 Oct 25 at 2:45 am