Одностраничники на базе MODx без контекстов
Доброго времени суток!
Стояла задача реализовать создание одностраничных сайтов с минимальными затратами по времени и ресурсам.
Моя реализация основана принципе создания одностраничного сайта в рамках стандартного ресурса MODx и подмены шаблона и содержимого главной страницы в зависимости от доменного имени сайта, по которому пользователь перешел.
Итак, суть решения:
Если кому-то будет полезно — буду рад.
Поправил по замечаниям, спасибо что указали на ошибки
Стояла задача реализовать создание одностраничных сайтов с минимальными затратами по времени и ресурсам.
Моя реализация основана принципе создания одностраничного сайта в рамках стандартного ресурса MODx и подмены шаблона и содержимого главной страницы в зависимости от доменного имени сайта, по которому пользователь перешел.
Итак, суть решения:
- К каждому ресурсу, который представляет собой отдельный одностраничный сайт присваивается tv поле с доменным именем
- на событие OnLoadWebDocument вешается плагин, который получает текущий домен и находит ресурс,
привязанный к данному домену, получает и применяет шаблон данного ресурса к главной странице, создает плейсхолдер [[+resid]], в котором хранится id нужного нам ресурса - Выводится нужный нам контент в соответствии с плейсхолдером [[+resid]] в нужном нам шаблоне
<?php
$id = $modx->resource->get('id');
if($modx->event->name == 'OnLoadWebDocument' ){
$domain = $_SERVER['HTTP_HOST'];
$q = $modx->newQuery('modTemplateVarResource', array('tmplvarid'=>1,'value'=>$domain));// 'tmplvarid'=>1 это id тв поля с доменом
$q->select('contentid');
$RESID = $modx->getValue($q->prepare());// получаем id ресурса соответствующего домену
if($RESID){
$modx->setPlaceholder('resid', $RESID);
if(!in_array($id,array(3,4))){//отсекаем страницы роботса и сайтмап
$res = $modx->getObject('modResource',$RESID);//
$template = $res->get('template');// сохраним id нужного ресурса для вызова в шаблонах
$modx->resource->set('template', $template);//задаем шаблон вывода
$modx->resource->save();
$cm = $modx->getCacheManager();
$cm->refresh();
}
}
}
Конечно можно просто создать для каждого сайта свой шаблон и не заморачиваться, но это не то, что нам нужно, поэтому весь контент в шаблонах вызывается через fastField: [[#[[+resid]].pagetitle]]Если кому-то будет полезно — буду рад.
Поправил по замечаниям, спасибо что указали на ошибки
Комментарии: 16
Вот такие конструкции:
$data = "SELECT contentid FROM base_site_tmplvar_contentvalues WHERE tmplvarid = 1 AND value = '$domain'";
Лучше писать более универсально:$q = $modx->newQuery('modTemplateVarResource');
$q->where(array('tmplavarid'=>1,'value'=>$domain));
$q->select('contentid');
$q->limit(1); // один же ресурс ищем
if($q->prepare() && $q->stmt->execute()) {
if($RESID = $q->stmt->fetch(PDO::FETCH_COLUMN)) { // - один столбец для одной стройки
// весь остальной код
}
}
Получить одно поле —
$q = $modx->newQuery('modTemplateVarResource', array('tmplavarid'=>1,'value'=>$domain));
$q->select('contentid');
$RESID = $modx->getValue($q->prepare());
Оказывается, вообще красиво можно — запомню :)
Довелось недавно делать одностраничник на Modx. В итоге получилось:
10+ ресурсов
10+ TV
20+ чанков
10+ ресурсов
10+ TV
20+ чанков
"SELECT contentid FROM base_site_tmplvar_contentvalues WHERE tmplvarid = 1 AND value = '$domain'";
Жесть. Кому нужен дырявый сайт, налетай. Стыдно должно быть, молодой человек!
а как в данном случае может проявиться уязвимость? этот скрипт запускается в плагине и, по сути из параметров принимает только домен. Как можно на этой дыре что-то сделать?
Спасибо за критику!
Спасибо за критику!
Домен у тебя получается из $_SERVER['HTTP_HOST'], который при не очень хорошо настроенном сервере будет выдавать то, что прислал юзер.
А прислать он может что угодно, включая длиннющую строку со слепой SQL инъекцией.
А прислать он может что угодно, включая длиннющую строку со слепой SQL инъекцией.
Но здесь же по сути переменная получает данные типа site.ru, то есть все остальные параметры просто не принимаются типа get параметров и прочего, или я не прав?
Ты не прав. HTTP_HOST присылает юзер в запросе.
Если у сервера нет определённых настроек (которых по умолчанию и нет), тебе могут вместо site.ru прислать что угодно, включая SQL инъекцию.
Если у сервера нет определённых настроек (которых по умолчанию и нет), тебе могут вместо site.ru прислать что угодно, включая SQL инъекцию.
Спасибо! дополнительно ознакомлюсь с темой!
Спасибо за критику!Ну если такое отношение к критике, то возьму на себя смелость разобрать код.
1. Теперь на один просмотр страницы будет 2 лишних запроса к БД.
2. Вот это
$modx->resource->save();
зачем? Кроме того, это ещё один запрос к БД.3. Вы понимаете, что после каждого просмотра вы убиваете весь кэш сайта?
4. И наконец, эта странная фраза
весь контент в шаблонах вызывается через fastField: [[#[[+resid]].pagetitle]]Это как интересно?
Почему нельзя просто сделать форвард на найденный ресурс?
Вообще, эта задача легко решается через контексты. И поддержка такого решения гораздо проще, ведь всё понятно. А вот для вашего решения нужна инструкция, ибо следующий программист вряд ли сходу поймёт ваше творчество.
2. $modx->resource->save(); без этого зачастую не срабатывала привязка шаблона, хз почему но с этим была беда
3. Да, согласен, это лишнее
4. А каким образом делается форвард на ресурс, при условии что url измениться не должен?
Про контексты — когда стоит задача сделать систему такую, чтоб обычный юзверь, без дополнительных регистраций контекстов, мог зарегистрировать, наполнить и запустить еще пару тройку одностраничников, по готовым шаблонам — мне кажется так проще. Человеку просто нужно зайти и заполнить ресурс как обычно + добавить url в поле — больше ничего делать не нужно (ну кроме регистрации домена, но это уже не касается системы)
3. Да, согласен, это лишнее
4. А каким образом делается форвард на ресурс, при условии что url измениться не должен?
Про контексты — когда стоит задача сделать систему такую, чтоб обычный юзверь, без дополнительных регистраций контекстов, мог зарегистрировать, наполнить и запустить еще пару тройку одностраничников, по готовым шаблонам — мне кажется так проще. Человеку просто нужно зайти и заполнить ресурс как обычно + добавить url в поле — больше ничего делать не нужно (ну кроме регистрации домена, но это уже не касается системы)
modx.pro/development/2157-method-sendforward-and-save-the-fields-of-the-resource/
А вот контент поменять врятли удастся:
github.com/modxcms/revolution/pull/13163
Вообще это хороший вопрос про sendforward
А вот контент поменять врятли удастся:
github.com/modxcms/revolution/pull/13163
Вообще это хороший вопрос про sendforward
Если покопаться в MODX API то можно научиться выводить любой ресурс в плагине на нужном событии:
Можно так на лету и виртуальные ресурсы делать, со своими pagetitle и прочими свойствами. При желании, можно вообще весь сайт без ресурсов сделать =)
$modx->resource = $modx->getObject('modResource', $modx->getOption('site_start'));
$modx->resource->set('content', $pdoTools->runSnippet('@FILE snippets/get_panel.php'));
$modx->request->prepareResponse();
Здесь, как видно, еще и замена контента на свой идёт, на лету. Можно так на лету и виртуальные ресурсы делать, со своими pagetitle и прочими свойствами. При желании, можно вообще весь сайт без ресурсов сделать =)
Хорошая штука:) Василий, а что скажете на счет такой реализации? Работать то она работает, но не является ли это каким-то велосипедом? Как-то привык доверять вашему мнению)
Ну а что здесь велосипедного?
MODX делает примерно тоже самое при загрузке страницы, просто дольше и с большими условиями.
MODX делает примерно тоже самое при загрузке страницы, просто дольше и с большими условиями.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.