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!
Диджитализация — ключ к успеху kraken зеркало kraken онион kraken онион тор кракен онион
RichardPep
18 Oct 25 at 9:15 pm
услуги по узакониванию перепланировки [url=http://soglasovanie-pereplanirovki-kvartiry14.ru/]http://soglasovanie-pereplanirovki-kvartiry14.ru/[/url] .
soglasovanie pereplanirovki kvartiri _doEl
18 Oct 25 at 9:16 pm
1xbet afrique apk 1xbet africain
parifoot-521
18 Oct 25 at 9:17 pm
telecharger 1xbet cameroun telecharger 1xbet cameroun
parifoot-379
18 Oct 25 at 9:18 pm
Link exchange is nothing else except it is just placing the other person’s web site link on your page at
appropriate place and other person will also do same for you.
https://ar.search.yahoo.com/mobile/s?ei=UTF-8&fl=0&p=site:www.telehao.com
18 Oct 25 at 9:18 pm
перепланировка [url=www.soglasovanie-pereplanirovki-kvartiry11.ru]www.soglasovanie-pereplanirovki-kvartiry11.ru[/url] .
soglasovanie pereplanirovki kvartiri _poMi
18 Oct 25 at 9:19 pm
компании занимащиеся офицально перепланировками квартир [url=https://soglasovanie-pereplanirovki-kvartiry3.ru/]https://soglasovanie-pereplanirovki-kvartiry3.ru/[/url] .
soglasovanie pereplanirovki kvartiri _srPi
18 Oct 25 at 9:21 pm
shopwithsmile – Very user-friendly site, easy navigation and clear product pages.
Stacy Alamillo
18 Oct 25 at 9:23 pm
https://tadalafiloexpress.com/# tadalafilo 5 mg precio
MickeySum
18 Oct 25 at 9:23 pm
современное медицинское оборудование [url=www.xn—–6kcdfldbfd2aga1bqjlbbb4b4d7d1fzd.xn--p1ai/]www.xn—–6kcdfldbfd2aga1bqjlbbb4b4d7d1fzd.xn--p1ai/[/url] .
oborydovanie medicinskoe_faOn
18 Oct 25 at 9:25 pm
куплю диплом медсестры в москве [url=https://www.frei-diplom14.ru]куплю диплом медсестры в москве[/url] .
Diplomi_buoi
18 Oct 25 at 9:26 pm
купить диплом в новом уренгое [url=http://rudik-diplom9.ru]http://rudik-diplom9.ru[/url] .
Diplomi_fbei
18 Oct 25 at 9:26 pm
согласование перепланировки [url=https://soglasovanie-pereplanirovki-kvartiry14.ru/]soglasovanie-pereplanirovki-kvartiry14.ru[/url] .
soglasovanie pereplanirovki kvartiri _jzEl
18 Oct 25 at 9:27 pm
chatroom
MichaelSig
18 Oct 25 at 9:27 pm
проект перепланировки жилого помещения [url=www.proekt-pereplanirovki-kvartiry17.ru]проект перепланировки жилого помещения[/url] .
proekt pereplanirovki kvartiri_kzml
18 Oct 25 at 9:27 pm
узаконить перепланировку стоимость [url=stoimost-soglasovaniya-pereplanirovki-kvartiry.ru]stoimost-soglasovaniya-pereplanirovki-kvartiry.ru[/url] .
stoimost soglasovaniya pereplanirovki kvartiri_jsPt
18 Oct 25 at 9:27 pm
услуги по узакониванию перепланировки [url=www.soglasovanie-pereplanirovki-kvartiry4.ru/]www.soglasovanie-pereplanirovki-kvartiry4.ru/[/url] .
soglasovanie pereplanirovki kvartiri _zjOr
18 Oct 25 at 9:27 pm
https://newyork.chaosads.com/item/1042134/
Harryamows
18 Oct 25 at 9:28 pm
официальный сайт мелбет бонус [url=melbetbonusy.ru]официальный сайт мелбет бонус[/url] .
melbet_vfOi
18 Oct 25 at 9:28 pm
согласование [url=https://soglasovanie-pereplanirovki-kvartiry11.ru]https://soglasovanie-pereplanirovki-kvartiry11.ru[/url] .
soglasovanie pereplanirovki kvartiri _ekMi
18 Oct 25 at 9:30 pm
проектная организация москва перепланировка [url=http://proekt-pereplanirovki-kvartiry17.ru]http://proekt-pereplanirovki-kvartiry17.ru[/url] .
proekt pereplanirovki kvartiri_fgml
18 Oct 25 at 9:30 pm
хоккей прогноз [url=http://prognozy-na-khokkej5.ru]хоккей прогноз[/url] .
prognozi na hokkei_foEa
18 Oct 25 at 9:30 pm
1xBet промокод актуальная информация о действующих предложениях и бонусных акциях для новых пользователей
Aaronawads
18 Oct 25 at 9:31 pm
узаконить перепланировку в москве цена [url=https://zakazat-proekt-pereplanirovki-kvartiry11.ru/]https://zakazat-proekt-pereplanirovki-kvartiry11.ru/[/url] .
zakazat proekt pereplanirovki kvartiri_lyet
18 Oct 25 at 9:31 pm
cialis kaufen ohne rezept: tadalafil 20 mg preis – cialis 20mg preis
RaymondNit
18 Oct 25 at 9:32 pm
Программа вывода из запоя в Воронеже от «Частного Медика 24» включает не только устранение физической зависимости, но и работу по восстановлению сна, гидратацию, лекарственную поддержку, а также психотерапию, чтобы помочь справиться не просто с запоем, но и с причинами, которые к нему привели.
Получить дополнительные сведения – [url=https://vyvod-iz-zapoya-v-stacionare-voronezh23.ru/]стационар вывод из запоя в воронеже[/url]
Anthonyvom
18 Oct 25 at 9:33 pm
перепланировка квартир [url=https://soglasovanie-pereplanirovki-kvartiry14.ru]https://soglasovanie-pereplanirovki-kvartiry14.ru[/url] .
soglasovanie pereplanirovki kvartiri _ufEl
18 Oct 25 at 9:34 pm
miglior prezzo Cialis originale: cialis prezzo – cialis generico
JosephPseus
18 Oct 25 at 9:34 pm
перепланировка помещения [url=http://soglasovanie-pereplanirovki-kvartiry3.ru/]http://soglasovanie-pereplanirovki-kvartiry3.ru/[/url] .
soglasovanie pereplanirovki kvartiri _jvPi
18 Oct 25 at 9:34 pm
Everything is very open with a precise description of the challenges.
It was definitely informative. Your website is useful. Thank you for sharing!
penalty unlimited inout
18 Oct 25 at 9:35 pm
It’s very trouble-free to find out any matter on web
as compared to books, as I found this article at this website.
Trusted Chips
18 Oct 25 at 9:35 pm
The Minotaurus presale raffle has me buzzing—$100K chance. $MTAUR’s utility real. Maze runner vibe addictive.
minotaurus token
WilliamPargy
18 Oct 25 at 9:38 pm
проект перепланировки квартиры для согласования цена москва [url=www.proekt-pereplanirovki-kvartiry16.ru]www.proekt-pereplanirovki-kvartiry16.ru[/url] .
proekt pereplanirovki kvartiri_haMl
18 Oct 25 at 9:38 pm
сколько стоит перепланировка в бти [url=http://stoimost-soglasovaniya-pereplanirovki-kvartiry.ru]http://stoimost-soglasovaniya-pereplanirovki-kvartiry.ru[/url] .
stoimost soglasovaniya pereplanirovki kvartiri_ejPt
18 Oct 25 at 9:39 pm
https://www.montessorijobsuk.co.uk/author/ucebyuhieya/
Anthonycam
18 Oct 25 at 9:39 pm
I simply couldn’t leave your site prior to suggesting that I actually loved the standard information an individual supply to your guests?
Is gonna be again frequently in order to inspect new posts
inout football game
18 Oct 25 at 9:40 pm
разработка проекта перепланировки [url=https://www.proekt-pereplanirovki-kvartiry17.ru]разработка проекта перепланировки[/url] .
proekt pereplanirovki kvartiri_euml
18 Oct 25 at 9:41 pm
перепланировка и согласование [url=soglasovanie-pereplanirovki-kvartiry11.ru]soglasovanie-pereplanirovki-kvartiry11.ru[/url] .
soglasovanie pereplanirovki kvartiri _kwMi
18 Oct 25 at 9:41 pm
Snagged some $MTAUR during stage 1; the price hike to next phase motivates quick action. Loving the hyper-casual vibe with blockchain perks. Early adopters win here.
minotaurus coin
WilliamPargy
18 Oct 25 at 9:41 pm
afrik foot pronostic africain foot
parifoot-606
18 Oct 25 at 9:41 pm
кракен обмен
кракен онион
JamesDaync
18 Oct 25 at 9:41 pm
Поскольку конфиденциальность и защита данных являются ключевыми аспектами при работе с даркнет-маркетплейсами, поиск надежного канала доступа играет определяющую роль. Применение непроверенных источников может привести к потере персональных данных и финансовых средств, ввиду чего необходимо соблюдать максимальную осторожность. [url=https://worldclasslearning.com/]кракен ссылка тор[/url] Используя данный линк, вы обретаете гарантированный доступ к широчайшему ассортименту площадки, включая рейтинги продавцов и круглосуточную техническую помощь. Данный метод позволяет полностью исключить риск перехода на мошеннический сайт и обеспечивает высочайшую степень конфиденциальности во время проведения любых операций.
Othex
18 Oct 25 at 9:43 pm
диплом медсестры с аккредитацией купить [url=www.frei-diplom14.ru/]диплом медсестры с аккредитацией купить[/url] .
Diplomi_rfoi
18 Oct 25 at 9:43 pm
перепланировка квартиры цена под ключ [url=https://stoimost-soglasovaniya-pereplanirovki-kvartiry.ru/]https://stoimost-soglasovaniya-pereplanirovki-kvartiry.ru/[/url] .
stoimost soglasovaniya pereplanirovki kvartiri_ycPt
18 Oct 25 at 9:45 pm
согласование перепланировки помещений [url=https://soglasovanie-pereplanirovki-kvartiry4.ru/]согласование перепланировки помещений[/url] .
soglasovanie pereplanirovki kvartiri _qiOr
18 Oct 25 at 9:46 pm
forexstrategyguide – Excellent course for scaling businesses, practical tips and strategies.
Gertie Prose
18 Oct 25 at 9:47 pm
сколько стоит узаконить перепланировку в бти [url=http://zakazat-proekt-pereplanirovki-kvartiry11.ru]http://zakazat-proekt-pereplanirovki-kvartiry11.ru[/url] .
zakazat proekt pereplanirovki kvartiri_kjet
18 Oct 25 at 9:49 pm
перепланировка квартиры дизайн проект [url=www.proekt-pereplanirovki-kvartiry17.ru]перепланировка квартиры дизайн проект[/url] .
proekt pereplanirovki kvartiri_gzml
18 Oct 25 at 9:49 pm
Если вы ищете надёжный и понятный путь к избавлению от алкогольной зависимости — вам стоит заглянуть в статью «Эффективные услуги лечения алкоголизма: путь к трезвой жизни». Получить больше информации – http://mymoscow.forum24.ru/?1-8-0-00000606-000-0-0-1754134302
Heathergak
18 Oct 25 at 9:49 pm
Мир программируется заново kraken официальные ссылки кракен онион тор кракен онион зеркало кракен даркнет маркет
RichardPep
18 Oct 25 at 9:50 pm