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!
Этот обзор предлагает структурированное изложение информации по актуальным вопросам. Материал подан так, чтобы даже новичок мог быстро освоиться в теме и начать использовать полученные знания в практике.
Получить больше информации – https://stokeanimalrights.com/content-coming-soon
Billybruic
15 Oct 25 at 9:51 am
Seth Gamble
Brentsek
15 Oct 25 at 9:52 am
Эта информационная статья содержит полезные факты, советы и рекомендации, которые помогут вам быть в курсе последних тенденций и изменений в выбранной области. Материал составлен так, чтобы быть полезным и понятным каждому.
Хочешь знать всё? – https://kayamgroupe.com/appartements-disponibles-kayam-groupe-immobilier
Williamexirm
15 Oct 25 at 9:52 am
купить диплом в бердске [url=www.rudik-diplom2.ru/]www.rudik-diplom2.ru/[/url] .
Diplomi_mxpi
15 Oct 25 at 9:54 am
купить диплом о высшем образовании проведенный [url=https://frei-diplom1.ru/]купить диплом о высшем образовании проведенный[/url] .
Diplomi_enOi
15 Oct 25 at 9:54 am
купить диплом логопеда [url=https://rudik-diplom10.ru]купить диплом логопеда[/url] .
Diplomi_mzSa
15 Oct 25 at 9:54 am
Right now it looks like Expression Engine is the preferred blogging platform available right now.
(from what I’ve read) Is that what you’re using on your blog?
Vaultraze Fund
15 Oct 25 at 9:54 am
Hi to every one, it’s actually a pleasant for me to pay
a visit this site, it consists of precious Information.
Dr. Cherrington
15 Oct 25 at 9:55 am
Alas, even within tⲟp schools, kids demand additional mathematics emphasis tⲟ succeed іn heuristics,
whɑt opens opportunities to gifted courses.
Nanyang Junior College champs multilingual quality,
mixing cultural heritage ѡith modern-daу education to nurture positive global residents.
Advanced centers support strong programs іn STEM, arts,
ɑnd liberal arts, promoting innovation ɑnd imagination. Students grow іn a dynamic neighborhood ᴡith opportunities fоr leadership and international exchanges.
Thee college’ѕ focus on worths and resilience constructs character
tߋgether with scholastic expertise. Graduates
master t᧐p organizations, continuing a legacy ᧐f achievement аnd cultural gratitude.
Tampines Meridian Junior College, born fгom the dynamic merger of Tampines Junior
College ɑnd Meridian Junior College, pгovides ɑn innovative and culturally rich education highlighted
Ьy specialized electives іn drama and Malay language, nurturing
meaningful аnd multilingual skills in a forward-thinking community.
Ꭲhe college’s cutting-edge facilities, including theater ɑreas, commerce simulation laboratories,
ɑnd science innovation hubs, support diverse academic streams thbat motivate interdisciplinary
exploration ɑnd uѕeful skill-building across arts,
sciences, аnd service. Talent development programs,
combined ᴡith abroaad immersion trips аnd cultural festivals, foster strong management qualities, cultural awareness, аnd adaptability to international characteristics.
Ԝithin a caring and empathetic school culture, students
take ⲣart in wellness initiatives, peer assistance ɡroups, and
co-curricular clubs that promote resilience,
psychological intelligence, ɑnd collective spirit.
Аѕ a result, Tampines Meridian Junior College’ѕ trainees accomplish holistic growth
аnd are well-prepared to deal wіth global obstacles, emerging
аs confident, versatile people ready fоr university success аnd beyоnd.
Wow, math serves аs the base pillar for primary schooling, assisting youngsters fоr spatial analysis іn building paths.
Eh eh, composed pom рi pi, mathematics гemains part from the higһest disciplines at Junior College, building
base fоr A-Level calculus.
Alas, primary mathematics instructs real-ԝorld implementations sucһ
as money management, thus mɑke ѕure yoսr youngster ɡets it right starting earⅼʏ.
Eh eh, composed pom рi pi, maths гemains part in thе leading
topics Ԁuring Junior College, laying groundwork t᧐ A-Level advanced math.
A-level excellence showcases ʏour potential to mentors аnd future bosses.
Parents, fear tһe difference hor, mathematics foundation гemains critical аt Junior College fоr grasping data, essential f᧐r toԀay’s digital ѕystem.
Wah lao, nno matter tһough institution proves hiɡh-еnd, math serves аs thе mɑke-or-break
subject fߋr building confidence гegarding numbeгs.
my site – ACS I
ACS I
15 Oct 25 at 9:55 am
1win qeydiyyat [url=http://1win5005.com/]http://1win5005.com/[/url]
1win_mxml
15 Oct 25 at 9:56 am
диплом техникума казахстана купить [url=http://frei-diplom8.ru/]диплом техникума казахстана купить[/url] .
Diplomi_xpsr
15 Oct 25 at 9:57 am
купить диплом для иностранцев [url=www.rudik-diplom13.ru]купить диплом для иностранцев[/url] .
Diplomi_skon
15 Oct 25 at 9:57 am
https://nrbfriends.com/read-blog/64238
jndamzx
15 Oct 25 at 9:58 am
Публикация предлагает читателю не просто информацию, а инструменты для анализа и саморазвития. Мы стимулируем критическое мышление, предлагая различные точки зрения и призывая к самостоятельному поиску решений.
Подробнее – https://melty-app.com/douhan/douhan-miryoku
Danielwrill
15 Oct 25 at 9:59 am
натяжные потолки потолочкин отзывы [url=http://www.natyazhnye-potolki-samara-2.ru]http://www.natyazhnye-potolki-samara-2.ru[/url] .
natyajnie potolki samara_avPi
15 Oct 25 at 9:59 am
купить диплом об окончании техникума в самаре [url=http://frei-diplom12.ru/]купить диплом об окончании техникума в самаре[/url] .
Diplomi_zbPt
15 Oct 25 at 10:00 am
This is a topic that is close to my heart… Best wishes!
Exactly where are your contact details though?
Aluminium Profile Bending Machine
15 Oct 25 at 10:01 am
диплом колледжа купить в волгограде [url=frei-diplom11.ru]frei-diplom11.ru[/url] .
Diplomi_jgsa
15 Oct 25 at 10:02 am
купить диплом с проведением [url=https://frei-diplom1.ru]купить диплом с проведением[/url] .
Diplomi_bsOi
15 Oct 25 at 10:02 am
купить диплом в йошкар-оле [url=https://www.rudik-diplom10.ru]купить диплом в йошкар-оле[/url] .
Diplomi_yaSa
15 Oct 25 at 10:04 am
диплом техникума колледжа купить пять плюс [url=http://www.frei-diplom8.ru]диплом техникума колледжа купить пять плюс[/url] .
Diplomi_ntsr
15 Oct 25 at 10:05 am
купить диплом в кирове [url=https://rudik-diplom13.ru]купить диплом в кирове[/url] .
Diplomi_ieon
15 Oct 25 at 10:05 am
https://telegra.ph/Mavic-3t-kupit-v-moskve-10-12-3
RonaldZer
15 Oct 25 at 10:06 am
After looking into a number of the blog articles on your website,
I really like your way of writing a blog. I added
it to my bookmark webpage list and will be checking back soon. Please check out my
website too and let me know your opinion.
Paito Warna Cambodia Forum
15 Oct 25 at 10:06 am
купить диплом зарегистрированный в реестре [url=http://www.frei-diplom3.ru]http://www.frei-diplom3.ru[/url] .
Diplomi_puKt
15 Oct 25 at 10:06 am
как купить проведенный диплом отзывы [url=http://www.frei-diplom2.ru]http://www.frei-diplom2.ru[/url] .
Diplomi_dvEa
15 Oct 25 at 10:06 am
1win mobil versiya [url=1win5004.com]1win mobil versiya[/url]
1win_mfoi
15 Oct 25 at 10:07 am
купить диплом инженера механика [url=http://www.rudik-diplom7.ru]купить диплом инженера механика[/url] .
Diplomi_umPl
15 Oct 25 at 10:08 am
купить диплом техникума ссср в оренбурге [url=https://www.frei-diplom12.ru]купить диплом техникума ссср в оренбурге[/url] .
Diplomi_khPt
15 Oct 25 at 10:08 am
Эта информационная заметка содержит увлекательные сведения, которые могут вас удивить! Мы собрали интересные факты, которые сделают вашу жизнь ярче и полнее. Узнайте нечто новое о привычных аспектах повседневности и откройте для себя удивительный мир информации.
Что ещё? Расскажи всё! – https://res-funeral.jp/info/?p=266
Kevinacart
15 Oct 25 at 10:08 am
Hey very nice web site!! Guy .. Excellent .. Superb .. I will bookmark your web site
and take the feeds additionally? I’m satisfied to search out numerous
helpful info right here within the submit, we’d like develop extra techniques on this regard, thank
you for sharing. . . . . .
Finetra AI
15 Oct 25 at 10:08 am
Great post. I was checking continuously this blog and I am inspired!
Very helpful information specifically the closing phase 🙂 I take care of such info much.
I was looking for this certain information for a
very long time. Thank you and best of luck.
toko resmi interactive flat panel Bogor
15 Oct 25 at 10:09 am
сколько стоит купить диплом медсестры [url=http://frei-diplom13.ru]сколько стоит купить диплом медсестры[/url] .
Diplomi_afkt
15 Oct 25 at 10:09 am
диплом техникума старого образца купить [url=frei-diplom9.ru]диплом техникума старого образца купить[/url] .
Diplomi_hlea
15 Oct 25 at 10:09 am
купить диплом техникума в кирове [url=https://frei-diplom8.ru/]купить диплом техникума в кирове[/url] .
Diplomi_issr
15 Oct 25 at 10:11 am
купить диплом в новочебоксарске [url=www.rudik-diplom2.ru]www.rudik-diplom2.ru[/url] .
Diplomi_ndpi
15 Oct 25 at 10:12 am
Напротив, после получения ресурсом
лицензии игроки начали хвалить честность и надежность сайта,
его конкурентоспособность на
фоне других заведений.
гама сайт казино
15 Oct 25 at 10:12 am
потолочкин самара [url=http://natyazhnye-potolki-samara-2.ru]http://natyazhnye-potolki-samara-2.ru[/url] .
natyajnie potolki samara_ayPi
15 Oct 25 at 10:14 am
кинешемский педагогический колледж диплом 1998 года купить [url=www.frei-diplom12.ru/]www.frei-diplom12.ru/[/url] .
Diplomi_qgPt
15 Oct 25 at 10:14 am
как купить легально диплом о высшем образовании [url=frei-diplom3.ru]как купить легально диплом о высшем образовании[/url] .
Diplomi_iaKt
15 Oct 25 at 10:14 am
я купил проведенный диплом [url=http://frei-diplom2.ru/]я купил проведенный диплом[/url] .
Diplomi_shEa
15 Oct 25 at 10:14 am
купить диплом с внесением в реестр [url=http://rudik-diplom6.ru]купить диплом с внесением в реестр[/url] .
Diplomi_vmKr
15 Oct 25 at 10:15 am
Эта обзорная заметка содержит ключевые моменты и факты по актуальным вопросам. Она поможет читателям быстро ориентироваться в теме и узнать о самых важных аспектах сегодня. Получите краткий курс по современной информации и оставайтесь в курсе событий!
Запросить дополнительные данные – https://gamap.es/hello-world
Davidjeali
15 Oct 25 at 10:16 am
Your way of describing everything in this article is
genuinely nice, all be capable of effortlessly know it, Thanks a lot.
norsk casino på nett
15 Oct 25 at 10:16 am
No matter if some one searches for his essential thing, therefore he/she wants to be available that in detail, therefore that thing is maintained over here.
Fairholt Cryptrix Legit Or Not
15 Oct 25 at 10:17 am
Этот обзорный материал предоставляет информационно насыщенные данные, касающиеся актуальных тем. Мы стремимся сделать информацию доступной и структурированной, чтобы читатели могли легко ориентироваться в наших выводах. Познайте новое с нашим обзором!
Ознакомиться с деталями – https://tecnohidraulicas.com.mx/product/pinza-de-electricista-9
AnthonyWrack
15 Oct 25 at 10:20 am
купить диплом программиста [url=http://rudik-diplom10.ru/]купить диплом программиста[/url] .
Diplomi_leSa
15 Oct 25 at 10:21 am
Hello, I read your blogs like every week. Your story-telling style is awesome,
keep doing what you’re doing!
Why confidence is the key to happiness
15 Oct 25 at 10:22 am
купить свидетельство о заключении брака [url=www.rudik-diplom3.ru]купить свидетельство о заключении брака[/url] .
Diplomi_tiei
15 Oct 25 at 10:23 am
компания потолочник [url=http://natyazhnye-potolki-samara-2.ru/]http://natyazhnye-potolki-samara-2.ru/[/url] .
natyajnie potolki samara_pxPi
15 Oct 25 at 10:23 am