Modx evo TV custom побитовые операции.

02 июля 2018

Мне нравится система управления сайтом Modx EVO. Возможно конечно есть и лучше решения, но я остановился имеено на этой системе. Почему не Modx REVO? Всё дело в том что в Modx REVO сильно тормозит админка. Видимая часть сайта работает быстро, а вот админка - это тормоз. Возможно в последних версиях это подправили, надо будет проверить и отписаться.

Но данная статья немного про другое, а именно про TV параметры. Все данные TV параметров вне зависимости от типа данных храняться в базе данных, в одной таблице (site_tmplvar_contentvalues). Структура таблицы очень простая - id параметра, id документа, value(данные). Тип столбца хранящий сами данные - текст. Можно конечно сделать customTV или воспользоваться MultiTV для хранения данных в своей таблице. Но тогда станет затруднительно использовать стандартное API modx evo.

В Modx можно сделать TV параметр Checkbox или Listbox (Multi-Select) с множественным выбором и тогда значения сохраниться в базе данных как текст примерно вот так: 17||38||46||11 и так далее. Данные хранящие таким образом неудобны для выборки. И если используешь TV параметр как какой нибудь фильт - то возникают трудности для быстрой выборки документов. Я много раз решал эту задачу разными способами, но в очередном проекте решил сделать по уму (ну как я это вижу).

Я решил использовать преимущество битовых операций. Битовые опрерации реализованы и в PHP и в базах данных. Но есть небольшой минус: в 32 битной версии PHP максимальное количество позиций в фильтре - 32. Но сейчас практически у всех хостеров 64 битные версии операционных систем, соответственно и ПЫХ 64 битный. А это уже 64 позиции для фильтра, хотя и 32 позиции не так уж и мало.

Я написал свой customTV параметр filtersAdd. Код не сложный. В результате в поле value храниться число - integer, а выборку можно производить с помощью битовых операций.
Вот код:
<?php
///defined('IN_MANAGER_MODE') or die();
if(!defined('MODX_BASE_PATH')){die('What are you doing? Get out of here!');}

$result = '';
$parentID = null;
$table = $modx->getFullTableName("site_content");
$table_tv = $modx->getFullTableName("site_tmplvar_contentvalues");

//Это массив ID TV параметра => ID родителя содержаший документы (фильтры) 

$filterArr = array(
    48 => 513,
    49 => 514,
    50 => 515,
    51 => 516,
    52 => 517
);

if (array_key_exists($field_id, $filterArr))
{
    $parentID = $filterArr[$field_id];
}

if(!empty($parentID))
{
    $valueB = $field_value;
    $result .= '<div id="filtersAdd_'.$field_id.'">';
    $result .= '<div id="filtersAddhead_'.$field_id.'">'.$modx->runSnippet('DocInfo', array('docid' => $parentID, 'field' => 'pagetitle')).'</div>';

    $result .= '<div id="filtersAddbody_'.$field_id.'">';
    $filtersDoc = $modx->getDocumentChildren($parentID);
    foreach($filtersDoc as $k => $v) {
       $value = (1 << $k);
       $ch = ($valueB & $value);
       $checked = (($valueB & (1 << $k)) > 0)? ' checked="checked" ' : '';
       $result .= '<div><input type="checkbox" data-value="'.$value.'" '.$checked.' value="'.$value.'" onchange="inpChangeFL'.$field_id.'(this);"> '.$v['pagetitle'].'</div>';
    }
    $result .= '</div>';
    $result .= '</div>';
}

echo '<script type="text/javascript">
   function inpChangeFL'.$field_id.'(o) {
      let items = document.getElementById( "filtersAddbody_'.$field_id.'" ).getElementsByTagName("input"), len, i;
      let result = 0;
      for (i = 0, len = items.length; i < len; i += 1) {
          if (items.item(i).checked) {
             value = parseInt(items.item(i).dataset.value);
             result = result + value;
          }
      }

      if(result > 0) {
         document.getElementById("tv'.$field_id.'").value = result;
      } else {
         document.getElementById("tv'.$field_id.'").value = "";
      }
  }
</script>';

echo '
<style type="text/css">
#tv'.$field_id.' {display:none;}
#filtersAdd_'.$field_id.' {width:100%; border: 1px solid #000; margin-bottom: 30px;}
#filtersAddhead_'.$field_id.' {width:100%; padding: 10px; border-bottom: 1px solid #000; background-color: #ccc;}
#filtersAddbody_'.$field_id.' {padding: 10px;}
#filtersAddbody_'.$field_id.' div {margin: 5px 0;}
</style> ';

echo '<input type="text" name="tv'.$field_id.'" id="tv'.$field_id.'" value=\''.$field_value.'\' onchange="documentDirty=true;" >';
echo $result;

?>

Надеюсь этот код поможет кому-нибудь.
Андрей Лебедев

,

, , ,

Комментарий

Нет комментарий.

Комментировать: