К содержанию

Одностраничники на базе MODx без контекстов

Доброго времени суток!
Стояла задача реализовать создание одностраничных сайтов с минимальными затратами по времени и ресурсам.
Моя реализация основана принципе создания одностраничного сайта в рамках стандартного ресурса MODx и подмены шаблона и содержимого главной страницы в зависимости от доменного имени сайта, по которому пользователь перешел.
Итак, суть решения:
  1. К каждому ресурсу, который представляет собой отдельный одностраничный сайт присваивается tv поле с доменным именем
  2. на событие OnLoadWebDocument вешается плагин, который получает текущий домен и находит ресурс,
    привязанный к данному домену, получает и применяет шаблон данного ресурса к главной странице, создает плейсхолдер [[+resid]], в котором хранится id нужного нам ресурса
  3. Выводится нужный нам контент в соответствии с плейсхолдером [[+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]]

Если кому-то будет полезно — буду рад.
Поправил по замечаниям, спасибо что указали на ошибки
Арсений
Арсений
06 октября 2017, 08:24
modx.pro
4 491
Реклама

Комментарии: 16

Евгений Шеронов
Евгений Шеронов Проверенный
08 октября 2017, 18:08
Вот такие конструкции:
$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)) { // - один столбец для одной стройки
       // весь остальной код 
    }
}
    Сергей Шлоков
    Сергей Шлоков Эксперт
    09 октября 2017, 07:17
    Получить одно поле —
    $q = $modx->newQuery('modTemplateVarResource', array('tmplavarid'=>1,'value'=>$domain));
    $q->select('contentid');
    $RESID = $modx->getValue($q->prepare());
      Евгений Шеронов
      Евгений Шеронов Проверенный
      09 октября 2017, 08:36
      Оказывается, вообще красиво можно — запомню :)
    Alexander V
    Alexander V Проверенный
    09 октября 2017, 04:15
    Довелось недавно делать одностраничник на Modx. В итоге получилось:
    10+ ресурсов
    10+ TV
    20+ чанков
      Сергей Шлоков
      Сергей Шлоков Эксперт
      09 октября 2017, 07:15
      "SELECT contentid FROM base_site_tmplvar_contentvalues WHERE tmplvarid = 1 AND value = '$domain'";
      Жесть. Кому нужен дырявый сайт, налетай.

      Стыдно должно быть, молодой человек!
        Арсений
        Арсений Проверенный
        09 октября 2017, 11:26
        а как в данном случае может проявиться уязвимость? этот скрипт запускается в плагине и, по сути из параметров принимает только домен. Как можно на этой дыре что-то сделать?
        Спасибо за критику!
          Василий Наумкин
          Василий Наумкин Администратор
          09 октября 2017, 13:54
          Домен у тебя получается из $_SERVER['HTTP_HOST'], который при не очень хорошо настроенном сервере будет выдавать то, что прислал юзер.

          А прислать он может что угодно, включая длиннющую строку со слепой SQL инъекцией.
            Арсений
            Арсений Проверенный
            09 октября 2017, 17:19
            Но здесь же по сути переменная получает данные типа site.ru, то есть все остальные параметры просто не принимаются типа get параметров и прочего, или я не прав?
              Василий Наумкин
              Василий Наумкин Администратор
              09 октября 2017, 17:26
              Ты не прав. HTTP_HOST присылает юзер в запросе.

              Если у сервера нет определённых настроек (которых по умолчанию и нет), тебе могут вместо site.ru прислать что угодно, включая SQL инъекцию.
                Арсений
                Арсений Проверенный
                09 октября 2017, 17:39
                Спасибо! дополнительно ознакомлюсь с темой!
            Сергей Шлоков
            Сергей Шлоков Эксперт
            09 октября 2017, 15:47
            Спасибо за критику!
            Ну если такое отношение к критике, то возьму на себя смелость разобрать код.
            1. Теперь на один просмотр страницы будет 2 лишних запроса к БД.
            2. Вот это
            $modx->resource->save();
            зачем? Кроме того, это ещё один запрос к БД.
            3. Вы понимаете, что после каждого просмотра вы убиваете весь кэш сайта?
            4. И наконец, эта странная фраза собака друг человека —
            весь контент в шаблонах вызывается через fastField: [[#[[+resid]].pagetitle]]
            Это как интересно?

            Почему нельзя просто сделать форвард на найденный ресурс?

            Вообще, эта задача легко решается через контексты. И поддержка такого решения гораздо проще, ведь всё понятно. А вот для вашего решения нужна инструкция, ибо следующий программист вряд ли сходу поймёт ваше творчество.
              Арсений
              Арсений Проверенный
              09 октября 2017, 17:15
              2. $modx->resource->save(); без этого зачастую не срабатывала привязка шаблона, хз почему но с этим была беда
              3. Да, согласен, это лишнее
              4. А каким образом делается форвард на ресурс, при условии что url измениться не должен?

              Про контексты — когда стоит задача сделать систему такую, чтоб обычный юзверь, без дополнительных регистраций контекстов, мог зарегистрировать, наполнить и запустить еще пару тройку одностраничников, по готовым шаблонам — мне кажется так проще. Человеку просто нужно зайти и заполнить ресурс как обычно + добавить url в поле — больше ничего делать не нужно (ну кроме регистрации домена, но это уже не касается системы)
                Алексей
                Алексей Проверенный
                09 октября 2017, 17:41
                modx.pro/development/2157-method-sendforward-and-save-the-fields-of-the-resource/
                А вот контент поменять врятли удастся:
                github.com/modxcms/revolution/pull/13163
                Вообще это хороший вопрос про sendforward
                  Василий Наумкин
                  Василий Наумкин Администратор
                  10 октября 2017, 12:39
                  Если покопаться в MODX API то можно научиться выводить любой ресурс в плагине на нужном событии:
                  $modx->resource = $modx->getObject('modResource', $modx->getOption('site_start'));
                  $modx->resource->set('content', $pdoTools->runSnippet('@FILE snippets/get_panel.php'));
                  $modx->request->prepareResponse();
                  Здесь, как видно, еще и замена контента на свой идёт, на лету.

                  Можно так на лету и виртуальные ресурсы делать, со своими pagetitle и прочими свойствами. При желании, можно вообще весь сайт без ресурсов сделать =)
                    Арсений
                    Арсений Проверенный
                    10 октября 2017, 15:23
                    Хорошая штука:) Василий, а что скажете на счет такой реализации? Работать то она работает, но не является ли это каким-то велосипедом? Как-то привык доверять вашему мнению)
                      Василий Наумкин
                      Василий Наумкин Администратор
                      10 октября 2017, 15:29
                      Ну а что здесь велосипедного?

                      MODX делает примерно тоже самое при загрузке страницы, просто дольше и с большими условиями.
            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
            16