Очень хитрые TV параметры

У любого ресурса MODX есть ограниченное число полей, таких как pagetitle, content, introtext. Чтобы расширить этот функционал, и добавить, например, картинку к заметке - нужны дополнительные поля.

В MODX они называются Template Variables, то есть, TV.

Это очень мощная система, и тэвэшки можно создавать бесконечно много, с разными свойствами и наворотами. Чем многие и злоупотребляют.

Объясняю почему. Один TV - это одна строка в таблице modTemplateVarResource. Если нужно получить 10 TV - это обычно 10 запросов в базу. Если нужно отсортировать по ним - еще сложнее и дольше.

Вот и выходит, что "MODX тормозит", когда на один ресурс навешано штук 20 ТВ и они выводятся на каждой странице с getResources.

Лично я стараюсь их вообще не использовать, но на ум пришла интересная идея. Нужно дублировать TV в поле properties ресурса, которое хранит json строку с любой информацией.

Вот плагин, для дублирования:

<?php
if ($modx->event->name == 'OnBeforeDocFormSave') {
    $tvs = array();

    foreach ($_POST as $k => $v) {
        if (preg_match('/^tv[0-9]+$/', $k)) {
            $tvs[$k] = $v;
        }
    }
    
    $properties = $resource->get('properties');
    ksort($tvs);
    $properties['tvs'] = $tvs;
    $resource->set('properties', $properties);
}

Он смотрит в $_POST при сохранении ресурса, и копирует TV куда надо. Обратите внимание, что используются id параметров с префиксом tv. Можно, конечно, и получать имена TV, но это лишняя работа при сохранении ресурса. К тому же, если вы переименуете параметр - эта инфа не обновится самостоятельно. Поэтому, тэвэшки будут просто tv1, tv2, tv3 в массиве tvs.

Отдельный массив tvs нужен, чтобы не затереть что-то нужное, так как поле properties используют и компоненты, например Articles и Tickets. Ключи перед сохранением сортируются, так что TV в поле будут всегда по возрастанию id.

А дальше мы можем выводить их обычным getResources, используя плейсхолдеры. Парсер разбирает массивы в ресурсе и склеивает ключи через точку.

[[+properties.tvs.tv1]]
[[+properties.tvs.tv2]]
[[+properties.tvs.tv3]]
и т.д.

То есть, значения TV параметров будут выводиться без лишних запросов в БД. Конечно, &processTVs работать не будет - ну и фиг с ним.

В любом случае, это легко можно использовать на загруженный сайтах, для ускорения вывода ресурсов. Теоретически, можно даже криво фильтровать по полю properties, но мне так и не удалось передать подходящий вызов в параметр &where.

Можно написать сниппет на pdoTools и он должен нормально выбирать, но я не проверял. В любом случае, эта фильтрация будет очень ограниченной, просто поиск по

`parameters` LIKE '%"tv1":"string"%'

Обновлено 05.02.13

В комментариях был километровый срач, который пришлось почистить, но для любопытных остался скриншот.

← Предыдущая заметка
Полезный сниппет для блога.
Следующая заметка →
Полезные выборки xPDO
Комментарии (16)
ilyautkinИлья Уткин
05.02.2013 01:21

Оу, даже не задумывался раньше о том, что можно использовать еще и это поле у ресурсов. Блин, классно, спасибо)

argnistВиталий Киреев
05.02.2013 10:19

Плохо, что без названий. Разве так упомнишь по номерам что куда вставлять...

bezumkinВасилий Наумкин
05.02.2013 10:21

В дереве элементов есть id ТВ параметров. Так что, никаких проблем.

alexeytulaАлексей
05.02.2013 13:18

Да, интересная идея! Возьмем на заметку! Вообще, производительность этих TV настолько слабая, что очень затрудняет их использование.

AlroniksИван Климчук
05.02.2013 14:27

Слабая скорость из-за очень гибкой и мощной по возможностям структуры данных и двойного join (сначала джойним таблицу с самими TV, а затем еще и таблицу со значениями этих TV).

agel_nashЕвгений Борисов
05.02.2013 15:01

начиная с версии Evolution идеология у TV параметров была другая. Их должны были использовать для формирования визуальных элементов при редактировании данных из других таблиц. А т.к. это сложный хинт и так делают редко, то пользуются ТВшками именно для хранения данных. Яркий пример иного использования TV - плагин TagSaver для Evo.

agel_nashЕвгений Борисов
05.02.2013 14:56

Еще в ноябре 2011 писал такой плагин, когда Валентин рассказал мне про property. Я так понимаю вся эта возня из-за того, что про него никто не упомянул в этом топике. Да, общественность только сейчас про эти фишки узнает... Обидно(

А вот моя версия плагина.

<?php
if($modx->event->name=='OnDocFormSave'){
$template = $resource->get('template');
$templateObj=$modx->getObject('modTemplate', $template);
$tvList=$templateObj->getTemplateVarList();
$data=array();
foreach ($tvList['collection'] as $tv) {
    $name=$tv->get('name');
    $data[$name] =  $resource->getTVValue($tv->get('id'));
}
  $resource->setProperties($data);
  $resource->save();
}

Как видно, я тут работаю не POST данными, а с уже сохраненными значениями, т.к. могут быть и другие плагины которые модифицируют значения TV параметров. +1 SQL запрос в админке при сохранении документа я думаю это не страшно.

agel_nashЕвгений Борисов
05.02.2013 15:06

ноябре 2012)) Не привык еще к 2013 году)))

bezumkinВасилий Наумкин
05.02.2013 16:24

Как то сложно ты получаешь тэвэшки. Почему не через getMany?

$tvs = $resource->getMany('TemplateVars')

Будет коллекция объектов всех ТВ ресурса.

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

98b503e504239ead5cc360331СикретНаме
05.02.2013 17:00

Почитал, вспомнил, как улыбнули слова: "по семейным обстоятельствам, Валентин не сможет...", ещё раз улыбнуло :0)

Я видел этот Talk и не понимаю, зачем взрослые дяди огород разводят. Ну сделали Вы Hybrid, ну сделал Валентин Talk - ну так и развивали бы их каждый по своему. Кто-то из вас у другого что, почти весь код украл? Вроде нет. О чём сыр-бор - НЕ понятно...

argnistВиталий Киреев
06.02.2013 00:22

Я эти пропертис еще в прошлом июне в своем проекте активно использовал (поэтому сразу добавил их поддержку в свой fastField), причем примерно так же, как в варианте Евгения Борисова. Что мне теперь тоже трясти "авторскими правами"?)) Правда в итоге все переписал на собственные таблицы, потому что стали нужны выборки по этим твшкам. То есть в админке редактируются TV, а плагин их запоминают в кастомную таблицу. Практически прообраз кастомного ресурса)...

bezumkinВасилий Наумкин
06.02.2013 00:47

Выходит, я и у тебя идею украл!

Вот я молодец!

agel_nashЕвгений Борисов
05.02.2013 16:38

Согласен. Можно сократить

$template = $resource->get('template');
$templateObj=$modx->getObject('modTemplate', $template);
$tvList=$templateObj->getTemplateVarList();

до

$tvList = $resource->getMany('TemplateVars')

В ней все равно используется getTemplateVars(); Но непомню что меня смутило тогда. Скорее всего возникла мысль, что если без дополнительной инициализации доставать значения, то есть вероятность не получить еще не сохраненные данные. Т.е. вернутся те, которые были во время предыдущего сохранения, т.к. объект еще обновиться не успел. Проверять не стал и поэтому создал новый объект.

shadowВладимир
23.02.2013 01:00

Почему то не срабатывает плагин. Посмотрел в базе, в ячейку properties в таблице modx_site_content, не копируются туда значения из tv ... Что не так ?... не пойму...

alexeytulaАлексей
03.04.2013 01:10

Видно, Василий, ваш код еще никто не пробовал) Или молчат все.

Ошибка здесь

$properties['tvs'] = ksort($tvs);

ksort не возвращает массив, она возвращает true или false, поэтому так:

ksort($tvs);
$properties['tvs'] = $tvs
bezumkinВасилий Наумкин
04.04.2013 13:40

Поправил, спасибо!

futuris
Futuris
16.03.2023 17:04
Ок, вижу \core\vendor\vesp\core\src\Controllers Спасибо!
futuris
Futuris
14.03.2023 16:04
Была папка tmp, и удалял и переустанавливал ее - все без толку. Выше товарищ правильно написал, что ...
inetlover
Александр Наумов
22.02.2023 19:10
Спасибо! Да, мне здесь подучиться нужно.
bezumkin
Василий Наумкин
19.02.2023 19:49
Не такая уж тут активность в комментриях, чтобы что-то снижать - а удобнее будет, в первую очередь м...
inetlover
Александр Наумов
19.02.2023 15:12
Спасибо!
inetlover
Александр Наумов
06.02.2023 00:48
Ок, спасибо!
inetlover
Александр Наумов
28.01.2023 18:27
Классно, все работает!
inetlover
Александр Наумов
24.01.2023 18:31
Понял, спасибо!
inetlover
Александр Наумов
16.01.2023 16:41
Понял, спасибо!
bezumkin
Василий Наумкин
14.01.2023 05:16
Да, мне тоже нравится Vite и он по умолчанию используется в Vue 3 и Nuxt 3. Более того, он вроде как...