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!
What you said made a ton of sense. However, consider
this, what if you added a little information? I ain’t saying your content isn’t solid, however suppose you added a post title to
possibly grab a person’s attention? I mean PHP hook,
building hooks in your application – Sjoerd Maessen blog at Sjoerd Maessen blog
is kinda vanilla. You ought to glance at Yahoo’s home
page and watch how they create news titles to get people to open the
links. You might try adding a video or a related pic or two to grab
readers excited about what you’ve got to say. Just my opinion, it would make your website a little bit
more interesting.
roofing services
20 Aug 25 at 5:28 pm
https://linkin.bio/nemiradaifi
Chriszek
20 Aug 25 at 5:39 pm
https://odysee.com/@dankieelidia
Howardhib
20 Aug 25 at 5:39 pm
Клиника создана для оказания квалифицированной помощи всем, кто страдает от различных форм зависимости. Мы стремимся не только к лечению, но также к формированию здорового образа жизни, возвращая пациентов к полноценной жизни.
Детальнее – https://нарко-специалист.рф/vivod-iz-zapoya-v-kruglosutochno-v-Ekaterinburge
ThomasNaima
20 Aug 25 at 5:40 pm
Fantastic beat ! I would like to apprentice even as you
amend your site, how could i subscribe for a blog website?
The account aided me a acceptable deal. I had been a little bit acquainted of this your broadcast provided brilliant
transparent idea
ilondonapartments.com
20 Aug 25 at 5:41 pm
подключение интернета по адресу
krasnodar-domashnij-internet004.ru
подключить интернет по адресу
inernetkrdelini
20 Aug 25 at 5:43 pm
1v1.lol
Currently it seems like BlogEngine is the top blogging platform out there right now.
(from what I’ve read) Is that what you are using on your blog?
1v1.lol
20 Aug 25 at 5:43 pm
Affordable sildenafil citrate tablets for men: Safe access to generic ED medication – Fast-acting ED solution with discreet packaging
ElijahKic
20 Aug 25 at 5:45 pm
Jupiter Swap acts as a meta-exchange, connecting all major Solana exchanges in possibly man platform.
Via aggregating liquidity, it ensures traders get bettor
completion prices while saving time and reducing
slippage. Instead of most memento swaps, it outperforms using a put DEX like Raydium
or Orca directly.
jupiter swap discord
20 Aug 25 at 5:47 pm
1win зеркало сейчас online [url=http://1win22097.ru/]http://1win22097.ru/[/url]
1win_njpr
20 Aug 25 at 5:53 pm
услуги оценки имущества https://ocenochnaya-kompaniya1.ru
ocenochnaya-kompaniya-630
20 Aug 25 at 5:54 pm
Extreme heat is a killer. A recent heat wave shows how much more deadly it’s becoming
[url=https://tripscan.xyz]tripskan[/url]
Extreme heat is a killer and its impact is becoming far, far deadlier as the human-caused climate crisis supercharges temperatures, according to a new study, which estimates global warming tripled the number of deaths in the recent European heat wave.
For more than a week, temperatures in many parts of Europe spiked above 100 degrees Fahrenheit. Tourist attractions closed, wildfires ripped through several countries, and people struggled to cope on a continent where air conditioning is rare.
https://tripscan.xyz
трипскан сайт
The outcome was deadly. Thousands of people are estimated to have lost their lives, according to a first-of-its-kind rapid analysis study published Wednesday.
A team of researchers, led by Imperial College London and the London School of Hygiene and Tropical Medicine, looked at 10 days of extreme heat between June 23 and July 2 across 12 European cities, including London, Paris, Athens, Madrid and Rome.
They used historical weather data to calculate how intense the heat would have been if humans had not burned fossil fuels and warmed the world by 1.3 degrees Celsius. They found climate change made Europe’s heat wave 1 to 4 degrees Celsius (1.8 to 7.2 Fahrenheit) hotter.
The scientists then used research on the relationship between heat and daily deaths to estimate how many people lost their lives.
They found approximately 2,300 people died during ten days of heat across the 12 cities, around 1,500 more than would have died in a world without climate change. In other words, global heating was responsible for 65% of the total death toll.
“The results show how relatively small increases in the hottest temperatures can trigger huge surges in death,” the study authors wrote.
Heat has a particularly pernicious impact on people with underlying health conditions, such as heart disease, diabetes and respiratory problems.
People over 65 years old were most affected, accounting for 88% of the excess deaths, according to the analysis. But heat can be deadly for anyone. Nearly 200 of the estimated deaths across the 12 cities were among those aged 20 to 65.
Climate change was responsible for the vast majority of heat deaths in some cities. In Madrid, it accounted for about 90% of estimated heat wave deaths, the analysis found.
Williamicomy
20 Aug 25 at 5:56 pm
My brother suggested I might like this blog.
He used to be entirely right. This submit actually made my day.
You can not imagine simply how much time I had spent
for this information! Thank you!
سایت انتخاب رشته فرهنگیان ۱۴۰۴
20 Aug 25 at 5:58 pm
Thanks on your marvelous posting! I quite enjoyed reading it, you can be
a great author. I will make certain to bookmark your blog and may come back
sometime soon. I want to encourage that you continue your great work,
have a nice weekend!
google
20 Aug 25 at 5:58 pm
https://rant.li/hucigyhrofuc/lozanna-kupit-kokain-mefedron-marikhuanu
Chriszek
20 Aug 25 at 6:00 pm
SildenaPeak: how to buy generic viagra online – SildenaPeak
ElijahKic
20 Aug 25 at 6:05 pm
Heya! I realize this is sort of off-topic but I needed to ask.
Does operating a well-established website like yours take a lot of
work? I am brand new to running a blog however I do write in my journal every day.
I’d like to start a blog so I can share my personal
experience and feelings online. Please let me
know if you have any kind of ideas or tips for new aspiring bloggers.
Appreciate it!
سایت psd فرهنگیان
20 Aug 25 at 6:05 pm
You really make it seem so easy with your presentation but I find this matter to be really something which
I think I would never understand. It seems too complicated and very broad for me.
I’m looking forward for your next post, I’ll try to get the
hang of it!
situs togel online
20 Aug 25 at 6:06 pm
It’s impressive that you are getting ideas from this article as well as from
our dialogue made at this place.
ma túy đá
20 Aug 25 at 6:11 pm
With havin so much written content do you ever run into any problems of plagorism or copyright
violation? My website has a lot of exclusive content I’ve either written myself or
outsourced but it appears a lot of it is popping it up all over the internet without my permission. Do you know any ways to help reduce content from being stolen? I’d truly appreciate
it.
Immediate Coraldex
20 Aug 25 at 6:12 pm
blacksprut зеркало
RichardPep
20 Aug 25 at 6:13 pm
I’m not that much of a internet reader to be honest but your blogs really nice, keep it
up! I’ll go ahead and bookmark your site to come back later.
All the best
stake online casino
20 Aug 25 at 6:14 pm
Каждый день запоя увеличивает риск для жизни. Не рискуйте — специалисты в Санкт-Петербурге приедут на дом и окажут экстренную помощь. Без боли, стресса и ожидания.
Получить дополнительные сведения – [url=https://vyvod-iz-zapoya-v-sankt-peterburge16.ru/]ленинградская область[/url]
StevenGuirl
20 Aug 25 at 6:14 pm
I just couldn’t leave your website prior to suggesting that I extremely
loved the usual info a person supply for your guests?
Is going to be again often to investigate cross-check new posts
best solar rechargeable batteries
20 Aug 25 at 6:15 pm
Чтобы сайт стал эффективным инструментом продаж, нужно [url=https://mihaylov.digital/prodvizhenie-sajta-v-google/]продвижение сайта в гугле[/url]. Мы предлагаем профессиональный сервис, который обеспечивает рост позиций и трафика. Работа включает техническую оптимизацию, улучшение структуры, контент и линкбилдинг. В результате вы получаете больше клиентов, снижаете стоимость лида и повышаете узнаваемость бренда. Это практичное решение для компаний, ориентированных на рост.
Агентство Mihaylov.digital предоставляет услуги SEO: продвижение сайтов, работа под ключ, комплексные кампании и реклама. Приезжайте в офис: Москва, Одесская ул., 2кС, 117638.
Mihaylov
20 Aug 25 at 6:17 pm
https://hoo.be/eheofaboc
Howardhib
20 Aug 25 at 6:18 pm
Drug information leaflet. Brand names.
levothyroxine synthroid contraindications
Some about medication. Read information now.
levothyroxine synthroid contraindications
20 Aug 25 at 6:18 pm
Hi there i am kavin, its my first occasion to commenting anyplace, when i read this post i thought i could also make comment due to this sensible article.
best crypto casinos
20 Aug 25 at 6:21 pm
https://hoo.be/iobygyfifi
Chriszek
20 Aug 25 at 6:22 pm
плинко кз [url=http://plinko-kz2.ru]http://plinko-kz2.ru[/url]
plinko_kz_soer
20 Aug 25 at 6:25 pm
Platform TESLATOTO menghadirkan permainan slot terpercaya dengan link aktif nonstop.
Nikmati slot online terpercaya, stabil, dan berhadiah menarik setiap hari.
situs toto login
20 Aug 25 at 6:29 pm
Great delivery. Great arguments. Keep up the great
work.
https://datasdy6d.hasil6d.com/
Keluaran Sydney 6 Digit
20 Aug 25 at 6:30 pm
Çok bilgilendirici bir makale! Teşekkürler!
Bu konuya ek olarak, bizim de Niğde’de sunduğumuz Web Tasarım hizmetleri gibi alanlarda sunduğumuz hizmetler hakkında daha fazla bilgi almak isterseniz, sitemizi ziyaret edebilirsiniz.
Merhaba! Bu yazı gerçekten çok faydalı oldu.
Bahsettiğiniz şu nokta çok önemliydi. Eğer ilgilenirseniz, bizim de mobil uygulama geliştirme gibi konular
hakkında sunduğumuz profesyonel hizmetler hakkında bilgi alabilirsiniz.
Merhaba! Blogunuzu takip ediyorum ve her zaman güncel konulara değiniyorsunuz.
Web geliştirme alanında sunduğumuz hizmetlerle ilgili detayları merak ederseniz, sitemizi ziyaret etmeniz yeterli.
Muhteşem bir içerik. Bu tür bilgilere her zaman ihtiyaç var.
Biz de Nevşehir bölgesindeki işletmelere
yönelik web yazılımı çözümleri sunuyoruz. Sitemizi ziyaret edebilirsiniz.
Sosyal Medya Yönetimi Niğde
20 Aug 25 at 6:31 pm
Hi there, I discovered your blog by means of Google even as searching for a related topic, your site came up, it seems good.
I have bookmarked it in my google bookmarks.
Hi there, simply become aware of your blog via
Google, and found that it’s truly informative.
I am gonna watch out for brussels. I’ll be grateful in the
event you continue this in future. Numerous folks might be benefited from your
writing. Cheers!
Golden Visa Program
20 Aug 25 at 6:33 pm
Увидел предложение про [url=https://mihaylov.digital/prodvizhenie-sajta-v-google/]google раскрутка сайтов[/url] и решил проверить. Честно, ожидал стандартные отчёты без эффекта, но результат удивил. Сайт вырос в поиске, клиенты пошли стабильно. Цена при этом осталась доступной, что приятно. Это честный вариант продвижения, который реально работает. Теперь я рекомендую услугу коллегам.
Агентство Mihaylov.digital помогает вывести сайты в ТОП поисковых систем. Предлагаем SEO, настройку рекламы, аудит и продвижение по позициям. Офис: Москва, Одесская ул., 2кС, 117638.
Mihaylov
20 Aug 25 at 6:33 pm
If you are going for best contents like I do, only pay a quick visit this web page
daily since it provides feature contents, thanks
Bit GPT AI
20 Aug 25 at 6:33 pm
Все процедуры проводятся в максимально комфортных и анонимных условиях, после тщательной диагностики и при полном информировании пациента о сути, длительности и возможных ощущениях.
Углубиться в тему – [url=https://kodirovanie-ot-alkogolizma-kolomna6.ru/]кодирование от алкоголизма на дому в коломне[/url]
JamesFrupe
20 Aug 25 at 6:35 pm
https://eed32d75ee97f158e830ab39d1.doorkeeper.jp/
Chriszek
20 Aug 25 at 6:43 pm
What’s up to every body, it’s my first visit of this blog; this web site
carries awesome and really fine stuff in favor of readers.
PG66
20 Aug 25 at 6:47 pm
Hello to every , as I am in fact keen of reading this web site’s post to be updated regularly.
It contains good data.
warna sgp prediksi kepala
20 Aug 25 at 6:47 pm
оценка оружия сайт оценочной компании Москва
ocenochnaya-kompaniya-587
20 Aug 25 at 6:50 pm
Нужен микрозайм? https://kubyshka24.ru: деньги на карту без справок и поручителей. Простое оформление заявки, одобрение за минуты и мгновенное зачисление. Удобно и доступно 24/7.
kubyshka24 595
20 Aug 25 at 6:54 pm
http://webanketa.com/forms/6mrk8c1q68qp2chm65h3ad9g/
Howardhib
20 Aug 25 at 6:58 pm
Когда организм на пределе, важна срочная помощь в Санкт-Петербурге — это команда опытных наркологов, которые помогут быстро и мягко выйти из запоя без вреда для здоровья.
Получить дополнительные сведения – [url=https://azithromycinum.ru/]вывод из запоя недорого[/url]
DerekSquar
20 Aug 25 at 6:59 pm
https://say.la/read-blog/125968
Chriszek
20 Aug 25 at 7:04 pm
Самостоятельно выйти из запоя — почти невозможно. В Санкт-Петербурге врачи клиники проводят медикаментозный вывод из запоя с круглосуточным выездом. Доверяйте профессионалам.
Получить больше информации – [url=https://vyvod-iz-zapoya-v-sankt-peterburge11.ru/]вывод из запоя вызов санкт-петербург[/url]
Peterbox
20 Aug 25 at 7:05 pm
Нужна срочная помощь? Центр «Alco.Rehab» в Москве предлагает круглосуточный вывод из запоя с выездом на дом.
Получить дополнительные сведения – [url=https://nazalnyj.ru/]вывод из запоя на дому цена город москва[/url]
DonaldFUP
20 Aug 25 at 7:05 pm
Your style is so unique in comparison to other folks I have read stuff from.
Thank you for posting when you’ve got the opportunity,
Guess I will just bookmark this site.
تخمین رشته ۱۴۰۴
20 Aug 25 at 7:12 pm
sildenafil 100 mg best price [url=https://sildenapeak.com/#]SildenaPeak[/url] SildenaPeak
RobertCat
20 Aug 25 at 7:14 pm
В Санкт-Петербурге решение есть — наркологическая клиника. Здесь помогают людям выйти из запоя без страха и осуждения. Всё анонимно, грамотно и с заботой о каждом пациенте.
Узнать больше – [url=https://vyvod-iz-zapoya-v-sankt-peterburge17.ru/]вывод из запоя недорого санкт-петербург[/url]
Edwardzifex
20 Aug 25 at 7:15 pm