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://oksanaschool.ru
9 Sep 25 at 10:35 am
You really make iit appear so easy together with your presentation however I iin finding this topic to
be actually one thing which I believe I would by no measns
understand. It seems too complicated and very brlad for me.
I am havinng a look forward on your next submit, I wiull try to get
thhe clig of it!
Also visit my site oral
oral
9 Sep 25 at 10:35 am
darknet links darknet markets 2025 darknet market lists [url=https://privatedarknetmarket.com/ ]darknet markets links [/url]
Robertalima
9 Sep 25 at 10:35 am
Публикация приглашает вас исследовать неизведанное — от древних тайн до современных достижений науки. Вы узнаете, как случайные находки превращались в революции, а смелые мысли — в новые эры человеческого прогресса.
Продолжить изучение – https://akornas.ac.id/akornas-terlibat-dalam-fgd-membahas-implementasi-undang-undang-no-11-tahun-2022-tentang-keolahragaan
HerbertSop
9 Sep 25 at 10:36 am
seo интенсив [url=www.kursy-seo-4.ru]www.kursy-seo-4.ru[/url] .
kyrsi seo_vqPl
9 Sep 25 at 10:39 am
Hello there, just became aware of your blog through Google, and found that it is truly informative.
I’m going to watch out for brussels. I’ll be grateful if you continue
this in future. Lots of people will be benefited from your writing.
Cheers!
dewascatter
9 Sep 25 at 10:40 am
Big Max Diamonds and Wilds играть в Сикаа
Thomassmich
9 Sep 25 at 10:45 am
mostbet qeydiyyat necə olur [url=http://mostbet4145.ru]mostbet qeydiyyat necə olur[/url]
mostbet_lpot
9 Sep 25 at 10:45 am
обучение продвижению сайтов [url=https://www.kursy-seo-4.ru]обучение продвижению сайтов[/url] .
kyrsi seo_lhPl
9 Sep 25 at 10:47 am
Do you mind if I quote a couple of your posts as long as I provide credit and sources back
to your blog? My website is in the exact same niche as
yours and my visitors would really benefit from some of the information you provide here.
Please let me know if this ok with you. Cheers!
casino ohne einschränkung
9 Sep 25 at 10:49 am
This article will help the internet users for creating new website or even a weblog from start to end.
Bondi Bitspire
9 Sep 25 at 10:51 am
I blog frequently and I genuinely thank you for your content.
This article has truly peaked my interest.
I will bookmark your blog and keep checking
for new information about once a week. I opted in for your RSS feed as well.
MV66
9 Sep 25 at 10:51 am
seo курсы [url=kursy-seo-4.ru]seo курсы[/url] .
kyrsi seo_btPl
9 Sep 25 at 10:51 am
seo бесплатно [url=https://www.kursy-seo-1.ru]https://www.kursy-seo-1.ru[/url] .
kyrsi seo_wjkt
9 Sep 25 at 10:52 am
seo бесплатно [url=https://kursy-seo-4.ru]seo бесплатно[/url] .
kyrsi seo_hwPl
9 Sep 25 at 10:54 am
курсы seo [url=https://www.kursy-seo-1.ru]https://www.kursy-seo-1.ru[/url] .
kyrsi seo_fsmt
9 Sep 25 at 10:55 am
Приобрести диплом любого университета!
Мы изготавливаем дипломы любой профессии по разумным тарифам— [url=http://diplom-and-attestat.ru/]diplom-and-attestat.ru[/url]
Lazrnvm
9 Sep 25 at 10:55 am
https://slides.com/bienvenue1xbet
NathanNah
9 Sep 25 at 10:57 am
купить диплом с занесением [url=http://educ-ua4.ru/]купить диплом с занесением[/url] .
Diplomi_lePl
9 Sep 25 at 11:01 am
Купить диплом техникума в Харьков [url=www.educ-ua7.ru/]Купить диплом техникума в Харьков[/url] .
Diplomi_ewEr
9 Sep 25 at 11:01 am
Имеются блоки новостей по всем основным темам, поисковая система с учетом лингвистического анализа.
http://schoolmontessori.ru
9 Sep 25 at 11:02 am
обучение продвижению сайтов [url=https://kursy-seo-1.ru]https://kursy-seo-1.ru[/url] .
kyrsi seo_hckt
9 Sep 25 at 11:03 am
seo с нуля [url=https://kursy-seo-4.ru]https://kursy-seo-4.ru[/url] .
kyrsi seo_sjPl
9 Sep 25 at 11:03 am
1win самолетик [url=www.aviator-igra-1.ru]www.aviator-igra-1.ru[/url] .
aviator igra_slOn
9 Sep 25 at 11:04 am
darknet markets onion address nexus darknet market url nexus darknet market [url=https://darknetmarketstore.com/ ]dark market list [/url]
Jamespem
9 Sep 25 at 11:08 am
Hello there, You’ve done a fantastic job. I’ll certainly digg it and personally suggest to my friends.
I am sure they will be benefited from this site.
TrovianexiPro
9 Sep 25 at 11:08 am
курсы seo [url=https://kursy-seo-3.ru/]курсы seo[/url] .
kyrsi seo_bion
9 Sep 25 at 11:09 am
Игровая платформа Vavada привлекает внимание игроков.
Акции открывают доступ к бездепам.
Регулярные акции дают шанс выиграть больше.
Подборка развлечений поддерживается ведущими провайдерами.
Регистрация быстрая, и моментально приступить к игре.
Больше информации ищите здесь: онлайн казино vavada
StacymuB
9 Sep 25 at 11:10 am
seo курсы [url=https://kursy-seo-1.ru/]https://kursy-seo-1.ru/[/url] .
kyrsi seo_rlkt
9 Sep 25 at 11:11 am
seo базовый курc [url=http://kursy-seo-4.ru]http://kursy-seo-4.ru[/url] .
kyrsi seo_ezPl
9 Sep 25 at 11:13 am
mosbet [url=http://mostbet4171.ru/]http://mostbet4171.ru/[/url]
mostbet_beEt
9 Sep 25 at 11:13 am
hello!,I like your writing so much! percentage
we communicate extra approximately your post on AOL? I need a specialist on this space to
resolve my problem. Maybe that’s you! Taking a look forward to see you.
make money online
9 Sep 25 at 11:14 am
продвижение обучение [url=http://kursy-seo-4.ru]http://kursy-seo-4.ru[/url] .
kyrsi seo_xePl
9 Sep 25 at 11:16 am
I am genuinely grateful to the owner of this site who has shared this fantastic paragraph at
at this time.
Heating and cooling Richmond VA
9 Sep 25 at 11:16 am
seo онлайн [url=https://kursy-seo-2.ru/]kursy-seo-2.ru[/url] .
kyrsi seo_faEr
9 Sep 25 at 11:17 am
Nu Nerve looks like a promising supplement for anyone struggling with nerve discomfort and tingling sensations.
I like that it’s designed to support nerve health naturally, focusing on soothing discomfort while also improving overall nerve function. The blend of ingredients seems carefully chosen to help with circulation, reduce inflammation, and
restore balance, which is a big plus. If you’re looking
for a more natural way to manage nerve pain and improve quality of life,
Nu Nerve definitely seems worth checking out!
NU NERVE
9 Sep 25 at 11:18 am
В этой статье представлен занимательный и актуальный контент, который заставит вас задуматься. Мы обсуждаем насущные вопросы и проблемы, а также освещаем истории, которые вдохновляют на действия и изменения. Узнайте, что стоит за событиями нашего времени!
Только для своих – https://www.gracetochinese.org/cropped-mainpic01-1-1-jpg
Larryvex
9 Sep 25 at 11:19 am
The best of our site: https://www.greenwichodeum.com
CharlesDreag
9 Sep 25 at 11:20 am
учиться seo [url=https://kursy-seo-3.ru/]kursy-seo-3.ru[/url] .
kyrsi seo_vdon
9 Sep 25 at 11:20 am
New and relevant information: https://amt-games.com
EnriqueTycle
9 Sep 25 at 11:20 am
seo бесплатно [url=https://kursy-seo-1.ru/]https://kursy-seo-1.ru/[/url] .
kyrsi seo_romt
9 Sep 25 at 11:21 am
seo курсы [url=www.kursy-seo-2.ru]www.kursy-seo-2.ru[/url] .
kyrsi seo_uvEr
9 Sep 25 at 11:23 am
seo бесплатно [url=www.kursy-seo-1.ru/]www.kursy-seo-1.ru/[/url] .
kyrsi seo_wvmt
9 Sep 25 at 11:25 am
Want to have fun? melbet drugs Whores, drugs, casino. We have it all, any drugs are on sale.
drugs-378
9 Sep 25 at 11:26 am
seo онлайн [url=https://www.kursy-seo-2.ru]https://www.kursy-seo-2.ru[/url] .
kyrsi seo_lyEr
9 Sep 25 at 11:27 am
дипломы бывшего ссср купить [url=https://educ-ua4.ru/]дипломы бывшего ссср купить[/url] .
Diplomi_ujPl
9 Sep 25 at 11:28 am
Купить диплом колледжа в Хмельницкий [url=http://educ-ua7.ru/]Купить диплом колледжа в Хмельницкий[/url] .
Diplomi_rwEr
9 Sep 25 at 11:28 am
В этом интересном тексте собраны обширные сведения, которые помогут вам понять различные аспекты обсуждаемой темы. Мы разбираем детали и факты, делая акцент на важности каждого элемента. Не упустите возможность расширить свои знания и взглянуть на мир по-новому!
Узнать напрямую – https://lacapillahotel.com/hello-world
Samuelnaf
9 Sep 25 at 11:28 am
учиться seo [url=https://kursy-seo-3.ru/]kursy-seo-3.ru[/url] .
kyrsi seo_xuon
9 Sep 25 at 11:30 am
курсы по seo [url=http://kursy-seo-1.ru]http://kursy-seo-1.ru[/url] .
kyrsi seo_ydmt
9 Sep 25 at 11:35 am