Очень хитрые 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Илья Уткин
04.02.2013 21:21

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

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

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

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

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

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

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

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

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

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

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

agel_nashЕвгений Борисов
05.02.2013 10: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 11:06

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

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

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

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

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

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

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

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

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

argnistВиталий Киреев
05.02.2013 20:22

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

bezumkinВасилий Наумкин
05.02.2013 20:47

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

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

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

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

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

до

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

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

shadowВладимир
22.02.2013 21:00

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

alexeytulaАлексей
02.04.2013 21:10

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

Ошибка здесь

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

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

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

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

bezumkin
Василий Наумкин
09.04.2024 01:45
Ошибка 500 Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи. Во...
futuris
Futuris
04.04.2024 05:56
Я просто немного запутался. Когда в абзаце &quot;Vesp/Core&quot; ты пишешь про &quot;новый trait Fil...
bezumkin
Василий Наумкин
20.03.2024 18:21
Volledig!
Андрей
14.03.2024 10:47
Василий! Как всегда очень круто! Моё почтение!
russelgal
russel gal
09.03.2024 17:17
А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал ...
inetlover
Александр Наумов
27.01.2024 00:06
Василий, спасибо! Извини, тупанул.
bezumkin
Василий Наумкин
22.01.2024 04:43
Давай-давай!
bezumkin
Василий Наумкин
24.12.2023 11:26
Спасибо!
bezumkin
Василий Наумкин
27.11.2023 02:43
Ура!
bezumkin
Василий Наумкин
25.11.2023 08:30
Vesp тянет 2 зависимости: vesp-frontent для фронта и vesp-core для бэкенда. Их можно обновлять, но э...