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!
кайт “Трюки на максимум”: Прогрессивный кайт: как выбрать снарягу, чтобы выделывать самые крутые штуки
Kennethvut
30 Jul 25 at 11:29 pm
Когда организм на пределе, важна срочная помощь в Ростове-На-Дону — это команда опытных наркологов, которые помогут быстро и мягко выйти из запоя без вреда для здоровья.
Узнать больше – [url=https://vyvod-iz-zapoya-rostov16.ru/]narkolog-vyvod-iz-zapoya rostov-na-donu[/url]
KeithJab
30 Jul 25 at 11:29 pm
Надёжная капельница от запоя в стационаре в клинике Частный Медик?24 (Коломна) — полный курс лечения, узнайте больше.
Изучить вопрос глубже – [url=https://kapelnica-ot-zapoya-kolomna14.ru/]вызвать капельницу от запоя коломна[/url]
HenryFem
30 Jul 25 at 11:33 pm
кайт школа Кайтсёрфинг летом: идеальный отдых на воде. Наслаждайтесь летним солнцем и ветром на лучших спотах.
Kennethvut
30 Jul 25 at 11:35 pm
melbet .com [url=https://www.melbet1033.ru]https://www.melbet1033.ru[/url]
melbet_pvPn
30 Jul 25 at 11:35 pm
купить аттестаты за 11 классов в кирове [url=arus-diplom22.ru]купить аттестаты за 11 классов в кирове[/url] .
Diplomi_nvsl
30 Jul 25 at 11:35 pm
I was curious if you ever considered changing the layout of
your website? Its very well written; I love
what youve got to say. But maybe you could a little more in the way of content so people could connect with it better.
Youve got an awful lot of text for only having one or two pictures.
Maybe you could space it out better?
Salt Trick for men
30 Jul 25 at 11:36 pm
Клиника Частный Медик?24 в Коломне — профессиональная капельница от запоя в стационаре, смотрите страницу услуги.
Получить дополнительную информацию – [url=https://kapelnica-ot-zapoya-kolomna16.ru/]капельница от запоя анонимно в коломне[/url]
AlbertEsold
30 Jul 25 at 11:37 pm
Обращение за помощью на дому имеет ряд неоспоримых преимуществ, особенно для тех, кто ценит конфиденциальность и стремится избежать дополнительных стрессовых факторов, связанных с посещением клиники:
Углубиться в тему – [url=https://narcolog-na-dom-ufa00.ru/]вызов нарколога на дом цена в уфе[/url]
MelvinNof
30 Jul 25 at 11:37 pm
перевозка автомобиля автовозом по россии [url=https://avtovoz-av.ru/]avtovoz-av.ru[/url] .
avtovoz_jlmr
30 Jul 25 at 11:37 pm
Hi, I do think this is a great site. I stumbledupon it 😉 I may revisit once again since I book marked it.
Money and freedom is the greatest way to change,
may you be rich and continue to help others.
Velyra Platform
30 Jul 25 at 11:37 pm
That is a really good tip particularly to those new to the blogosphere.
Simple but very precise information… Thank you for sharing this one.
A must read post!
Instant Akpro 2X
30 Jul 25 at 11:43 pm
Hello There. I found your blog the usage of msn. This is a very well written article.
I will make sure to bookmark it and return to learn extra of your helpful
information. Thank you for the post. I will certainly return.
casino ohne einschränkung
30 Jul 25 at 11:46 pm
Внутривенная инфузия – это один из самых быстрых и безопасных способов очистки организма от алкоголя и его токсичных продуктов распада. Она позволяет:
Исследовать вопрос подробнее – [url=https://kapelnica-ot-zapoya-krasnoyarsk6.ru/]капельница от запоя на дому недорого[/url]
Miguelodora
30 Jul 25 at 11:48 pm
перевозка автомобилей автовозом по россии [url=www.avtovoz-av.ru/]www.avtovoz-av.ru/[/url] .
avtovoz_uqmr
30 Jul 25 at 11:48 pm
NeuroRelief Rx [url=https://neuroreliefrx.shop/#]gabapentin controlled drug[/url] NeuroRelief Rx
JamesAmola
30 Jul 25 at 11:49 pm
Для проживающих в Балашихе: услуга стационарного вывода из запоя от Частного Медика 24 — переходите по ссылке.
Подробнее можно узнать тут – http://vyvod-iz-zapoya-v-stacionare-balashiha11.ru/
RichardBut
30 Jul 25 at 11:52 pm
https://gosuslugie.ru/kak-poluchit-zaym-cherez-gosuslugi.html
MartinShale
30 Jul 25 at 11:54 pm
Пациенты выбирают нашу клинику для срочного вызова врача-нарколога благодаря следующим важным преимуществам:
Узнать больше – http://narcolog-na-dom-novosibirsk00.ru/narkolog-na-dom-czena-novosibirsk/
DanielHah
30 Jul 25 at 11:59 pm
order corticosteroids without prescription: order corticosteroids without prescription – anti-inflammatory steroids online
LarryBoymn
30 Jul 25 at 11:59 pm
Мега ссылка
RichardPep
31 Jul 25 at 12:00 am
Надёжный вывод из запоя в клинике Частный Медик 24 (Балашиха) — полный стационарный курс, смотрите по ссылке.
Детальнее – [url=https://vyvod-iz-zapoya-v-stacionare-balashiha12.ru/]вывод из запоя на дому московская область[/url]
ElbertCox
31 Jul 25 at 12:07 am
доставка авто [url=https://avtovoz-av8.ru/]https://avtovoz-av8.ru/[/url] .
avtovoz_laKt
31 Jul 25 at 12:08 am
Hi everybody, here every person is sharing such familiarity,
thus it’s pleasant to read this weblog, and I
used to pay a visit this webpage daily.
my website – beste provider voor Nederlanders in Hongarije
beste provider voor Nederlanders in Hongarije
31 Jul 25 at 12:09 am
After exploring various sources, I discovered the best review of Netbet casino, highlighting why it’s truly the ideal option for Greeks.
Read this insightful analysis on Netbet Casino via the link at the bottom:
https://jaytechengineering.com/casino-netbet-700/casino-netbet-700/
Taheskix
31 Jul 25 at 12:12 am
Купить диплом университета мы поможем. Купить диплом техникума, колледжа в Набережных Челнах – [url=http://diplomybox.com/kupit-diplom-tekhnikuma-kolledzha-v-naberezhnykh-chelnakh/]diplomybox.com/kupit-diplom-tekhnikuma-kolledzha-v-naberezhnykh-chelnakh[/url]
Cazrpqp
31 Jul 25 at 12:12 am
The researchers used a hydrogel to 3D-print a model of the corpus cavernosum – a key structure in the penis that fills with blood during an erection. Next, they seeded this scaffold with endothelial cells – the main cells that line blood vessels
viagra 4 pack
31 Jul 25 at 12:13 am
Клиника Частный Медик?24 в Коломне — профессиональная капельница от запоя в стационаре, смотрите страницу услуги.
Получить дополнительную информацию – [url=https://kapelnica-ot-zapoya-kolomna.ru/]капельница от запоя[/url]
Eddiedrell
31 Jul 25 at 12:22 am
Услуга
Узнать больше – [url=https://kapelnica-ot-zapoya-nizhniy-novgorod000.ru/]kapelnicza-ot-zapoya nizhnij novgorod[/url]
EugeneSow
31 Jul 25 at 12:22 am
После звонка специалист клиники «ВитаЛайн» оперативно отправляется по указанному адресу и обычно прибывает в течение 30–60 минут. На месте врач сразу проводит детальную диагностику, оценивая состояние пациента: проверяет пульс, давление, сатурацию, степень интоксикации и наличие хронических болезней. На основании результатов осмотра нарколог разрабатывает индивидуальную схему терапии.
Ознакомиться с деталями – [url=https://narcolog-na-dom-novosibirsk0.ru/]нарколог на дом вывод из запоя[/url]
Jameshit
31 Jul 25 at 12:26 am
мелбет отзывы 2022 [url=http://melbet1033.ru/]http://melbet1033.ru/[/url]
melbet_elPn
31 Jul 25 at 12:29 am
доставка авто из тольятти [url=https://avtovoz-av8.ru]https://avtovoz-av8.ru[/url] .
avtovoz_nqKt
31 Jul 25 at 12:36 am
кайт школа “Уход”: Как ухаживать за кайтом, чтобы он прослужил долго
Kennethvut
31 Jul 25 at 12:40 am
Hello Dear, are you genuinely visiting this website regularly,
if so after that you will definitely obtain pleasant experience.
vibely xpress control mascara ingredients
31 Jul 25 at 12:40 am
Do you have any video of that? I’d want to find out more details.
buy telegram post views
31 Jul 25 at 12:51 am
кайт школа “Первый взлет”: Советы новичкам: какой кайт взять, чтобы не улететь на Бали
Kennethvut
31 Jul 25 at 12:54 am
услуги транспортировки автомобилей [url=https://avtovoz-av8.ru/]https://avtovoz-av8.ru/[/url] .
avtovoz_ezKt
31 Jul 25 at 12:55 am
Hey this is kind of of off topic but I was wanting to know if blogs
use WYSIWYG editors or if you have to manually code with HTML.
I’m starting a blog soon but have no coding
experience so I wanted to get guidance from someone with experience.
Any help would be enormously appreciated!
رشته معماری بدون کنکور
31 Jul 25 at 1:05 am
Услуга “Нарколог на дом” в Уфе охватывает широкий спектр лечебных мероприятий, направленных как на устранение токсической нагрузки, так и на работу с психоэмоциональным состоянием пациента. Комплексная терапия включает в себя медикаментозную детоксикацию, корректировку обменных процессов, а также психотерапевтическую поддержку, что позволяет не только вывести пациента из состояния запоя, но и помочь ему справиться с наркотической зависимостью.
Подробнее тут – https://narcolog-na-dom-ufa000.ru/narkolog-na-dom-ufa-czeny
Bruceprort
31 Jul 25 at 1:13 am
I really like reading a post that can make people think.
Also, many thanks for allowing for me to comment!
viagra
31 Jul 25 at 1:14 am
If you are going for most excellent contents like I do, just pay a quick visit this site everyday because it provides quality contents, thanks
Here is my homepage … monthly internet Hungary
monthly internet Hungary
31 Jul 25 at 1:25 am
당신의 정보을 공유해줘서 감사합니다. 당신의 노력에 정말
감사하고, 다음 포스트을 기다리고 있습니다.
다시 한 번 감사합니다.
|
정말 훌륭한 포스트입니다! 귀하의 기사는
정말 도움이 되고, 특히 rumus terpercaya에 대한 부분이 눈에
띄었어요. 추가적인 정보을 위해 자주 방문할게요.
앞으로도 이런 훌륭한 콘텐츠 부탁드려요! 고맙습니다!
|
안녕하세요! 이 사이트를 우연히 발견했는데, 정말 대단합니다!
귀하의 글은 °øÀÎÁß°³»çµ¿¿µ»ó에 대해
새로운 시각을 제공해요. 하지만, 이미지나 시각 자료를
조금 더 추가하면 방문자들이 더 몰입할 수 있을
것 같아요. 아이디어일 뿐이지만, 고려해 보세요!
계속 좋은 콘텐츠 기대할게요!
|
와, 이 기사은 정말 놀라워요! PHP hook, building hooks in your application –
Sjoerd Maessen blog at Sjoerd Maessen blog에서 이렇게 유익한 정보를 찾을 줄 몰랐어요.
당신의 글쓰기 스타일이 정말 쉽고 읽기가 즐거웠어요.
질문이 있는데, submission 관련 더
자세한 자료를 어디서 찾을 수 있을까요?
감사합니다!
|
훌륭한 작업입니다! 이 블로그는 dossiers d’adhésion에 대해
상세한 정보를 제공해서 정말 도움이 됐어요.
하지만, 페이지 로딩 속도가 조금 느린 것 같아요.
호스팅 문제인지 확인해 보시면 어떨까요?
그래도 콘텐츠는 정말 최고예요!
앞으로도 기대할게요!
|
안녕하세요! PHP hook, building hooks in your application – Sjoerd Maessen blog at Sjoerd
Maessen blog의 팬이 됐어요! 당신의 기사는 항상 재미있어요.
특히 Обратившись에 대한 설명이 정말 인상 깊었어요.
제안드리자면, 방문자와의 상호작용을 위해 댓글란에 토론 주제를 추가하면 더 활발한
커뮤니티가 될 것 같아요! 감사합니다!
|
대단해요! 이 웹사이트에서 keys에 대해 이렇게 상세한 정보를 얻을 수 있다니
믿기지 않아요. 귀하의 글은 쉽게 이해할 수 있고 일반
독자에게도 딱이에요. 추가로 관련된 주제의 자료를 공유해 주실 수 있나요?
앞으로도 멋진 콘텐츠 부탁드려요!
|
안녕하세요! PHP hook, building hooks in your application –
Sjoerd Maessen blog at Sjoerd Maessen blog을 동료 추천으로 알게 됐는데, 정말
훌륭해요! 레비트라10mg판매에 대한 귀하의 포스트는 정말 유용했고.
하지만, 모바일에서 볼 때 레이아웃이 약간 어색해요.
반응형 디자인을 고려해 보시면 어떨까요?
그래도 콘텐츠는 최고예요! 감사합니다!
|
진심으로 감사드립니다! PHP hook, building hooks in your application –
Sjoerd Maessen blog at Sjoerd Maessen blog의 포스트는 ammattiautoilun ja logistiikan erikoislehti에
대해 제가 찾던 정확한 정보을 제공해 줬어요.
당신의 글은 쉽게 읽혀서 읽는 게 전혀 아깝지 않았어요.
제안이 있는데, 이 주제에 대해 정기적인 업데이트를 계획 중이신가요?
계속 기대할게요!
|
와우, 이 사이트는 정말 대단해요!
Advieskantoor 관련 정보를 찾다가 PHP hook, building hooks in your application – Sjoerd Maessen blog at
Sjoerd Maessen blog에 도착했는데, 기대 이상이었어요.
당신의 기사는 정말 전문적이고. 추가로
관련 주제의 커뮤니티를 추천해
주실 수 있나요? 앞으로도 좋은 콘텐츠 부탁드려요!
|
안녕하세요! PHP hook, building hooks in your application – Sjoerd Maessen blog at Sjoerd Maessen blog의 기사를
읽으면서 정말 많이 배웠어요.
en viagra diabeticos에 대한 당신의 분석은 정말 독창적이에요.
하지만, 짧은 비디오 같은 시각 자료를 추가하면 더 매력적일 것
같아요. 생각해 보세요! 고맙습니다, 다음 포스트도 기대할게요!
|
대단한 웹사이트네요! premium drupal themes에 대해 이렇게 상세하고 정보를 제공하는 곳은 드물어요.
당신의 글쓰기 스타일이 정말 친근하고 계속 읽고 싶어져요.
질문이 있는데, 이 주제에 대한 세미나나 강의
계획이 있나요? 앞으로도 멋진 콘텐츠 부탁드려요!
|
안녕! PHP hook, building hooks in your application – Sjoerd Maessen blog at Sjoerd Maessen blog을 처음 방문했는데,
정말 인상 깊어요! Spent Fuel & Nuclear에 대한 당신의 기사는 매우 유익하고.
하지만, 검색 엔진에서 이 페이지를 찾기가
조금 어려웠어요. SEO 최적화를 조금 더 강화하면 더 많은 독자가 올 것 같아요!
감사합니다!
|
놀라워요! PHP hook, building hooks in your application – Sjoerd Maessen blog at Sjoerd Maessen blog에서 레비트라처방에
대해 이렇게 명확하고 설명한 곳은 처음이에요.
당신의 포스트는 일반인도 쉽게 이해할 수
있게 쓰여 있어서 정말 감동적이었어요.
추가로 이 주제에 대한 전자책 같은 자료를 제공하시나요?
앞으로도 멋진 콘텐츠 기대할게요!
|
안녕하세요! PHP hook, building hooks in your application – Sjoerd Maessen blog at
Sjoerd Maessen blog의 포스트를 읽고 정말 즐거웠어요.
premium wp themes에 대한 귀하의 분석은 정말 직관적이라 이해하기 쉬웠어요.
궁금한 점이 있는데, 방문자가 직접 참여할
수 있는 설문 같은 콘텐츠를 추가하면 어떨까요?
감사합니다, 다음 포스트도 기대할게요!
|
와, PHP hook, building hooks in your application – Sjoerd
Maessen blog at Sjoerd Maessen blog은 정말 멋진 블로그네요!
synthesizer 관련 정보를 찾다가 여기 왔는데, 귀하의 기사는 정말 도움이 됐어요.
다만, 트위터에서 이 콘텐츠를 더 적극적으로 공유하면 더 많은 사람들이 볼 수
있을 것 같아요! 계속해서 좋은 콘텐츠 부탁드려요!
|
인사드립니다! PHP hook, building hooks in your application – Sjoerd Maessen blog at
Sjoerd Maessen blog의 기사를 읽으며 نرم افزار تخمین رتبه에
대해 깊은 이해를 얻었어요. 귀하의 글은 정말 전문적이고.
질문이 있는데, 이 주제와 관련된 참고 자료를 알려주실 수 있나요?
감사합니다, 자주 방문할게요!
|
대단한 블로그입니다! software su misura caserta에 대한 당신의 기사는 정말
눈에 띄어요. 하지만, 모바일에서 볼 때 글씨 크기가 조금 작게 느껴져요.
폰트 크기 조정을 고려해 보시면 어떨까요?
그래도 콘텐츠는 정말 멋져요! 고맙습니다!
|
안녕! PHP hook, building hooks in your application – Sjoerd
Maessen blog at Sjoerd Maessen blog을 동료에게 추천받아
방문했는데, 정말 놀라워요! software
di qualità에 대한 귀하의 콘텐츠는 정말 도움이 되고.
제안로, 방문자와의 상호작용을 위해 라이브 Q&A 같은 이벤트를 열어보면 어떨까요?
계속해서 멋진 콘텐츠 기대할게요!
|
놀라워요! PHP hook, building hooks in your application –
Sjoerd Maessen blog at Sjoerd Maessen blog에서 cialis ou
viagra levitra에 대해 이렇게 깊이 있는 정보를 찾을 수 있다니 놀라워요!
당신의 글은 정말 논리적이고 읽혀서 읽는 게
전혀 아깝지 않았어요. 질문이 있는데, 이 주제에
대한 온라인 강의 계획이 있나요? 고맙습니다!
|
안녕! PHP hook, building hooks in your application – Sjoerd Maessen blog at Sjoerd Maessen blog의 기사를 읽고 Archive에 대해 깊은 인상을 받았어요.
당신의 글쓰기 스타일이 정말 친근하고 계속 읽고 싶어져요.
하지만, 구글에서 이 페이지를 찾기가
조금 어려웠어요. SEO를 강화하면
더 많은 독자가 올 것 같아요! 계속해서 좋은 콘텐츠 부탁드려요!
Keep on writing, great job!
비아그라 판매 사이트,
31 Jul 25 at 1:25 am
Алкогольный запой представляет собой тяжелое состояние, вызванное длительным бесконтрольным употреблением спиртных напитков. Без медицинского вмешательства вывести организм из запоя может быть сложно и даже опасно. Срочная помощь нарколога требуется при следующих признаках:
Узнать больше – [url=https://kapelnica-ot-zapoya-nizhniy-novgorod0.ru/]капельница от запоя нижний новгород[/url]
RobertFum
31 Jul 25 at 1:26 am
I’ve been exploring for a little for any high quality articles or blog
posts in this sort of house . Exploring in Yahoo
I eventually stumbled upon this web site. Reading this info So i’m satisfied to express that I’ve a
very good uncanny feeling I discovered exactly what I
needed. I so much no doubt will make sure to do not fail to
remember this website and provides it a glance on a relentless
basis.
Feel free to surf to my web site internetaanbieders Hongarije
internetaanbieders Hongarije
31 Jul 25 at 1:30 am
прогнозы на хоккей от профессионалов бесплатно [url=http://www.luchshie-prognozy-na-khokkej6.ru]http://www.luchshie-prognozy-na-khokkej6.ru[/url] .
lychshie prognozi na hokkei_wrMi
31 Jul 25 at 1:33 am
доставка авто [url=www.avtovoz-av8.ru/]www.avtovoz-av8.ru/[/url] .
avtovoz_smKt
31 Jul 25 at 1:35 am
Il s’adapte à tous les styles, que ce soit
avec des sneakers pour un look casual ou des mocassins pour une allure plus élégante.
web site
31 Jul 25 at 1:37 am
перевозка автомобиля автовозом по россии [url=www.avtovoz-av8.ru]www.avtovoz-av8.ru[/url] .
avtovoz_yfKt
31 Jul 25 at 1:41 am
самые точные прогнозы на нхл [url=http://www.luchshie-prognozy-na-khokkej6.ru]http://www.luchshie-prognozy-na-khokkej6.ru[/url] .
lychshie prognozi na hokkei_ahMi
31 Jul 25 at 1:42 am
Heya just wanted to give you a quick heads up and let you know a few of the pictures
aren’t loading correctly. I’m not sure why but I think its a
linking issue. I’ve tried it in two different browsers and both show the same outcome.
Here is my blog post :: beste internet in Hongarije
beste internet in Hongarije
31 Jul 25 at 1:44 am