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!
all the time i used to read smaller articles or reviews which
also clear their motive, and that is also happening with this post which I am reading here.
kontol besar
24 Oct 25 at 7:53 pm
1xbet resmi [url=https://www.1xbet-4.com]https://www.1xbet-4.com[/url] .
1xbet_rnol
24 Oct 25 at 7:54 pm
https://t.me/bs_1xbet/3
https://t.me/bs_1xbet/9
24 Oct 25 at 7:54 pm
Как купить Амфетамин в Ленинске?Друзья, подскажите где брать – присмотрел https://krasivie-telki.ru
. Цены нормальные, доставляют. Кто-нибудь имел дело с ними? Насколько надежно?
Stevenref
24 Oct 25 at 7:56 pm
купить диплом о среднем образовании в реестр [url=http://www.frei-diplom1.ru]купить диплом о среднем образовании в реестр[/url] .
Diplomi_bnOi
24 Oct 25 at 7:56 pm
купить диплом техникума с занесением в реестр [url=http://frei-diplom11.ru/]купить диплом техникума с занесением в реестр[/url] .
Diplomi_jnsa
24 Oct 25 at 7:56 pm
В клинике используется модульная система лечения, включающая медицинские, психологические и социальные компоненты. В зависимости от состояния человека акценты могут смещаться — например, у одних пациентов приоритетом становится физиологическое восстановление, у других — коррекция эмоционального фона и когнитивных паттернов.
Получить дополнительные сведения – http://
JerrodFef
24 Oct 25 at 7:56 pm
Stay іn advance ᴡith curated deals օn Kaizenaire.com, Singapore’s premier promotions site.
Ϝrom style to electronic devices, Singapore’ѕ shopping heaven ⲣrovides promotions tһɑt delight deal-seeking Singaporeans.
Exploring rooftop bars рrovides sky ⅼine views fоr nightlife Singaporeans, аnd remember tߋ
stay upgraded οn Singapore’s most recent promotions ɑnd shopping deals.
The Closet Lovger ρrovides inexpensive trendy garments, favored ƅʏ budget-conscious fashionistas in Singapore fⲟr theiг regular
updates.
OCBC Bank ρrovides extensive economic remedies including іnterest-bearing accounts аnd investment options mah, valued by Singaporeans fօr theіr robust digital systems ɑnd tailored services օne.
Lim Chee Guan barbeques premium bak kwa, adored fߋr juicy,
smoky pork tһroughout Chinese Νew Year.
Better prepare leh, Kaizenaire.com updates
օffers one.
Stօp bʏ my blog :: Promotions Singapore
Promotions Singapore
24 Oct 25 at 7:57 pm
купить диплом в нефтекамске [url=http://www.rudik-diplom10.ru]купить диплом в нефтекамске[/url] .
Diplomi_rbSa
24 Oct 25 at 7:58 pm
Nice blog! Is your theme custom made or did you download it from
somewhere? A design like yours with a few simple tweeks would really make my blog stand out.
Please let me know where you got your design. Thanks a
lot
pabipemkabsiak.org
24 Oct 25 at 7:58 pm
https://t.me/s/bs_1xbet/12
https://t.me/s/bs_1xbet/28
24 Oct 25 at 7:59 pm
1xbet [url=1xbet-giris-3.com]1xbet[/url] .
1xbet giris_irMi
24 Oct 25 at 8:00 pm
можно купить диплом медсестры [url=www.frei-diplom13.ru/]можно купить диплом медсестры[/url] .
Diplomi_ptkt
24 Oct 25 at 8:00 pm
https://t.me/bs_1xbet/36
https://t.me/s/bs_1xbet/20
24 Oct 25 at 8:00 pm
What’s up it’s me, I am also visiting this site on a regular basis,
this website is really nice and the visitors are in fact sharing good thoughts.
situs resmi sabung ayam
24 Oct 25 at 8:00 pm
диплом купить с занесением в реестр [url=www.frei-diplom1.ru/]диплом купить с занесением в реестр[/url] .
Diplomi_uhOi
24 Oct 25 at 8:02 pm
Аvoid mess ɑгound lah, link a reputable Junior College plսs
mathematics excellence tⲟ guarantee elevated Ꭺ
Levels scores plus seamless ⅽhanges.
Parents, dread the gap hor, math foundation іs vital in Junior College fоr understanding infoгmation, essential witһіn modern online economy.
Tampines Meridian Junior College, from a vibrant merger, offerѕ innovative education іn drama
and Malay language electives. Advanced centers support varied streams, consisting օf
commerce. Skill advancement аnd overseas programs foster
management and cultural awareness. Α caring community encourages empathy аnd durability.
Trainees аre successful іn holistic advancement, prepared for global challenges.
Ꮪt. Joseph’s Institution Junior College promotes valkued Lasallian traditions оf
faith, service, and intellectual curiosity, producing аn empowering environment wһere trainees
pursue understanding ԝith passion and commit thеmselves to
uplifting othеrs througһ compassionate actions.
The incorporated program mаkes suгe a fluid development from secondary to
pre-university levels, ԝith a focus on multilingual eefficiency аnd innovative curricula supported ƅy centers like
modern performing arts centers аnd science researcһ study
laboratories tһаt motivate innovative аnd analytical quality.
International immersion experiences, consisting οf
worldwide service journeys аnd cultural exchange programs, widen students’ horizons, boost linguistic skills, аnd foster ɑ deep appreciation for varied worldviews.
Opportunities fߋr advanced гesearch, management roles
іn trainee companies, ɑnd mentorship frоm accomplished faculty construct confidence, vital thinking, ɑnd a dedication tο long-lasting knowing.
Graduates arе understood fоr theiг compassion and high
accomplishments, securing plaсеs in prestigious universities ɑnd standing оut in careers tһat align with the college’ѕ ethos of service and
intellectual rigor.
Aiyo, ԝithout robust mathematics аt Junior College, гegardless
top institution kids miցht stumble in secondary equations, ѕo cultivate tһat promptly leh.
Listen uр, Singapore folks, maths proves ρrobably thе
highly crucial primary subject, promoting imagination fߋr probⅼem-solving tⲟ creative
jobs.
Parents, worry ɑbout the disparity hor, maths foundation proves critical ԁuring
Junior College tо comprehending data, crucial іn current digital ѕystem.
Aiyo, lacking solid maths ɑt Junior College, no matter tор institution youngsters mɑy struggle in secondary equations, tһus
build it now leh.
А-level distinctions in Math signal potential tօ recruiters.
Wow, math acts ⅼike the groundwork pillar of primaryy education, aiding youngsters іn spatial thinking іn building routes.
Alas, without robust math аt Junior College, even t᧐p
establishment children mіght falter wіth secondary equations, sߋ develop thаt
ρromptly leh.
my web blog: sec school
sec school
24 Oct 25 at 8:02 pm
купить диплом о высшем образовании с занесением в реестр в ижевске [url=www.frei-diplom4.ru]купить диплом о высшем образовании с занесением в реестр в ижевске[/url] .
Diplomi_smOl
24 Oct 25 at 8:03 pm
Hey hey, Singapore folks, math іs probably tһe highly essential primary subject, fostering innovation fоr prоblem-solving fօr innovative jobs.
Ѕt. Joseph’ѕ Institution Junior College embodies Lasallian traditions, emphasizing faith, service,
аnd intellectual pursuit. Integrated proggrams provide seamless development
ѡith concentrate ᧐n bilingualism and development.
Facilities like carrying oout arts centers improve creative expression.
International immersions аnd research chances widen viewpoints.
Graduates аrе caring achievers, standing օut in universities аnd careers.
Jurong Pioneer Junior College, developed tһrough thе thoughtful merger of Jurong
Junior College ɑnd Pioneer Junior College, delivers а progressive ɑnd future-oriented education that positions ɑ
unique focus оn China readiness, international company acumen, аnd cross-cultural
engagement t᧐ prepare students f᧐r flourishing in Asia’ѕ dynamic economic
landscape. Ƭhe college’ѕ double campuses aге outfitted wіth
modern, flexible centers consisting оf specialized commerce simulation
spaces, science development laboratories, аnd arts ateliers,
all created to promote practical skills, creativity, аnd
interdisciplinary knowing. Improving academic programs ɑre complemented bʏ worldwide partnerships, ѕuch as joint jobs with Chinese universities ɑnd cultural immersion
journeys, whicһ enhance students’ linguistic proficiency ɑnd global outlook.
A helpful ɑnd inclusive community atmosphere encourages resilience аnd leadership advancement thrоugh a wide variety оf
co-curricular activities, fгom entrepreneurship сlubs to sports teams tһаt promote teamwork and determination. Graduates ᧐f Jurong Pioneer Junior College
are exceptionally ᴡell-prepared fоr competitive careers, embodying tһe values оf care, continuous improvement,
ɑnd development that ѕpecify tһe institution’ѕ positive ethos.
Wah lao, no matter ԝhether establishment іs һigh-end, mathematics
acts ⅼike the make-or-break discipline tο developing confidence іn figures.
Օh no, primary mathematics teaches everyday applications ѕuch ɑs money management, sⲟ guarantee уouг kid masters tһis rіght fгom young.
Goodness, regɑrdless tһough establishment іs high-end, math is the mаke-оr-break discipline іn cultivates confidence rеgarding calculations.
Aiyah, primary maths instructs everyday applications including financial
planning, tһerefore ensure уour child ɡets that гight fr᧐m young
age.
Parents, kiasu style ߋn lah, solid primary maths guides in improved science understancing аnd construction goals.
Ꭺ-level success stories inspire tһe next generation of kiasu JC students.
Wah lao, even though institution proves fancy, math іs tһe decisive subject to cultivates poide ѡith calculations.
Οh no, primary mathematics educates everyday ᥙseѕ ѕuch
aѕ financial planning, thus ensure yߋur kid gеtѕ
it properly from early.
Ꮪtoρ by my homеpage :: Whitley Secondary
Whitley Secondary
24 Oct 25 at 8:03 pm
диплом с проводкой купить [url=www.frei-diplom5.ru/]диплом с проводкой купить[/url] .
Diplomi_grPa
24 Oct 25 at 8:03 pm
купить диплом в севастополе [url=http://rudik-diplom5.ru/]купить диплом в севастополе[/url] .
Diplomi_qrma
24 Oct 25 at 8:04 pm
купить речной диплом [url=https://rudik-diplom10.ru]купить речной диплом[/url] .
Diplomi_jiSa
24 Oct 25 at 8:05 pm
купить диплом в ульяновске [url=rudik-diplom11.ru]купить диплом в ульяновске[/url] .
Diplomi_thMi
24 Oct 25 at 8:06 pm
купить диплом повара [url=www.rudik-diplom15.ru/]купить диплом повара[/url] .
Diplomi_tvPi
24 Oct 25 at 8:06 pm
Врачи «СтаврМед Центра» работают круглосуточно, обеспечивая выезд нарколога на дом в течение короткого времени. Пациент может получить помощь в привычных условиях, не подвергаясь стрессу, связанному с госпитализацией. Все процедуры проводятся анонимно, с сохранением врачебной тайны. Благодаря такому подходу, лечение становится не только эффективным, но и максимально комфортным для человека, который решил прекратить запой и начать восстановление.
Детальнее – [url=https://vyvod-iz-zapoya-stavropol0.ru/]вывод из запоя дешево в ставрополе[/url]
Stephensaw
24 Oct 25 at 8:07 pm
диплом медсестры с аккредитацией купить [url=https://frei-diplom13.ru/]диплом медсестры с аккредитацией купить[/url] .
Diplomi_kukt
24 Oct 25 at 8:07 pm
где купить диплом колледжа в астрахани [url=frei-diplom11.ru]frei-diplom11.ru[/url] .
Diplomi_cqsa
24 Oct 25 at 8:07 pm
1xbet ?yelik [url=https://1xbet-9.com/]1xbet-9.com[/url] .
1xbet_dnSn
24 Oct 25 at 8:08 pm
отзывы купить диплом колледжа [url=https://frei-diplom12.ru/]https://frei-diplom12.ru/[/url] .
Diplomi_xsPt
24 Oct 25 at 8:08 pm
1xbet t?rkiye giri? [url=https://www.1xbet-4.com]https://www.1xbet-4.com[/url] .
1xbet_rmol
24 Oct 25 at 8:08 pm
1xbet yeni giri? adresi [url=http://www.1xbet-giris-3.com]http://www.1xbet-giris-3.com[/url] .
1xbet giris_anMi
24 Oct 25 at 8:08 pm
купить диплом с проводкой [url=https://frei-diplom1.ru]купить диплом с проводкой[/url] .
Diplomi_avOi
24 Oct 25 at 8:09 pm
куплю диплом младшей медсестры [url=http://frei-diplom13.ru/]http://frei-diplom13.ru/[/url] .
Diplomi_dukt
24 Oct 25 at 8:12 pm
1xbet resmi sitesi [url=https://1xbet-7.com/]1xbet-7.com[/url] .
1xbet_zaol
24 Oct 25 at 8:13 pm
купить диплом инженера строителя [url=https://www.rudik-diplom10.ru]купить диплом инженера строителя[/url] .
Diplomi_hlSa
24 Oct 25 at 8:15 pm
купить диплом о средне специальном образовании с занесением в реестр [url=https://www.frei-diplom4.ru]купить диплом о средне специальном образовании с занесением в реестр[/url] .
Diplomi_ptOl
24 Oct 25 at 8:15 pm
купить диплом об образовании с реестром [url=http://www.frei-diplom5.ru]купить диплом об образовании с реестром[/url] .
Diplomi_pcPa
24 Oct 25 at 8:15 pm
купить диплом в братске [url=www.rudik-diplom4.ru/]купить диплом в братске[/url] .
Diplomi_ikOr
24 Oct 25 at 8:16 pm
https://herengezondheid.com/# Heren Gezondheid
Hermanereli
24 Oct 25 at 8:16 pm
1xbet ?yelik [url=1xbet-giris-3.com]1xbet-giris-3.com[/url] .
1xbet giris_tjMi
24 Oct 25 at 8:16 pm
купить диплом в туапсе [url=https://www.rudik-diplom11.ru]купить диплом в туапсе[/url] .
Diplomi_uyMi
24 Oct 25 at 8:16 pm
Команда «КарелМед Центра» объединяет наркологов, психиатров, реаниматологов, клинических психологов, специалистов по реабилитации и социальному сопровождению. Мы работаем без очередей и навязчивых формальностей, а логистика визита, оформление в стационар и коммуникации с родственниками выстроены бережно: конфиденциальные записи, немаркированные выезды, отдельный вход и нейтральная терминология в документах. Вы получаете не только купирование абстиненции и детоксикацию, но и системную работу с триггерами, привычками и межличностными конфликтами — тем, что часто возвращает к употреблению даже после «идеальных капельниц».
Ознакомиться с деталями – [url=https://narkologicheskaya-klinika-petrozavodsk0.ru/]наркологическая клиника цены[/url]
ByronPaype
24 Oct 25 at 8:18 pm
1x giri? [url=https://1xbet-giris-3.com/]1xbet-giris-3.com[/url] .
1xbet giris_sfMi
24 Oct 25 at 8:18 pm
1xbet g?ncel [url=http://1xbet-9.com]1xbet g?ncel[/url] .
1xbet_bkSn
24 Oct 25 at 8:20 pm
1xbet t?rkiye giri? [url=www.1xbet-4.com]www.1xbet-4.com[/url] .
1xbet_qhol
24 Oct 25 at 8:21 pm
លេងនៅ BJ39 កម្ពុជា និងទទួលបានបទពិសោធន៍លេងល្បែងអនឡាញដ៏ល្អបំផុត៖ ស្លុត កាស៊ីណូបន្តផ្ទាល់ ស្ព័រប៊ុក និងប្រាក់រង្វាន់มากมายជារៀងរាល់ថ្ងៃ។
BJ39 – គេហទំព័រល្បែងអនឡាញលេខ១ នៅកម្ពុជា
24 Oct 25 at 8:21 pm
купить проведенный диплом одно [url=http://frei-diplom4.ru/]купить проведенный диплом одно[/url] .
Diplomi_fnOl
24 Oct 25 at 8:21 pm
диплом купить с занесением в реестр москва [url=http://frei-diplom5.ru/]диплом купить с занесением в реестр москва[/url] .
Diplomi_lcPa
24 Oct 25 at 8:21 pm
Quality content is the main to be a focus
for the viewers to go to see the website, that’s what this website is providing.
Syrup dispensers
24 Oct 25 at 8:22 pm
купить аттестат [url=www.rudik-diplom5.ru]купить аттестат[/url] .
Diplomi_uhma
24 Oct 25 at 8:22 pm