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!
exploreandcreate – Checkout looked streamlined and payment options appear clearly displayed.
Candis Hinchliffe
28 Oct 25 at 3:20 pm
uniquelifestylehub – Product photos are sharp and description snippets are easy to read.
Muriel Shadley
28 Oct 25 at 3:21 pm
OMT’sdiagnostic evaluations customize ideas, assisting trainees fаll fߋr their one-оf-ɑ-kind math journey t᧐ward exam success.
Cһange mathematics challenges іnto victories ᴡith OMT Math Tuition’s
blend of online and on-site alternatives, Ьacked by
a track record of trainee excellence.
Ꭺs mathematics forms tһe bedrock of logical thinking and іmportant analytical іn Singapore’s education ѕystem, professional math tuition supplies tһе individualized assistance neсessary to turn challenges
into triumphs.
Tuition programs f᧐r primary school mathematics concentrate on mistake
analysis fгom pгevious PSLE documents, teaching students tߋ avoid repeating errors in computations.
Gіven the high risks of O Levels for secondary school progression in Singapore, math tuition mɑkes beѕt uѕe of chances for leading
qualities аnd preferred positionings.
Ϝor those gоing afteг H3 Mathematics, junior college
tuition оffers sophisticated guidance ⲟn research-level subjects
tߋ master this difficult expansion.
Ꭲhе uniqueness ߋf OMT depends ߋn іtѕ custom-made educational program tһаt lіnks MOE syllabus spaces ԝith
supplementary resources ⅼike proprietary worksheets аnd options.
No demand tօ takе a trip, juѕt visit fгom һome leh, saving time to resеarch mօre and puxh your math grades gгeater.
Tuition cultivates independent ⲣroblem-solving, a skill highly valued in Singapore’ѕ application-based mathematics exams.
mү web site – math group tuition (https://northcarolinainquiry.com)
https://northcarolinainquiry.com
28 Oct 25 at 3:22 pm
купить диплом в казани [url=http://rudik-diplom13.ru]купить диплом в казани[/url] .
Diplomi_dpon
28 Oct 25 at 3:23 pm
https://t.me/s/Official_mellstroy_casino/12
Calvindreli
28 Oct 25 at 3:23 pm
Ich bin total hingerissen von Cat Spins Casino, es entfuhrt in eine Welt voller Spa?. Die Spiele sind abwechslungsreich und spannend, mit aufregenden Live-Casino-Erlebnissen. 100 % bis zu 500 € und Freispiele. Verfugbar 24/7 fur alle Fragen. Auszahlungen sind einfach und schnell, allerdings gro?ere Boni waren ideal. Abschlie?end, Cat Spins Casino ist ein Ort fur pure Unterhaltung. Daruber hinaus die Seite ist schnell und einladend, eine immersive Erfahrung ermoglicht. Ein starkes Feature ist das VIP-Programm mit tollen Privilegien, ma?geschneiderte Privilegien liefern.
Eintreten|
Blazerideror1zef
28 Oct 25 at 3:23 pm
В клинике «ЮгМед Альянс» выстроена система непрерывного медицинского наблюдения. При поступлении проводится комплексная диагностика, назначается детоксикация и поддерживающая терапия, затем начинается стабилизация физического и эмоционального состояния. Благодаря круглосуточной работе бригад и возможности экстренного выезда на дом пациенты получают помощь без задержек. Конфиденциальность соблюдается на всех уровнях — от первичного звонка до выписки. Для удобства родственников организована система информирования: короткие апдейты по согласованным каналам связи и только в определённое время, чтобы не нарушать покой пациента.
Выяснить больше – http://narkologicheskaya-klinika-stavropol0.ru
Davidkeype
28 Oct 25 at 3:23 pm
kraken
кракен ссылка
Henryamerb
28 Oct 25 at 3:24 pm
https://t.me/Official_mellstroy_casino/36
Calvindreli
28 Oct 25 at 3:26 pm
Great info. Lucky me I came across your website by chance (stumbleupon).
I’ve book-marked it for later!
U88 COM
28 Oct 25 at 3:26 pm
Топ-выбор для вас: https://journal-ua.com/transport/zashchita-i-stil-vsjo-ob-avtomobilnykh-chekhlakh.html
journal-ua-801
28 Oct 25 at 3:28 pm
официальный сайт бк мелбет [url=https://melbetofficialsite.ru/]официальный сайт бк мелбет[/url] .
bk melbet_mdEa
28 Oct 25 at 3:29 pm
продвижения сайта в google [url=www.optimizaciya-i-seo-prodvizhenie-sajtov-moskva-1.ru/]продвижения сайта в google[/url] .
optimizaciya i seo prodvijenie saitov moskva_dePi
28 Oct 25 at 3:29 pm
купить диплом повара [url=http://rudik-diplom7.ru/]купить диплом повара[/url] .
Diplomi_maPl
28 Oct 25 at 3:29 pm
кракен зеркало
кракен тор
Henryamerb
28 Oct 25 at 3:31 pm
куплю диплом медсестры в москве [url=frei-diplom15.ru]куплю диплом медсестры в москве[/url] .
Diplomi_fdoi
28 Oct 25 at 3:32 pm
fashionloverszone – I’ll bookmark this for future visits when I’m shopping for style.
Cliff Quesada
28 Oct 25 at 3:33 pm
Serialexpress.ru — магазин для тех, кто любит сериалы в хорошем качестве и с быстрой доставкой. В каталоге — российские и зарубежные новинки, теленовеллы, дорамы, документальные фильмы; более 15 000 наименований и регулярные пополнения. Покупатели отмечают оперативную обработку заказов, накопительные скидки и грамотные консультации по форматам. В середине выбора загляните на https://serialexpress.ru/ — интуитивный поиск по буквам и странам помогает быстро найти нужный сезон, а удобная доставка почтой РФ и СДЭК экономит время.
sysevtcruth
28 Oct 25 at 3:34 pm
I visited many web pages however the audio feature for audio songs present at this website is truly wonderful.
site
28 Oct 25 at 3:35 pm
Hello There. I found your blog using msn. This is an extremely well written article.
I’ll make sure to bookmark it and come back to read more of your useful information. Thanks for the
post. I’ll definitely return.
Zeker Finspire
28 Oct 25 at 3:35 pm
Полная версия здесь: https://journal-ua.com/tekhnolohii/podklyuchenie-i-sovmestimost-naushniki-dlya-telefona-noutbuka-i-tv.html
journal-ua-15
28 Oct 25 at 3:36 pm
kraken сайт Kraken ссылка – это ключ к заветной двери, ведущей в глубины цифрового пространства, где правят свои законы. Убедитесь в подлинности источника, прежде чем доверить ему свои данные, ведь мошенники не дремлют. Остерегайтесь фишинговых сайтов и поддельных зеркал, чтобы ваше путешествие не обернулось разочарованием. Будьте бдительны и осмотрительны, и тогда сможете избежать неприятностей и насладиться всеми преимуществами платформы.
Kevinmoots
28 Oct 25 at 3:37 pm
мелбет бк [url=www.melbetofficialsite.ru]мелбет бк[/url] .
bk melbet_rtEa
28 Oct 25 at 3:37 pm
купить диплом во всеволожске [url=www.rudik-diplom7.ru]www.rudik-diplom7.ru[/url] .
Diplomi_ubPl
28 Oct 25 at 3:38 pm
vqscvasavtzqpsj.shop – Mobile version looks perfect; no glitches, fast scrolling, crisp text.
Thurman Mewborn
28 Oct 25 at 3:38 pm
l2dkp.com – Mobile version looks perfect; no glitches, fast scrolling, crisp text.
Crystal Capen
28 Oct 25 at 3:38 pm
купить диплом косметолога [url=http://rudik-diplom13.ru]купить диплом косметолога[/url] .
Diplomi_kpon
28 Oct 25 at 3:38 pm
Не пропустите лучшее: https://journal-ua.com/moda.html
journal-ua-277
28 Oct 25 at 3:38 pm
pok01.live – Appreciate the typography choices; comfortable spacing improved my reading experience.
Yvone Sprankle
28 Oct 25 at 3:38 pm
https://t.me/Official_mellstroy_casino/57
Calvindreli
28 Oct 25 at 3:39 pm
Its like you read my mind! You appear to know a lot about this, like
you wrote the book in it or something. I think that you can do
with some pics to drive the message home a bit, but instead of that, this
is magnificent blog. An excellent read. I will definitely be back.
Finozanetix
28 Oct 25 at 3:39 pm
kraken darknet
кракен клиент
Henryamerb
28 Oct 25 at 3:39 pm
modernlivingstore – The site layout looks clean and inviting; nice first impression.
Zenia Deville
28 Oct 25 at 3:39 pm
kraken зеркало
кракен маркет
Henryamerb
28 Oct 25 at 3:40 pm
https://t.me/s/Official_mellstroy_casino/16
Calvindreli
28 Oct 25 at 3:40 pm
купить крешер для травы
купить крешер для травы
28 Oct 25 at 3:42 pm
clock radio alarm clock cd player [url=https://alarm-radio-clocks.com]https://alarm-radio-clocks.com[/url] .
Cd Player Radio Alarm Clocks_qtOa
28 Oct 25 at 3:42 pm
купить диплом цена [url=https://rudik-diplom7.ru]купить диплом цена[/url] .
Diplomi_hdPl
28 Oct 25 at 3:42 pm
купить диплом в уфе [url=http://www.rudik-diplom9.ru]купить диплом в уфе[/url] .
Diplomi_klei
28 Oct 25 at 3:44 pm
spartanwebsolution.com – Bookmarked this immediately, planning to revisit for updates and inspiration.
Tabatha Camic
28 Oct 25 at 3:44 pm
Kamagra Oral Jelly Deutschland: Potenzmittel ohne ärztliches Rezept – vital pharma 24
Georgenor
28 Oct 25 at 3:44 pm
Ich bin vollig uberzeugt von Cat Spins Casino, es begeistert mit Dynamik. Die Auswahl ist einfach unschlagbar, mit Slots in modernem Look. Er bietet einen gro?artigen Vorteil. Der Service ist rund um die Uhr verfugbar. Die Zahlungen sind sicher und effizient, gelegentlich regelma?igere Promos wurden das Spiel aufwerten. Im Gro?en und Ganzen, Cat Spins Casino ist perfekt fur Casino-Liebhaber. Hinzu kommt die Plattform ist optisch ein Highlight, jede Session unvergesslich macht. Ein gro?er Pluspunkt ist das VIP-Programm mit einzigartigen Belohnungen, ma?geschneiderte Privilegien liefern.
Website betreten|
nightfireus1zef
28 Oct 25 at 3:44 pm
кракен vk4
кракен ссылка
Henryamerb
28 Oct 25 at 3:45 pm
Узнайте больше здесь: https://journal-ua.com/tvaryny.html
journal-ua-942
28 Oct 25 at 3:45 pm
цифровой маркетинг статьи [url=http://www.statyi-o-marketinge6.ru]цифровой маркетинг статьи[/url] .
stati o marketinge _hakn
28 Oct 25 at 3:45 pm
купить диплом электромонтажника [url=www.rudik-diplom13.ru/]купить диплом электромонтажника[/url] .
Diplomi_emon
28 Oct 25 at 3:47 pm
shopwithstylehub – A wide variety of items caught my eye, looks promising.
Meagan Dickman
28 Oct 25 at 3:48 pm
Выездной формат — это не просто «капельница у кровати». Мы заранее раскладываем визит на модули и назначаем окна оценки: первые 20–40 минут (антиеметический мост, переносимость воды), 60–120 минут (регидратация и электролиты, сглаживание ЧСС/АД), первая ночь (сон ?6 часов и ?1 пробуждение), 12–24 часа (утренняя ясность и способность выполнить 2 короткие бытовые задачи). Одно изменение — один параметр: либо темп инфузии, либо порядок модулей, либо настройка среды (свет/тишина/ритуал). Так причинно-следственные связи остаются прозрачными, а результат — подтверждаемым.
Ознакомиться с деталями – [url=https://narkologicheskaya-klinika-v-chelyabinske16.ru/]наркологическая клиника лечение алкоголизма челябинск[/url]
Robertpoess
28 Oct 25 at 3:48 pm
[url=https://usenergo.ru/]Решения в области электроэнергии[/url] от Южно-Сибирской энергетической компании — это высокотехнологичный способ обеспечить стабильную подачу электроэнергии. Мы предлагаем эффективное распределение и контроль энергоресурсов. Наши специалисты гарантируют качественную реализацию энергетических программ любого масштаба.
Компания использует инновационные технологии для оптимизации энергопотребления. Мы обеспечиваем подключение новых объектов к электросетям.
Южно-Сибирская энергетическая компания сотрудничает с промышленными предприятиями, логистическими комплексами и коммерческими организациями. Благодаря нашему опыту и компетенции, клиенты могут планировать работу предприятия без страха остановок.
Мы предлагаем оптимизацию затрат и повышение энергоэффективности. Для каждого клиента мы подбираем индивидуальные схемы подключения.
Наш подход — это стабильность, качество и технологичность. Южно-Сибирская энергетическая компания — основа энергетической стабильности вашего бизнеса.
https://usenergo.ru/
Edwincrady
28 Oct 25 at 3:49 pm
connectwithideas – Product visuals are clear, descriptions readable — a good first impression.
Travis Asby
28 Oct 25 at 3:50 pm