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!
Oh my goodness! Incredible article dude!
Many thanks, However I am experiencing difficulties with your RSS.
I don’t understand why I cannot subscribe to it. Is there anybody getting similar RSS problems?
Anyone that knows the answer will you kindly respond? Thanks!!
Lumino Valtrix
15 Oct 25 at 6:42 pm
натяжные потолки официальный сайт нижний новгород [url=http://www.natyazhnye-potolki-nizhniy-novgorod.ru]http://www.natyazhnye-potolki-nizhniy-novgorod.ru[/url] .
natyajnie potolki nijnii novgorod_xaOt
15 Oct 25 at 6:43 pm
1win hesab yaratmaq [url=https://1win5004.com/]https://1win5004.com/[/url]
1win_haoi
15 Oct 25 at 6:45 pm
https://telegra.ph/Dji-rs-4-pro-combo-kupit-10-14
Merletunse
15 Oct 25 at 6:45 pm
1win apk [url=www.1win5005.com]www.1win5005.com[/url]
1win_arml
15 Oct 25 at 6:46 pm
потолки в нижнем новгороде [url=https://stretch-ceilings-nizhniy-novgorod.ru/]https://stretch-ceilings-nizhniy-novgorod.ru/[/url] .
natyajnie potolki nijnii novgorod_haPl
15 Oct 25 at 6:46 pm
Создание сайтов – это очень важный процесс для любого бизнеса.
Веб сайт является лицом компании и помогает привлечь новых клиентов.
Сайт может содержать информацию о компании, ее
услугах и продуктах.Создание сайта начинается с разработки дизайна.
Дизайн должен быть привлекательным и удобным
для пользователей. Далее создается структура сайта.
На этом этапе определяется количество страниц на сайте
и их расположение. После этого сайт программируется.
Программист пишет код для функционирования
сайта. Затем сайт тестируется
и отлаживается.
В заключение, создание сайтов
– это сложный и трудоемкий процесс, требующий
профессионального подхода и знаний в области веб-разработки.
создание и продвижение сайтов
15 Oct 25 at 6:46 pm
yoga to reduce waist
PHP hook, building hooks in your application – Sjoerd Maessen blog at Sjoerd Maessen blog
yoga to reduce waist
15 Oct 25 at 6:47 pm
купить диплом об окончании медицинского колледжа [url=www.frei-diplom12.ru/]www.frei-diplom12.ru/[/url] .
Diplomi_onPt
15 Oct 25 at 6:52 pm
1win azerbaycan rəsmisi [url=http://1win5005.com]1win azerbaycan rəsmisi[/url]
1win_laml
15 Oct 25 at 6:53 pm
Thanks for one’s marvelous posting! I quite enjoyed reading it, you could
be a great author.I will make sure to bookmark your blog and definitely will come back from now on. I want to encourage you to continue your great posts, have a nice evening!
kra37 сс
15 Oct 25 at 6:54 pm
купить диплом в великом новгороде [url=http://rudik-diplom6.ru/]купить диплом в великом новгороде[/url] .
Diplomi_jnKr
15 Oct 25 at 6:55 pm
Appreciating the persistence you put into your website and in depth information you present.
It’s awesome to come across a blog every once
in a while that isn’t the same out of date rehashed material.
Wonderful read! I’ve bookmarked your site and I’m including your RSS feeds
to my Google account.
effectively
15 Oct 25 at 6:59 pm
1win canlı yayım [url=www.1win5005.com]1win canlı yayım[/url]
1win_uqml
15 Oct 25 at 6:59 pm
1win azerbaycan [url=https://1win5004.com]1win azerbaycan[/url]
1win_knoi
15 Oct 25 at 7:00 pm
Налоговый мониторинг: суть и этапы
реализации
https://instukzia.com/81341-chto-takoe-nalogovyy-monitoring-i-ego-provedenie.html
15 Oct 25 at 7:03 pm
На этом этапе специалист уточняет, сколько времени продолжается запой, какие основные симптомы наблюдаются, и если имеются, то какие хронические заболевания могут влиять на течение терапии. Точный анализ этих данных позволяет сформировать персонализированную стратегию лечения, которая будет максимально адаптирована к состоянию пациента и его потребностям.
Детальнее – [url=https://vyvod-iz-zapoya-yaroslavl0.ru/]вывод из запоя клиника в ярославле[/url]
Walterionib
15 Oct 25 at 7:03 pm
потолочников [url=natyazhnye-potolki-nizhniy-novgorod.ru]natyazhnye-potolki-nizhniy-novgorod.ru[/url] .
natyajnie potolki nijnii novgorod_yeOt
15 Oct 25 at 7:03 pm
заказать кухню по индивидуальным размерам в спб [url=kuhni-spb-2.ru]kuhni-spb-2.ru[/url] .
kyhni spb_qrmn
15 Oct 25 at 7:03 pm
сайт натяжной потолок [url=http://natyazhnye-potolki-nizhniy-novgorod-1.ru]http://natyazhnye-potolki-nizhniy-novgorod-1.ru[/url] .
natyajnie potolki nijnii novgorod_hvma
15 Oct 25 at 7:05 pm
Hi there very nice website!! Guy .. Excellent .. Wonderful ..
I’ll bookmark your site and take the feeds additionally? I am happy to search out so many helpful information here
in the submit, we’d like develop more strategies in this regard, thanks for sharing.
. . . . .
kra38 сс
15 Oct 25 at 7:05 pm
1win qanunidirmi [url=http://1win5005.com/]http://1win5005.com/[/url]
1win_sbml
15 Oct 25 at 7:06 pm
Строительный портал https://v-stroit.ru всё о строительстве, ремонте и архитектуре. Полезные советы, технологии, материалы, новости отрасли и практические инструкции для мастеров и новичков.
Rogerzok
15 Oct 25 at 7:07 pm
Thanks a lot for sharing this with all of us you actually recognize what
you’re speaking about! Bookmarked. Kindly additionally consult with my site =).
We may have a link change arrangement between us
education director
15 Oct 25 at 7:07 pm
Современный темп жизни, постоянные стрессы и бытовые трудности всё чаще приводят к тому, что проблема зависимостей становится актуальной для самых разных людей — от молодых специалистов до взрослых, состоявшихся семейных людей. Наркологическая помощь в Домодедово в клинике «РеабилитейшнПро» — это возможность получить профессиональное лечение, консультации и поддержку в любой, даже самой сложной ситуации, без огласки и промедления.
Углубиться в тему – [url=https://narkologicheskaya-pomoshch-domodedovo6.ru/]наркологическая помощь на дому домодедово[/url]
Briangen
15 Oct 25 at 7:07 pm
Scientists discovered something alarming seeping out from beneath the ocean around Antarctica
[url=https://www.dr-igonin-clinic-med.ru/140225/novosti-vasilenko-roman-poslednie-novosti/]анальный секс зрелых[/url]
Planet-heating methane is escaping from cracks in the Antarctic seabed as the region warms, with new seeps being discovered at an “astonishing rate,” scientists have found, raising fears that future global warming predictions may have been underestimated.
Huge amounts of methane lie in reservoirs that have formed over millennia beneath the seafloor around the world. This invisible, climate-polluting gas can escape into the water through fissures in the sea floor, often revealing itself with a stream of bubbles weaving their way up to the ocean surface.
https://nebrehnya.com/news/item/16792-ot-life-is-good-do-begstva-na-kariby-moshennicheskie-shemy-vasilenko-na-mezhdunarodnoy-arene
геи жестко
Relatively little is known about these underwater seeps, how they work, how many there are, and how much methane reaches the atmosphere versus how much is eaten by methane-munching microbes living beneath the ocean.
But scientists are keen to better understand them, as this super-polluting gas traps around 80 times more heat than carbon dioxide in its first 20 years in the atmosphere.
Methane seeps in Antarctica are among the least understood on the planet, so a team of international scientists set out to find them. They used a combination of ship-based acoustic surveys, remotely operated vehicles and divers to sample a range of sites in the Ross Sea, a bay in Antarctica’s Southern Ocean, at depths between 16 and 790 feet.
What they found surprised them. They identified more than 40 methane seeps in the shallow water of the Ross Sea, according to the study published this month in Nature Communications.
Bubbles rising from a methane seep at Cape Evans, Antarctica. Leigh Tate, Earth Sciences New Zealand
Many of the seeps were found at sites that had been repeatedly studied before, suggesting they were new. This may indicate a “fundamental shift” in the methane released in the region, according to the report.
Methane seeps are relatively common globally, but previously there was only one confirmed active seep in the Antarctic, said Sarah Seabrook, a report author and a marine scientist at Earth Sciences New Zealand, a research organization. “Something that was thought to be rare is now seemingly becoming widespread,” she told CNN.
Every seep they discovered was accompanied by an “immediate excitement” that was “quickly replaced with anxiety and concern,” Seabrook said.
The fear is these seeps could rapidly transfer methane into the atmosphere, making them a source of planet-heating pollution that is not currently factored into future climate change predictions.
The scientists are also concerned the methane could have cascading impacts on marine life.
DonaldCix
15 Oct 25 at 7:10 pm
потолки в нижнем новгороде [url=http://www.stretch-ceilings-nizhniy-novgorod.ru]http://www.stretch-ceilings-nizhniy-novgorod.ru[/url] .
natyajnie potolki nijnii novgorod_xxPl
15 Oct 25 at 7:18 pm
https://slovarikslov.ru/terem/xaus/
https://slovarikslov.ru/terem/xaus/
15 Oct 25 at 7:22 pm
В поисках идеальных подарков для близких стоит обратить внимание на магазины, где собраны креативные идеи для любого повода, и одним из таких является Armodrein, предлагающий разнообразный ассортимент от стильных аксессуаров до милых сувениров, вдохновленных популярными брендами вроде Pusheen. В ассортименте имеются не только трендовые украшения вроде тиар, бантиков и бижутерии, но и специальные изделия на разные темы, подходящие и детям, и взрослым, кто хочет внести в будни элемент фантазии. https://armodrein.ru – это платформа, где удобно просматривать категории, получать советы от консультантов и оформлять заказы с доставкой, делая процесс выбора подарка простым и приятным. Обзоры пользователей подчеркивают качество материалов и оригинальность дизайна, что делает покупки здесь настоящим удовольствием, а праздничные коллекции, включая новогодние наборы, добавляют магии в повседневность. В итоге, Armodrein становится надежным помощником в создании запоминающихся моментов, где каждый товар несет в себе частичку радости и заботы.
fafecBum
15 Oct 25 at 7:24 pm
Spot on with this write-up, I really believe that this
website needs a great deal more attention. I’ll probably be returning
to read through more, thanks for the information!
do australians need a visa for turkey
15 Oct 25 at 7:25 pm
Scientists discovered something alarming seeping out from beneath the ocean around Antarctica
[url=https://can-explain.com/temnik/item/194978-gemcy-gem-cy-novaya-piramida-vasilenko]гей порно парни[/url]
Planet-heating methane is escaping from cracks in the Antarctic seabed as the region warms, with new seeps being discovered at an “astonishing rate,” scientists have found, raising fears that future global warming predictions may have been underestimated.
Huge amounts of methane lie in reservoirs that have formed over millennia beneath the seafloor around the world. This invisible, climate-polluting gas can escape into the water through fissures in the sea floor, often revealing itself with a stream of bubbles weaving their way up to the ocean surface.
https://rubrikator.org/items/kompaniya-life-is-good_175402
красивый анальный секс
Relatively little is known about these underwater seeps, how they work, how many there are, and how much methane reaches the atmosphere versus how much is eaten by methane-munching microbes living beneath the ocean.
But scientists are keen to better understand them, as this super-polluting gas traps around 80 times more heat than carbon dioxide in its first 20 years in the atmosphere.
Methane seeps in Antarctica are among the least understood on the planet, so a team of international scientists set out to find them. They used a combination of ship-based acoustic surveys, remotely operated vehicles and divers to sample a range of sites in the Ross Sea, a bay in Antarctica’s Southern Ocean, at depths between 16 and 790 feet.
What they found surprised them. They identified more than 40 methane seeps in the shallow water of the Ross Sea, according to the study published this month in Nature Communications.
Bubbles rising from a methane seep at Cape Evans, Antarctica. Leigh Tate, Earth Sciences New Zealand
Many of the seeps were found at sites that had been repeatedly studied before, suggesting they were new. This may indicate a “fundamental shift” in the methane released in the region, according to the report.
Methane seeps are relatively common globally, but previously there was only one confirmed active seep in the Antarctic, said Sarah Seabrook, a report author and a marine scientist at Earth Sciences New Zealand, a research organization. “Something that was thought to be rare is now seemingly becoming widespread,” she told CNN.
Every seep they discovered was accompanied by an “immediate excitement” that was “quickly replaced with anxiety and concern,” Seabrook said.
The fear is these seeps could rapidly transfer methane into the atmosphere, making them a source of planet-heating pollution that is not currently factored into future climate change predictions.
The scientists are also concerned the methane could have cascading impacts on marine life.
DonaldCix
15 Oct 25 at 7:27 pm
купить кухню на заказ спб [url=www.kuhni-spb-2.ru]www.kuhni-spb-2.ru[/url] .
kyhni spb_ynmn
15 Oct 25 at 7:27 pm
натяжной потолок цена нижний новгород [url=natyazhnye-potolki-nizhniy-novgorod-1.ru]natyazhnye-potolki-nizhniy-novgorod-1.ru[/url] .
natyajnie potolki nijnii novgorod_yhma
15 Oct 25 at 7:28 pm
bester willkommensbonus sportwetten
Also visit my web-site :: wie kann ich beim wetten immer gewinnen
wie kann ich beim wetten immer gewinnen
15 Oct 25 at 7:31 pm
bookmarked!!, I love your website!
Affordable wand massagers for beginners
15 Oct 25 at 7:31 pm
https://t.me/s/Official_1xbet_1xbet
Josephtog
15 Oct 25 at 7:35 pm
натяж потолки [url=https://natyazhnye-potolki-nizhniy-novgorod.ru]https://natyazhnye-potolki-nizhniy-novgorod.ru[/url] .
natyajnie potolki nijnii novgorod_caOt
15 Oct 25 at 7:36 pm
Заказать диплом ВУЗа можем помочь. Купить диплом бакалавра в Ульяновске – [url=http://diplomybox.com/kupit-diplom-bakalavra-v-ulyanovske/]diplomybox.com/kupit-diplom-bakalavra-v-ulyanovske[/url]
Cazrvvt
15 Oct 25 at 7:36 pm
What’s up to every one, it’s actually a good for me to go to
see this web site, it consists of valuable Information.
Seriously
15 Oct 25 at 7:36 pm
экстренный вывод из запоя
vivod-iz-zapoya-cherepovec015.ru
лечение запоя
izzapoyacherepovecNeT
15 Oct 25 at 7:37 pm
1win hesabı bərpa etmək [url=http://1win5004.com/]http://1win5004.com/[/url]
1win_yboi
15 Oct 25 at 7:37 pm
I am extremely impressed with your writing skills and also with the
layout on your blog. Is this a paid theme or did you customize
it yourself? Anyway keep up the nice quality writing, it’s rare to see a nice blog
like this one today.
Football predictions
15 Oct 25 at 7:38 pm
DreamStalker — электронная маска для осознанных снов, которая помогает уверенно переходить в ОС и настраивать сценарии под себя. Новая версия Expert предлагает расширенные режимы, поддержку дневного тренинга DreamTrainer и удобную посадку, а доставка по России — бесплатная. Ишете dreamstalker купить? Подробности, модели и способы оплаты смотрите на claps.me/news/dreamstalker-buy/ Магазин обещает быструю выдачу, реальную техподдержку и замену без экспертизы — редкий уровень сервиса в нише устройств для сна.
rekixiDaulp
15 Oct 25 at 7:38 pm
The $MTAUR token seems like a solid pick for anyone into casual gaming with crypto twists. Navigating mazes as a minotaur while earning in-game currency sounds addictive and rewarding. With the presale offering 80% off, it’s hard not to jump in early.
mtaur token
WilliamPargy
15 Oct 25 at 7:38 pm
Основной этап терапии — установка внутривенной капельницы. Через капельницу вводятся специально подобранные растворы, способствующие быстрому выведению токсинов, восстановлению водно-электролитного баланса и нормализации работы внутренних органов. При необходимости врач назначает дополнительные медикаменты для защиты печени, стабилизации сердечной деятельности и купирования симптомов абстинентного синдрома. В течение всей процедуры состояние пациента контролируется врачом, который корректирует схему лечения для достижения наилучших результатов. По завершении процедуры специалист дает подробные рекомендации по дальнейшему восстановлению и профилактике повторных запоев.
Ознакомиться с деталями – [url=https://kapelnica-ot-zapoya-nizhniy-novgorod00.ru/]врача капельницу от запоя нижний новгород[/url]
Kennykam
15 Oct 25 at 7:42 pm
mexico pharmacy [url=http://medicosur.com/#]MedicoSur[/url] farmacia pharmacy mexico
CareyMag
15 Oct 25 at 7:43 pm
Начнем путешествие по магическим уголкам российских заповедников.
Кстати, если вас интересует Изучение ООПТ России: парки, заповедники, водоемы, посмотрите сюда.
Вот, можете почитать:
[url=https://alloopt.ru]https://alloopt.ru[/url]
Надеюсь, вы нашли это путешествие по природе познавательным.
fixRow
15 Oct 25 at 7:44 pm
Выбор клиники — задача не только медицинская, но и стратегическая. Учитывать нужно не только наличие лицензии, но и содержание программ, их гибкость, участие родственников в процессе, а также прозрачность взаимодействия с пациентом. Именно эти аспекты позволяют отличить профессиональное учреждение от формального.
Детальнее – http://narkologicheskaya-klinika-yaroslavl0.ru/lechenie-narkomanii-i-alkogolizma-yaroslavl/
ChrisWeall
15 Oct 25 at 7:50 pm
1win azerbaycan qeydiyyat [url=http://1win5004.com/]http://1win5004.com/[/url]
1win_atoi
15 Oct 25 at 7:52 pm
Строительный портал https://v-stroit.ru всё о строительстве, ремонте и архитектуре. Полезные советы, технологии, материалы, новости отрасли и практические инструкции для мастеров и новичков.
Rogerzok
15 Oct 25 at 7:54 pm