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!
Грузии Гори
AnthonyDeeta
4 Sep 25 at 9:58 pm
раскрутка и продвижение сайта [url=https://internet-prodvizhenie-moskva.ru]раскрутка и продвижение сайта[/url] .
internet prodvijenie moskva_qdOr
4 Sep 25 at 9:58 pm
продвижение по трафику [url=https://internet-agentstvo-prodvizhenie-sajtov-seo.ru/]продвижение по трафику[/url] .
internet agentstvo prodvijenie saitov seo_gpot
4 Sep 25 at 9:59 pm
поисковое seo в москве [url=https://www.poiskovoe-seo-v-moskve.ru]https://www.poiskovoe-seo-v-moskve.ru[/url] .
poiskovoe seo v moskve_tcPr
4 Sep 25 at 10:03 pm
купить диплом нового образца [url=www.educ-ua17.ru/]купить диплом нового образца[/url] .
Diplomi_jtSl
4 Sep 25 at 10:04 pm
A Powerful Method To Get Back Libks article (https://opcmd60482.life3dblog.com)
https://opcmd60482.life3dblog.com
4 Sep 25 at 10:05 pm
Right now it seems like BlogEngine is the best blogging platform out there right now.
(from what I’ve read) Is that what you’re using on your blog?
چارت درسی مهندسی پزشکی
4 Sep 25 at 10:13 pm
продвижения сайта в google [url=http://internet-agentstvo-prodvizhenie-sajtov-seo.ru]продвижения сайта в google[/url] .
internet agentstvo prodvijenie saitov seo_hwot
4 Sep 25 at 10:15 pm
mostbet parolni unutdingizmi [url=www.mostbet4167.ru]mostbet parolni unutdingizmi[/url]
mostbet_luKa
4 Sep 25 at 10:16 pm
This is my first time go to see at here and i am actually impressed to read all at single place.
Tap to open
4 Sep 25 at 10:17 pm
поисковое продвижение сайта в интернете москва [url=poiskovoe-seo-v-moskve.ru]poiskovoe-seo-v-moskve.ru[/url] .
poiskovoe seo v moskve_snPr
4 Sep 25 at 10:19 pm
When some one searches for his essential thing, so he/she desires to be
available that in detail, therefore that thing is maintained over here.
adameve discount code
4 Sep 25 at 10:20 pm
комплексное продвижение сайтов москва [url=https://internet-agentstvo-prodvizhenie-sajtov-seo.ru/]комплексное продвижение сайтов москва[/url] .
internet agentstvo prodvijenie saitov seo_htot
4 Sep 25 at 10:21 pm
tele4
טלגראס כיוונים בית דגן
4 Sep 25 at 10:22 pm
Today, I went to the beach with my kids. I found a
sea shell and gave it to my 4 year old daughter and
said “You can hear the ocean if you put this to your ear.” She placed the shell to her
ear and screamed. There was a hermit crab inside and it pinched
her ear. She never wants to go back! LoL I know this is totally off topic but I had
to tell someone!
kontol besasr
4 Sep 25 at 10:22 pm
I must thank you for the efforts you’ve put in penning this blog.
I’m hoping to check out the same high-grade blog posts from you in the future
as well. In fact, your creative writing abilities has inspired me to get
my very own website now 😉
party rentals
4 Sep 25 at 10:23 pm
Everything is very open with a precise explanation of the challenges.
It was definitely informative. Your site is very
helpful. Thank you for sharing!
чемпион казино вход
4 Sep 25 at 10:24 pm
kraken darknet ссылка kraken onion
kraken onion ссылка
kraken onion зеркала
kraken рабочая ссылка onion
сайт kraken onion
kraken darknet
kraken darknet market
kraken darknet ссылка
сайт kraken darknet
kraken актуальные ссылки
кракен ссылка kraken
kraken официальные ссылки
kraken ссылка тор
kraken ссылка зеркало
kraken ссылка на сайт
kraken онион
kraken онион тор
кракен онион
кракен онион тор
кракен онион зеркало
кракен даркнет маркет
кракен darknet
кракен onion
кракен ссылка onion
кракен onion сайт
kra ссылка
kraken сайт
kraken актуальные ссылки
kraken зеркало
kraken ссылка зеркало
kraken зеркало рабочее
актуальные зеркала kraken
kraken сайт зеркала
kraken маркетплейс зеркало
кракен ссылка
кракен даркнет
RichardPep
4 Sep 25 at 10:25 pm
раскрутка и продвижение сайта [url=www.internet-agentstvo-prodvizhenie-sajtov-seo.ru]раскрутка и продвижение сайта[/url] .
internet agentstvo prodvijenie saitov seo_idot
4 Sep 25 at 10:25 pm
заказать анализ сайта [url=https://poiskovoe-seo-v-moskve.ru/]poiskovoe-seo-v-moskve.ru[/url] .
poiskovoe seo v moskve_qwPr
4 Sep 25 at 10:26 pm
купить диплом о высшем образовании украины [url=https://educ-ua17.ru]купить диплом о высшем образовании украины[/url] .
Diplomi_hcSl
4 Sep 25 at 10:26 pm
Гдов
Jameslak
4 Sep 25 at 10:26 pm
поисковое продвижение сайта в интернете москва [url=http://poiskovoe-seo-v-moskve.ru]http://poiskovoe-seo-v-moskve.ru[/url] .
poiskovoe seo v moskve_nfPr
4 Sep 25 at 10:30 pm
Wow, marvelous blog layout! How lengthy have you ever been running
a blog for? you made blogging look easy. The total look of your site
is great, as neatly as the content! http://nagatinos.getbb.ru/posting.php?mode=post&f=6&sid=c7258f92f5364b18bbcc63461eafaa6c
çat ruletka18+
4 Sep 25 at 10:30 pm
https://construires.fr/pag/code_promo_1xbet_inscription.html
EdwardStake
4 Sep 25 at 10:32 pm
трансформаторные подстанции купить [url=https://www.bisound.com/forum/showthread.php?t=1984168]трансформаторные подстанции купить[/url] .
transformatornie podstancii _naer
4 Sep 25 at 10:34 pm
Now I am going away to do my breakfast, afterward having my breakfast
coming again to read further news.
m98 bet
4 Sep 25 at 10:34 pm
ставки на спорт бишкек онлайн [url=https://mostbet4130.ru]https://mostbet4130.ru[/url]
mostbet_kg_bdpr
4 Sep 25 at 10:34 pm
I am in fact glad to glance at this website posts which contains plenty of
valuable facts, thanks for providing these data.
رتبه بندی دانشگاه های علوم پزشکی ایران
4 Sep 25 at 10:35 pm
Использование современных автоматизированных систем дозирования гарантирует точное введение медикаментов, что минимизирует риск передозировки и побочных эффектов. Постоянный мониторинг жизненно важных показателей позволяет врачу оперативно корректировать дозировки и адаптировать схему лечения в режиме реального времени.
Подробнее – https://наркология-дома1.рф/narkolog-na-dom-kruglosutochno-ryazan
Eddiebog
4 Sep 25 at 10:35 pm
mostbet yangi promo kod [url=http://mostbet4167.ru/]http://mostbet4167.ru/[/url]
mostbet_luKa
4 Sep 25 at 10:37 pm
seo partner [url=https://internet-agentstvo-prodvizhenie-sajtov-seo.ru/]https://internet-agentstvo-prodvizhenie-sajtov-seo.ru/[/url] .
internet agentstvo prodvijenie saitov seo_oqot
4 Sep 25 at 10:41 pm
продвижение сайтов в москве [url=http://poiskovoe-seo-v-moskve.ru]продвижение сайтов в москве[/url] .
poiskovoe seo v moskve_lzPr
4 Sep 25 at 10:46 pm
сколько стоит купить диплом специалиста [url=https://educ-ua17.ru]сколько стоит купить диплом специалиста[/url] .
Diplomi_vpSl
4 Sep 25 at 10:47 pm
Greetings! Very helpful advice within this post! It is the little changes that make the biggest
changes. Thanks for sharing!
اسامی بهترین مشاوران کنکور اصفهان
4 Sep 25 at 10:49 pm
Ищете женский портал о моде и красоте? Посетите сайт https://modnyeidei.ru/ и вы найдете большой выбор модных решений по оформлению маникюра и макияжа, эксклюзивный дизайн, секреты от мастериц, нестандартное сочетание. Правила ухода за женским телом и здоровьем и многое другое. Узнаете о самых горячих новинках в мире моды, посмотрите наглядные варианты и примерите к себе!
bonemasBor
4 Sep 25 at 10:50 pm
When I initially commented I clicked the “Notify me when new comments are added” checkbox and now
each time a comment is added I get four emails with the same comment.
Is there any way you can remove people from that service?
Thank you!
رفع مشکل کاهش ظرفیت رشته های پزشکی دندانپزشکی
4 Sep 25 at 10:51 pm
пленка клеющаяся для стен [url=https://samokleyushchayasya-plenka-1.ru/]samokleyushchayasya-plenka-1.ru[/url] .
plenka samokleushayasya zashitnaya_jtma
4 Sep 25 at 10:53 pm
купить диплом бакалавра цена [url=http://educ-ua17.ru]купить диплом бакалавра цена[/url] .
Diplomi_kzSl
4 Sep 25 at 10:53 pm
https://clubgti.com/wp-includes/articles/?codigo-promocional-1xbet_bono-de-bienvenida.html
Kennethtok
4 Sep 25 at 10:53 pm
Подгорица
RobertZoday
4 Sep 25 at 10:54 pm
дизайнерская мебель для гостиной [url=http://www.dizajnerskaya-mebel-1.ru]дизайнерская мебель для гостиной[/url] .
dizainerskaya mebel_pbEr
4 Sep 25 at 10:54 pm
Great website. A lot of helpful info here. I’m sending it to some friends ans also sharing in delicious.
And naturally, thank you in your sweat!
دانشگاه آزاد بهتره یا پردیس خودگردان
4 Sep 25 at 10:55 pm
https://t.me/anapaorgonit Оргониты что такое: Устройства из смолы, металла и кристаллов, предназначенные для преобразования энергии.
Anthonyarole
4 Sep 25 at 10:55 pm
Saya benar-benar mengapresiasi artikel ini karena membahas KUBET dan Situs Judi Bola Terlengkap
dengan sangat jelas.
Banyak orang sering mencari informasi seputar topik ini, dan artikel ini mampu memberikan penjelasan yang lengkap sekaligus mudah dipahami.
Tulisan ini terasa relevan bagi pembaca dari berbagai latar belakang, baik pemula maupun yang sudah berpengalaman.
Hal yang menarik adalah cara penyusunan konten yang runtut dan tidak
bertele-tele.
KUBET dan Situs Judi Bola Terlengkap tidak
hanya disebutkan sebagai judul, tetapi benar-benar dijelaskan dari
sisi keunggulan dan manfaatnya.
Bagi saya, ini membuat artikel terasa lebih berbobot dibandingkan tulisan lain yang
hanya sekilas membahas.
Selain itu, gaya bahasa yang digunakan sangat enak dibaca.
Dengan kalimat yang sederhana, penulis berhasil membuat topik yang mungkin cukup teknis menjadi mudah dipahami.
Hal ini tentu meningkatkan kualitas forum dan memberi nilai tambah bagi pembacanya.
Saya pribadi merasa tulisan ini memberikan sudut pandang baru yang jarang ditemui di artikel lain.
KUBET dan Situs Judi Bola Terlengkap memang sudah dikenal
luas, tapi penjelasan mendalam seperti ini sangat jarang ditemukan.
Oleh karena itu, saya yakin artikel ini akan sangat bermanfaat bagi siapa saja yang
membacanya.
Semoga ke depannya lebih banyak lagi tulisan dengan kualitas seperti
ini.
Ulasan yang detail, terpercaya, dan disajikan dengan bahasa sederhana pasti akan selalu
dicari.
Terima kasih kepada penulis karena sudah menghadirkan artikel yang sangat membantu.
KUBET
4 Sep 25 at 10:57 pm
cialis generique pas cher [url=https://intimapharmafrance.shop/#]commander cialis discretement[/url] commander cialis discretement
KennethOpike
4 Sep 25 at 10:57 pm
комплексное продвижение сайтов москва [url=https://internet-prodvizhenie-moskva.ru]комплексное продвижение сайтов москва[/url] .
internet prodvijenie moskva_uoOr
4 Sep 25 at 10:59 pm
https://longbeach-criminallawyer.com/media/pgs/plinko_demo__a_chave_para_dominar_o_jogo_antes_de_apostar_dinheiro_real.html
JamesWoure
4 Sep 25 at 11:01 pm
трансформаторные подстанции купить [url=http://www.fanfiction.borda.ru/?1-1-0-00000393-000-0-0]трансформаторные подстанции купить[/url] .
transformatornie podstancii _myer
4 Sep 25 at 11:02 pm
https://theomnibuzz.com/in-the-dynamic
Raymondvop
4 Sep 25 at 11:05 pm