Как уйти от TV и увеличить быстродействие MODX mFilter2?

Александр
2K
2
Александр Здравствуйте! Вы в одном из комментариев отметили что для того, чтобы, скорость фильтрации mFilter2 возросла, необходимо чтобы значения tv сохранялись в отдельной таблице, озадачился этой темой но инфы по поводу этого просто ноль, не могли бы вы если это возможно, описать как создать отдельную таблицу и сохранять значения tv которые для фильтрации там а далее как указать фильтру эту таблицу?

Комментарии ()

  1. Александр
    10 января 2020, 00:43
    Александр Здравствуйте! Столкнулся с проблемой решил не создавать отдельный вопрос, так как, есть предположение что проблема с дополнением msFavorites (Избранное), связана с расширением класса mfilter2.

    В чанке deflaut, mFilter2, вызов избранного такой:
    <a class="msfavorites"
               data-click
               data-data-list="default"
               data-data-type="resource"
               data-data-key="[[+id]]"
               data-msfavorites-animation="img/like.png"
               
            >
                <i class="msfavorites-icon-heart"></i>
            </a>
            <span class="msfavorites-total"
                  data-data-list="default"
                  data-data-type="resource"
                  
            >0</span>
    всё работает, ошибок нет, но проблема с множественной подгрузкой одного и того же файла, action.php, если открыть консоль браузера, раздел XHR, далее перезагрузить страницу с фильтром, будет видно, что грузиться один файл, action.php, это нормально, далее, если отметить один чекбокс в фильтре и перезагрузить страницу, будет видно что грузятся уже три одинаковых файла action.php, отмечаю в фильтре еще пару чекбоксов, перезагружаю страницу, грузятся уже 8 одинаковых файлов, чем больше в фильтре отмечено чекбоксов, тем больше одинаковых вызовов action.php, дополнения msFavorites.

    Пытался убирать сторонние скрипты с шаблона, думал может в них проблема, грешил на дополнение, но тестанул и это походу не тот случай, так и не могу точно найти источник проблемы, остаётся только расширенный класс mFilter2. Александр, подскажите пожалуйста, что можно попробовать сделать в данном случае?

    Скриншот консоли браузера раздела XHR:
    1. Александр
      10 января 2020, 03:12
      Александр, баг с коннектором был в дополнении, сейчас всё работает, та версия с которой я тестил и пытался создать аналогичную проблему, была новая и проблемы с коннектором, там уже не было, поэтому был сделан ошибочный вывод, что причина не в msFavorites, а оказалось именно в нём.
    2. Sergey
      06 декабря 2019, 14:01
      Может есть способ проще, без создания таблицы… по типу как тут?
      modx.pro/howto/13058
      1. Александр Мальцев
        07 декабря 2019, 15:17
        В случае с TV параметрами исключать нечего, поэтому наиболее корректный вариант – это оптимизировать данные в базе данных. Или вообще избавиться от них, и написать свои решения.
      2. Sergey
        29 ноября 2019, 22:02
        Скажите, а если уже имеется каталог с tv параметрами у mFilter2 этот способ поможет?
        1. Александр
          30 ноября 2019, 20:21
          Да поможет, сейчас у вас фильтрует по дефолтной таблице а с этим вариантом будет по той которую создадите.
          При редактировании ресурса, значения полей так же сможете изменять как и раньше, только в данном случае при заполнении тв у ресурса помимо дефолтной таблицы они будут дублироваться в новую таблицу. Уменьшиться количества запросов к базе и скорость фильтрации возрастёт. Перед тем как будите что-то менять, сделайте резервною копию базы данных и сайта. Способ отличный, спасибо Александру за подробное руководство.
        2. Александр Мальцев
          29 сентября 2019, 02:25
          Вот так можно сделать фильтр в mFilter2 для своей таблицы.

          1. Создать файл \core\components\msearch2\custom\filters\custom.class.php:
          <?php
          class myCustomFilter extends mse2FiltersHandler {
          
            public function __construct(mSearch2 &$mse2, array $config = array()) {
              parent::__construct($mse2, $config);
              $this->modx->addPackage('extendResource' ,MODX_CORE_PATH.'components/extendresource/model/');
            }	
          
            public function getExtendresourceValues(array $fields, array $ids) {
              $filters = array();
              $q = $this->modx->newQuery('modResource', array('modResource.id:IN' => $ids));
              $q->leftJoin('extendResource', 'myTV',
                'myTV.resource = modResource.id'
              );
              $q->select('myTV.resource as id, myTV.tv1 as tv1, myTV.tv2 as tv2, myTV.tv3 as tv3');
              $tstart = microtime(true);
              if ($q->prepare() && $q->stmt->execute()) {
                $this->modx->queryTime += microtime(true) - $tstart;
                $this->modx->executedQueries++;
                while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
                  if (empty($row['id'])) {
                    continue;
                  } elseif ((is_null($row['tv2']) || trim($row['tv2']) == '') && (is_null($row['tv1']) || trim($row['tv1']) == '') && (is_null($row['tv3']) || trim($row['tv3']) == '')) {
                    continue;
                  }
                  $tmp = strpos($row['tv2'], '||') !== false
                    ? explode('||', $row['tv2'])
                    : array($row['tv2']);
                  foreach ($tmp as $v) {
                    $v = str_replace('"', '"', trim($v));
                    if ($v == '') {
                      continue;
                    }
                    $name = 'tv2';
                    if (isset($filters[$name][$v])) {
                      $filters[$name][$v][$row['id']] = $row['id'];
                    } else {
                      $filters[$name][$v] = array($row['id'] => $row['id']);
                    }
                  }
                  $tmp = strpos($row['tv1'], '||') !== false
                    ? explode('||', $row['tv1'])
                    : array($row['tv1']);
                  foreach ($tmp as $v) {
                    $v = str_replace('"', '"', trim($v));
                    if ($v == '') {
                      continue;
                    }
                    $name = 'tv1';
                    if (isset($filters[$name][$v])) {
                      $filters[$name][$v][$row['id']] = $row['id'];
                    } else {
                      $filters[$name][$v] = array($row['id'] => $row['id']);
                    }
                  }
                  $tmp = strpos($row['tv3'], '||') !== false
                    ? explode('||', $row['tv3'])
                    : array($row['tv3']);
                  foreach ($tmp as $v) {
                    $v = str_replace('"', '"', trim($v));
                    if ($v == '') {
                      continue;
                    }
                    $name = 'tv3';
                    if (isset($filters[$name][$v])) {
                      $filters[$name][$v][$row['id']] = $row['id'];
                    } else {
                      $filters[$name][$v] = array($row['id'] => $row['id']);
                    }
                  }
                }
              } else {
                $this->modx->log(modX::LOG_LEVEL_ERROR, "[mSearch2] Error on get filter params.\nQuery: ".$q->toSQL()."\nResponse: ".print_r($q->stmt->errorInfo(),1));
              }
              return $filters;
            }
          
          }
          
          2. В системных настройках в разделе mSearch2 в параметре mse2_filters_handler_class указать свой класс-обработчик для фильтров:
          myCustomFilter
          
          3. Настроить сниппет mFilter2:
          [[!mFilter2? 
            ...
            &loadModels=`extendresource`
            &filters=`extendresource|tv:default`
          ]]
          
          1. Александр
            20 июля 2020, 17:15
            Александр, здравствуйте! Не так давно, вышло обновление mSearh2 1.14-0-pl, где добавлена возможность кэширование предварительных результатов и сразу возникли проблемы с фильтрацией по своей таблицы а именно с предварительными подсчётами и правильным построением результатов, происходит это так у всех фильтров в фильтре в предварительных результатах одно и тоже число, при выборе любого фильтра остальные становятся не доступны, логика полностью нарушена, до этого были проблемы с подсчётами и тогда помогло такое решение, добавить пару строчек кода в файл custom.class.php:

            //Правильные подсчёты в mFilter2
            public function filterDefault(array $requested, array $values, array $ids) {
                 return array_unique(parent::filterDefault($requested,$values,$ids));
            }
            после всё работало, но после обновления mSearh2, такой вариант не прокатывает, подскажите пожалуйста что можно попробовать сделать?
            1. Александр Мальцев
              06 августа 2020, 15:29
              Здравствуйте! Это нужно смотреть какие изменения были сделаны в этой версии. Но так как проект закрытый и его нет на Github, то узнать, что в коде было изменено так просто не получится. Если найдёте какие изменения были конкретно сделаны в новой версии, то в этом случае уже можно будет что-то предложить.
            2. Александр
              04 октября 2019, 21:49
              Здравствуйте, изначально не заметил но сортирует не правильно:

              Вызов такой:
              <a href="#" data-sort="extendresource|tv1" data-dir="[[+mse2_sort:is=`extendresource|tv1:desc`:then=`desc`]]" data-default="desc" class="sort">Тест <span></span></a>
              с чем связано не подскажите?
              1. Александр
                05 октября 2019, 03:56
                Возможно кому пригодиться, проблема с сортировкой была у полей, которых значения в виде числа: пример: 5000,350,580 и т.д, у таких полей в таблице, тип поля нужно выбрать: smallint.
                1. Александр Мальцев
                  05 октября 2019, 07:41
                  Как понимаю, проблема с сортировкой решилась. Нужно было чтобы она выполнялась как с числами, а она выполнялась как со строками.
                  1. Александр
                    05 октября 2019, 16:01
                    Да, с сортировкой проблема решилась, хотел бы уточнить кое какие моменты, для чисел нужно использовать INT, для текста VARCHAR или TEXT — тогда всё должно сортироваться верно.
                    1. Александр Мальцев
                      06 октября 2019, 06:11
                      В основном эти.
                      Для целых чисел int, для строк с переменной длиной от 1 до 255 символов varchar, text — для строк с максимальной длиной, равной 65535 символов.
                      Ещё бывает используется tinyint для хранения маленьких чисел (со знаком от –128 до 127, без знака от 0 до 255), datetime — для даты и время, и mediumtext — для больших текстов с максимальной длиной до 16777215 символов.
              2. Александр
                30 сентября 2019, 04:38
                По одному из вопросов в предыдущем сообщении, касаемо своего чанка для каждой группы фильтров, проблем нет, у меня не работало потому-что, забыл прописать aliases, выводиться обычным способом:
                &tplFilter.outer.tv1=`tpl.имя чанка`
                1. Александр
                  29 сентября 2019, 18:39
                  Александр, огромнейшее Вам спасибо, за уникальную и ценнейшую информацию. Получилось вывести фильтры, фильтрация работает, но не могу понять кое какие моменты.

                  Вывожу фильтр так:

                  [[!mFilter2?
                  &tvFiltersOrDelimiter=`||`
                  &tpl_5=`tpl5th`
                  &parents=`0`
                  EmptyFilters=`1`
                  &tpls=`tpl_default`
                  &includeTVs=`data,tv1,tv2`
                  &noPreciseMSFilters=`1`
                  &forceSearch=`0`
                  &setMeta=`0` 
                  &suggestions=`1`
                  &showLog=`0`
                  &limit=`25`
                  &paginator=`pdoPage`
                  &ajaxMode=`button`
                  &toSeparatePlaceholders=`my.`
                  &loadModels=`extendresource`
                  
                  &filters=`
                  extendresource|tv:default
                  `
                  &aliases=`
                  extendresource|tv1==tv1,
                  `
                  &tplFilter.outer.my.tv1=`tpl.outertv1`
                  &tplFilter.outer.tv|tv2=`tpl.mFilter2.filter.slider`
                  ]]
                  1) Вот в этой строке: &includeTVs=`data,tv1,tv2` как правильно указать?

                  2) Не понятно как правильно указать чанк для группы фильтров: &tplFilter.outer.my.tv1=`tpl.outertv1`?

                  3) Сколько не пытался не получается вывести значения tv в результатах фильтра, создал сниппет, назвал getTVFields, поместил вызов в шаблон, где вызываю mfilter2:
                  [[!getTVFields? &id=`[[*id]]`]]
                  В чанке:
                  [[!+my.tv1]]
                  не выводит, подозреваю что не правильно указал тв в вызове фильтра:
                  &includeTVs=`data,tv1,tv2` ?
                  4) Как можно убедиться в том, что фильтрует именно по этой таблице а не дефолтной?

                  5) Группы фильтров вывожу так: [[+my.extendresource|tv2]], это правильный вариант?

                  6) Теперь если я правильно понимаю при добавлении нового тв, нужно править файл в этой строке:
                  $q->select('myTV.resource as id, myTV.tv1 as tv1, myTV.tv2 as tv2, myTV.tv3 as tv3');
                  и тут:
                  $tmp = strpos($row['tv1'], '||') !== false
                            ? explode('||', $row['tv1'])
                            : array($row['tv1']);
                          foreach ($tmp as $v) {
                            $v = str_replace('"', '"', trim($v));
                            if ($v == '') {
                              continue;
                            }
                            $name = 'tv1';
                            if (isset($filters[$name][$v])) {
                              $filters[$name][$v][$row['id']] = $row['id'];
                            } else {
                              $filters[$name][$v] = array($row['id'] => $row['id']);
                            }
                          }
                  6) Как я понимаю, если установлен сео-фильтр, чтобы он работал с этой таблицей, там нужно выбрать, (значение в другой таблице), как правильно там прописать, подскажите пожалуйста?


                  1. Александр Мальцев
                    30 сентября 2019, 14:53
                    В SeoFilter:
                    — компонент: extendresource
                    — класс: extendResource
                    — поле для сопоставления (id): resource
                    — поле, где хранится значение (name): tv1
                    1. Александр
                      01 октября 2019, 00:40
                      SeoFilter при таком раскладе не хочет нормально работать, что с параметрами что без них не работает, а именно подсчёты не работают и хлебные крошки через ajax ну и в админке вкладка сео-страницы, название страниц не выводит, походу там тоже нужно расширять класс, чтобы работало нормально? Сейчас всё завязано на этом: modTemplateVar
                      1. Александр Мальцев
                        01 октября 2019, 14:04
                        SeoFilter не использовал, могу подсказать только навскидку.
                        1. Александр
                          01 октября 2019, 18:41
                          Как я понимаю, если использовать свой класс в SeoFilter, там нужно расширять его, примерно так-же как и в mFilter2, тогда подсчёты будут работать, это так мысли в слух.
                    2. Александр Мальцев
                      30 сентября 2019, 14:29
                      Параметры «&includeTVs», «&tvFiltersOrDelimiter» и другие, связанные с TV не нужны. Иначе они будут включаться в запрос. Выборка данных осуществляется же с другой таблицы.
                      В этом случае сниппет нужно вызывать в чанке и в нём id записи уже будет плейсхолдер [[+id]]:
                      [[!getTVFields? &id=`[[+id]]`]]
                      
                      Или вообще не использовать сниппет, а сделать так:
                      [[!mFilter2? 
                        &loadModels=`extendresource`
                        &leftJoin=`{
                          "extendResource": {
                            "class": "extendResource",
                            "alias": "extFields", 
                            "on": "extFields.resource = modResource.id"
                          }
                        }`
                        &select=`{
                          "extFields": "extFields.tv1 as tv1, extFields.tv2 as tv2, extFields.tv3 as tv3"
                        }`
                        ...
                      
                      Поставьте debugParser и протестируйте время и количество запросов. Параметр «&filters» определяется почему будет фильтроваться.

                      При добавлении нового поля нужно добавить ещё в условие, где оно проверяется на пустоту или null.
                      1. Александр
                        30 сентября 2019, 19:39
                        Александр, по всем вопросам всё предельно понятно, спасибо. DebugParser, пользуюсь им и отслеживаю каждый килобайт и запрос, лишний надеюсь не проскочит:) но есть проблема только с выводом значений в результатах фильтра на сколько я понимаю, более а точнее менее затратный по ресурсам, это второй вариант: leftJoin, у меня не получается вывести, если я в чанке вызываю так: [[!+tv1]] то тянуться значения с дефолтной таблицы и не зависимо от того, есть ли в вызове mFilter2 ваш пример: leftJoin, проверил это ручным удалением с дефолтной таблицы значения. Если делаю так: [[!+extFields.tv1]] то не выводит не чего, очевидно что я просто не правильно делаю вызов?
                        1. Александр Мальцев
                          01 октября 2019, 14:25
                          Наиболее просто — это вывести все плейсхолдеры на экран и посмотреть, как они называются. Для этого параметру устанавливающему чанк для каждого результата нужно в качестве значения установить пустую строку:
                          &tpl = ``
                          
                          1. Александр
                            01 октября 2019, 20:33
                            По поводу разделителя, хотел бы уточнить свой вопрос, понимаю что можно выводить так:
                            [[!+tv1:replace=`||==, `]]
                            , но интересует ваше мнение и есть ли ищё какие варианты вывода? Можно ли в &leftJoin это прописать?
                            1. Александр Мальцев
                              02 октября 2019, 11:50
                              Обработку лучше выполнять после получения данных.
                              Можно через Fenom:
                              {var $arrtv1 = $tv1 | split : '||'}
                              {if $arrtv1 | iterable}
                                  {foreach $arrtv1 as $value}
                                      <div>{$value}</div>
                                  {/foreach}
                              {/if}
                              
                              Так же можно написать пользовательские модификаторы вывода. Они реализуются через сниппеты, тут уже можно написать любую логику.
                              1. Александр
                                02 октября 2019, 23:08
                                Александр, спасибо.
                            2. Александр
                              01 октября 2019, 19:09
                              Александр, подскажите пожалуйста, как изменить разделитель || при выводе значений на, с помощью модификатора? как лучше и правильней это делать?
                              1. Александр
                                01 октября 2019, 18:53
                                Спасибо! Мистика честно говоря, вызов обычный: [[!+tv1]] выводит и при чём выводит с новой таблицы, всё как нужно, это при том, что я удалил с дефолтной таблицы в ручную все значения, оставил только их в новой таблице, но не понятно почему тогда, когда значения находились в обоих таблицах, при таком вызове: [[!+tv1]] выводились значения с дефолтной таблицы, вообще такое теоретические возможно, при указанном &leftJoin, если значения в обоих таблицах то выводятся с дефолтной, если только в новой, то с неё? И обязательно вызов должен быть не кешированым?
                                1. Александр Мальцев
                                  02 октября 2019, 11:55
                                  Может они переопределялись значениями дефолтной таблицы.
                      2. Александр
                        27 сентября 2019, 22:11
                        Александр, по поводу отсутствия id в таблице, оказывается забыл при создании таблицы поставить галку параметра auto_increment.
                        Сейчас выглядит так:


                        Остались только проблемы с разбиением, как я понимаю от этого зависит разделитель значений тв в таблице? что там указывать?

                        Так же не получается вывести в mfilter2, как нужно указать там?

                        Вывожу так:
                        [[!mFilter2?
                        &tvFiltersOrDelimiter=`||`
                        &parents=`0`
                        EmptyFilters=`1`
                        &includeTVs=`tv1`
                        &noPreciseMSFilters=`1`
                        &forceSearch=`0`
                        &setMeta=`0` 
                        &suggestions=`1`
                        &showLog=`0`
                        &limit=`25`
                        &paginator=`pdoPage`
                        &ajaxMode=`button`
                        &toSeparatePlaceholders=`my.`
                        
                        &filters=`
                        tv|tv1
                        `
                        &aliases=`
                        		tv|tv1==tv1
                        `
                        &tplFilter.outer.tv1=`tpl.checkboxmy`
                        ]]
                        1. Александр Мальцев
                          28 сентября 2019, 14:38
                          В плагине нужно поправить код:
                          ...
                          //$tv1 = $resource->getTVValue('tv1');
                          //$tv2 = $resource->getTVValue('tv2');            
                          //$tv3 = $resource->getTVValue('tv3'); 
                          
                          $tv1 = $modx->getObject('modTemplateVarResource', array(
                            'tmplvarid' => 1, // id TV
                            'contentid' => $id
                          ));
                          if (is_object($tv1)) {
                            $tv1 = $tv1->get('value');
                          } else {
                            $tv1= '';
                          }
                                 
                          $tv2 = $modx->getObject('modTemplateVarResource', array(
                            'tmplvarid' => 2, // id TV
                            'contentid' => $id
                          ));
                          if (is_object($tv2)) {
                            $tv2 = $tv2->get('value');
                          } else {
                            $tv2 = '';
                          }            
                                     
                          $tv3 = $modx->getObject('modTemplateVarResource', array(
                            'tmplvarid' => 3, // id TV
                            'contentid' => $id
                          )); 
                          if (is_object($tv3)) {
                            $tv3 = $tv3->get('value');
                          } else {
                            $tv3 = '';
                          }   
                          
                          Метод getTVValue выполняет обработку данных, поэтому вместо него нужно просто выбирать значения.

                          Таблица готова, теперь для выбора всех полей нужен всего 1 запрос.

                          По mFilter2 нет готового рецепта, тут нужно писать решение для этой таблицы, т.е. свой фильтр для mFilter2.
                          1. Александр
                            07 октября 2019, 01:28
                            Всё на много серьёзней оказывается, при сохранении любого ресурса в новой базе появляется пустая строка, как исправить не подскажите?
                            1. Александр Мальцев
                              07 октября 2019, 13:57
                              Это из-за того, что в плагине нет проверки.
                              TV привязываются к шаблону, поэтому можно написать проверку, в которой проверить id шаблона ресурса. Если id шаблона нужный, то выполнять сохранение, в противном случае прервать выполнение кода.
                              switch ($modx->event->name) {
                                  case 'OnDocFormSave':
                                  case 'OnDocPublished':
                                  case 'OnDocUnPublished':
                                  case 'OnResourceUndelete':
                                      // например, выполнять после условия, только для тех ресурсов, у которых id шаблона, равно 15
                                      if ($resource->get('template') !== 15) {
                                          break;
                                      }
                                      ...
                              
                              1. Александр
                                07 октября 2019, 15:50
                                То что нужно, спасибо.
                            2. Александр
                              07 октября 2019, 01:04
                              Заметил не большой баг, при сохранении ресурса в котором лежат все ресурсы, плагин добавил пустую строку в базе данных с id этого ресурса, на функционал не влияет но хотелось бы понять почему?
                              1. Александр
                                28 сентября 2019, 16:49
                                Здравствуйте! При таком раскладе в таблицу пишуться урл тв поля img чё то не правильно делаю?

                                <?php
                                $modx->addPackage('extendResource', $modx->getOption('core_path').'components/extendresource/model/');
                                
                                switch ($modx->event->name) {
                                 
                                        // Documents
                                        case 'OnDocFormSave':
                                        case 'OnDocPublished':
                                        case 'OnDocUnPublished':
                                        case 'OnResourceUndelete':
                                          
                                
                                $isPublished = $resource->get('published');
                                    $id = $resource->get('id');        
                                $tv1 = $modx->getObject('modTemplateVarResource', array(
                                  'tmplvarid' => 1, // id TV
                                  'contentid' => $id
                                ));
                                if (is_object($tv1)) {
                                  $tv1 = $tv1->get('value');
                                } else {
                                  $tv1= '';
                                }
                                       
                                $tv2 = $modx->getObject('modTemplateVarResource', array(
                                  'tmplvarid' => 2, // id TV
                                  'contentid' => $id
                                ));
                                if (is_object($tv2)) {
                                  $tv2 = $tv2->get('value');
                                } else {
                                  $tv2 = '';
                                }            
                                           
                                $tv3 = $modx->getObject('modTemplateVarResource', array(
                                  'tmplvarid' => 3, // id TV
                                  'contentid' => $id
                                )); 
                                if (is_object($tv3)) {
                                  $tv3 = $tv3->get('value');
                                } else {
                                  $tv3 = '';
                                }   
                                            
                                            
                                    $extendResource = $modx->getObject('extendResource',array(
                                               'resource' => $id,
                                            ));
                                            if (is_object($extendResource)) {
                                                if ($isPublished) {
                                                $extendResource->set('resource', $id);
                                                $extendResource->set('tv1', $tv1);
                                                $extendResource->set('tv2', $tv2);
                                                $extendResource->set('tv3', $tv3);
                                                $extendResource->save(); } else {
                                                  $extendResource->remove();
                                                }
                                            } else {
                                                if ($isPublished) {
                                                $extendResource = $modx->newObject('extendResource');
                                                $extendResource->set('resource', $id);
                                                $extendResource->set('tv1', $tv1);
                                                $extendResource->set('tv2', $tv2);
                                                $extendResource->set('tv3', $tv3);
                                                $extendResource->save();
                                                }
                                            }
                                        break;        
                                        
                                        case 'OnDocFormDelete':
                                          $extendResource = $modx->getObject('extendResource',array(
                                               'resource' => $resource->get('id'),
                                          ));
                                          if (is_object($extendResource)) {
                                              $extendResource->remove();
                                          }          
                                        break;     
                                }
                                1. Александр Мальцев
                                  28 сентября 2019, 23:00
                                  Сейчас TV указываются с помощью id. Значит нужно указать id нужных TV полей.
                                  'tmplvarid' => 1, // id TV
                                  
                                  1. Александр
                                    06 октября 2019, 02:37
                                    Вообщем проблема тут:
                                    addPackage('extendResource'
                                    крови она мне выпила, но странная вещь, на локалке работает на на хосте не в какую, поэтому изначально даже не предполагал что в этом весь гемор.
                                    1. Александр Мальцев
                                      06 октября 2019, 03:00
                                      На хосте создали таблицу в базе данных? Дополнение core/extendresource скопировали?
                                      1. Александр
                                        06 октября 2019, 04:58
                                        Хотя наверно я не прав, но факт есть, работает а по другому не работает, с чем связано не понятно.
                                        1. Александр
                                          06 октября 2019, 04:32
                                          Всё делал по новой, то есть с нуля, не работало если в плагине указано addPackage('extendResource' при чём пять раз переделывал, заработало addPackage('extendresource', по логике тут же должно быть название пакета, (папки extendresource) а не класса или я не прав?
                                          1. Александр Мальцев
                                            06 октября 2019, 05:57
                                            Там указывается название пакета (папки), так что должно быть маленькими буквами, т.е. extendresource. В коде неправильно написал. В Windows нет разницы прописная буква или строчная, поэтому и сработало. А на боевом сайте (в Linux) — нет, т.к. там есть разница прописная буква или строчная.
                                            1. Александр
                                              06 октября 2019, 15:45
                                              А зачем подгружать пакет плагин да без этого не работает, а в custom.class.php, если убрать блок construct работает, зачем он там нужен?
                                              1. Александр Мальцев
                                                06 октября 2019, 16:26
                                                Значит уже загружен, тогда подгрузка не нужна и фрагмент construct можно убрать.
                                      2. Александр
                                        05 октября 2019, 22:28
                                        Хотел бы дополнить и поправить вопрос, оказывается причина не в префиксе, не могу разобраться в чём, но как только устанавливаешь системное событие: OnDocFormSave, вылетают ошибки а при сохранении ресурса просто зависает, Александр если есть время внесите свою лепту по поводу этого, очень нужно?
                                        1. Александр
                                          05 октября 2019, 20:09
                                          Такие ошибки сыпятся:
                                          [2019-10-05 20:06:10] (ERROR @ /home/s20017/www/core/xpdo/xpdo.class.php : 644) Could not load class: extendResource from mysql.extendresource.
                                          [2019-10-05 20:06:10] (ERROR @ /home/s20017/www/core/xpdo/xpdo.class.php : 762) extendResource::load() is not a valid static method.
                                          [2019-10-05 20:06:10] (ERROR @ /home/s20017/www/core/xpdo/xpdo.class.php : 644) Could not load class: extendResource from mysql.extendresource.
                                          1. Александр
                                            05 октября 2019, 19:39
                                            Александр, если у базы данных префикс к примеру такой 2jbFDWbsFUQx, что в плагине нужно изменить? Просто возникла проблема если плагин установлен то не сохраняет ресурс, просто зависает при сохранении. На локалке всё работает на хосте с другим префиксом зависает.
                                            1. Александр Мальцев
                                              06 октября 2019, 06:22
                                              Префикс мы ни где не указывали. Он не нужен. Т.к. запрос к базе данных составляет сам механизм MODX и он, конечно, создаёт его с учётом префикса.
                                              Префикс может понадобиться, если писать SQL запросы напрямую. В этом случае нужно будет получить префикс таблиц и подставить его в SQL:
                                              $tablePrefix = $modx->getOption('table_prefix');
                                              
                                              1. Александр
                                                06 октября 2019, 15:57
                                                Спасибо, предельно понятно. Изначально грешил на него, когда были проблемы с плагином.
                                            2. Александр
                                              29 сентября 2019, 00:19
                                              Александр, где эти id? Если 3,4,5 у вас ниже на скрине тоже самое что и у меня, то с ними у меня не работает, так же если те id в таблице где у вас на втором скрине 5,6,7,8 они же не привязаны к конкретному полю или я чё то не догоняю, на всякий случай пробовал те и эти не сохраняет в таблице значения. В данном случае появляется пустая строка в таблице с новым id.


                                              1. Александр Мальцев
                                                29 сентября 2019, 01:50
                                                id TV это то что указано в круглях скобках в дереве элементов:
                                                Вкладка с элементами в MODX
                                                В этом примере tv1 имеет id, равный 7, tv2 имеет id, равный 8, tv3 имеет id, равный 9.
                                                1. Александр
                                                  29 сентября 2019, 02:26
                                                  :) Точно нужны же id полей, чтобы плагин знал какие брать с дефолтной таблицы, и дублировал их в новой, запутался не много, поэтому не сообразил, спасибо:) Теперь всё работает.

                                                  Александр а по поводу фильтрации с mfilter2 по этой таблице, как это примерно реализовать, расширять класс? Может есть готовое решение где нужно просто изменить по минимуму, к примеру взять с файла filter.class.php? как я понимаю сейчас даже не получиться вывести эти тв в результатах mfilter2
                                      3. Александр Мальцев
                                        27 сентября 2019, 13:44
                                        Привет!
                                        Первую часть вопроса можно реализовать воспользовавшись рецептом, описанным в этой статье.

                                        Т.е. открываете phpMyAdmin или какой-то другой инструмент для работы с базой данных. С помощью phpMyAdmin создаёте таблицу, например, modx_site_content_extend (modx_ — это префикс, который установлен для таблиц на сайте).
                                        Структура таблицы modx_site_content_extend
                                        Тут, всё понятно. Поле «id» – это первичный ключ, resource – это id ресурса, tv1, tv2, tv3, и т.д. – значения tv полей.

                                        После этого создаём в «/core/components» папку нашего приложения, например, extendresource. А в ней папку «model», а в ней папку «schema».
                                        В папке «schema» создадим файл «extendresource.mysql.schema.xml».
                                        Содержимое файла:
                                        <?xml version="1.0" encoding="UTF-8"?>
                                        <model package="extendresource" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
                                            <object class="extendResource" table="site_content_extend" extends="xPDOSimpleObject">
                                                <field key="resource" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" index="pk" />
                                                <field key="tv1" dbtype="mediumtext" phptype="string" null="false" />
                                                <field key="tv2" dbtype="mediumtext" phptype="string" null="false" />
                                                <field key="tv3" dbtype="mediumtext" phptype="string" null="false" />
                                                <index alias="resource" name="resource" primary="false" unique="true" type="BTREE" >
                                                    <column key="resource" length="" collation="A" null="false" />
                                                </index>
                                                <aggregate alias="Resource" class="modResource" local="resource" foreign="id" cardinality="one" owner="foreign" />
                                            </object>
                                        </model>
                                        
                                        Далее скачиваем скрипт parse_schema.php и помещае его в корень проекта.
                                        Открываем данный файл, вводим в него название «extendresource».
                                        Выполняем данный файл. Всё компонент готов.

                                        Далее создаём плагин со следующим содержимым:
                                        <?php
                                        $modx->addPackage('extendResource', $modx->getOption('core_path').'components/extendresource/model/');
                                        
                                        switch ($modx->event->name) {
                                         
                                                // Documents
                                                case 'OnDocFormSave':
                                                case 'OnDocPublished':
                                                case 'OnDocUnPublished':
                                                case 'OnResourceUndelete':
                                                  
                                                    $isPublished = $resource->get('published');
                                                    $id = $resource->get('id');
                                                    $tv1 = $resource->getTVValue('tv1');
                                                    $tv2 = $resource->getTVValue('tv2');            
                                                    $tv3 = $resource->getTVValue('tv3'); 
                                                    
                                                    $extendResource = $modx->getObject('extendResource',array(
                                                       'resource' => $id,
                                                    ));
                                                    if (is_object($extendResource)) {
                                                        if ($isPublished) {
                                                        $extendResource->set('resource', $id);
                                                        $extendResource->set('tv1', $tv1);
                                                        $extendResource->set('tv2', $tv2);
                                                        $extendResource->set('tv3', $tv3);
                                                        $extendResource->save(); } else {
                                                          $extendResource->remove();
                                                        }
                                                    } else {
                                                        if ($isPublished) {
                                                        $extendResource = $modx->newObject('extendResource');
                                                        $extendResource->set('resource', $id);
                                                        $extendResource->set('tv1', $tv1);
                                                        $extendResource->set('tv2', $tv2);
                                                        $extendResource->set('tv3', $tv3);
                                                        $extendResource->save();
                                                        }
                                                    }
                                                break;
                                                
                                                case 'OnDocFormDelete':
                                                  $extendResource = $modx->getObject('extendResource',array(
                                                       'resource' => $resource->get('id'),
                                                  ));
                                                  if (is_object($extendResource)) {
                                                      $extendResource->remove();
                                                  }          
                                                break;     
                                                
                                        }
                                        
                                        На вкладке «Системные события» отмечаем галочками пункты: OnDocFormDelete, OnDocFormSave, OnDocPublished, OnDocUnPublished и OnResourceUndelete.
                                        Системные события плагина MODX

                                        Данный плагин будет обновлять таблицу modx_site_content_extend при сохранении ресурса, публикации, снятие его с публикации и удалении.

                                        Данные таблицы modx_site_content_extend
                                        1. Александр
                                          28 сентября 2019, 01:57
                                          Поспешил не много, как я понял значения полей tv1 tv2 tv3, дублируются в таблицу modx_site_tmplvar_contentvalues, изначально ошибочно предполагая что сохраняться они будут только в новой таблице, поэтому решил что всё у меня работает, так как фильтрация работала. Александр, если не трудно подскажите как использовать эти поля, значения в фильтре? И просто выводить плейсхолдером?

                                          И нормально ли это что в таблице значения у тв без разделителя просто слитно в таком формате: СпичкиСтружка?

                                          1. Александр Мальцев
                                            28 сентября 2019, 15:25
                                            Да, они дублируются, иначе нужно было бы переписывать уже существующую логику на страницах. А так она будет использоваться там, где нужно сократить время. Например, если используется 7 TV, то вместо 7 запросов можно ограничиться одним.

                                            Т.к. таблица кастомная, то нужно писать свою логику для mFilter2.

                                            Выводить значения из своей таблицы можно реализовать через сниппет или плагин.
                                            Например, можно создать сниппет getExtendFields:
                                            <?php
                                            $modx->addPackage('extendResource', $modx->getOption('core_path').'components/extendresource/model/');
                                            
                                            $extendResource = $modx->getObject('extendResource',array(
                                              'resource' => $id,
                                            ));
                                            
                                            $tv1 = "";
                                            $tv2 = "";
                                            $tv3 = "";
                                            
                                            if (is_object($extendResource)) {
                                              $tv1 = $extendResource->get('tv1');
                                              $tv2 = $extendResource->get('tv2');
                                              $tv3 = $extendResource->get('tv3');
                                            }
                                                      
                                            $modx->setPlaceholders(array(
                                               'tv1' => $tv1,
                                               'tv2' => $tv2,
                                               'tv3' => $tv3,   
                                            ),'my.');
                                            
                                            return; 
                                            
                                            После этого поместить его вызов в шаблон:
                                            [[!getTVFields? &id=`[[*id]]`]]
                                            
                                            Вывести поля в этом случае можно так:
                                            [[!+my.tv1]]
                                            [[!+my.tv2]]
                                            [[!+my.tv3]]
                                            
                                          2. Александр
                                            27 сентября 2019, 23:15
                                            Александр всё работает ищё раз огромное спасибо, фильтрация тоже, только не понятны некоторые вещи, скажите, значения тв в таблице добавляются слитно, это нормально?

                                            Предупреждение (Разбиение отсутствует) как с этим решить вопрос?

                                            Как я понимаю сейчас при создание тв, если мне нужно чтобы его значения сохранялись в этой таблице, необходимо вручную добавить строку в таблице и указать название тв в плагине, правильно я понимаю?

                                            В компонентах не чего не нужно править для работы с этой таблицей?
                                            1. Александр Мальцев
                                              28 сентября 2019, 15:29
                                              Да, для дублирования TV в своей таблице нужно не только это выполнить, а также обновить схему компонента и сгенерировать ему новую модель.
                                            2. Александр
                                              27 сентября 2019, 21:17
                                              Александр душевное Вам спасибо, за развёрнутый ответ. Получилось сделать, чтобы сохранялись значений поля tv1 в этой таблице, но я что-то походу намудрил в создании таблицы, сделал скрины что у меня вышло:

                                              Как видно id нет и значения не разделяются


                                              И ошибки есть:


                                              В руководстве есть опечатка «modal» model.

                                              Подскажите пожалуйста в чём я допустил ошибку?

                                            Войдите, пожайлуста, в аккаунт, чтобы оставить комментарий.