Наверх

Часть 4. Связи объектов, getOne, getMany, работа с ТВ

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

Итак, создайте новый TV-параметр, назначьте его одному из шаблонов и у какого-нибудь ресурса установите значение этого параметра.

Думаю, вы уже догадались, что TV-параметры — это тоже объекты) У TV-параметров класс modTemplateVarResource.

Давайте посмотрим, как же выглядят эти объекты:
$tvs = $modx->getCollection('modTemplateVarResource');
foreach ($tvs as $k => $tv) {
    $tvs[$k] = $tv->toArray();
}
print '<pre>';
print_r($tvs);
Если хоть у одного из ресурсов заполнено хоть одно из дополнительных полей, вы увидите это значение в результате выполнения скрипта.

У объектов класса modTemplateVarResource есть поля: id, tmplvarid, contentid и value.
tmplvarid — id самого дополнительного поля (во вкладке «Элементы» рядом с названием TV),
contentid — id ресурса,
value — соответственно, значение данного TV-параметра у данного ресурса.
Соответственно, чтобы узнать значение TV у какого-то ресурса надо найти объект modTemplateVarResource, у которого значение contentid соответствует id ресурса, а tmplvarid — id нужного нам TV:
$where = array(
        'contentid' => 16
      , 'tmplvarid' => 4
    );
$tv = $modx->getObject('modTemplateVarResource', $where);
return $tv->get('value');

Мы с вами познакомились со связью между объектами: в данных одного объекта указаны параметры другого (в объекте modTemplateVarResource есть поле, в котором указано значение поля id объекта modResource). И это не просто так. Объекты modResource и modTemplateVarResource связаны друг с другом. О типах связей мы поговорим в другой раз, я сейчас покажу, как можно использовать связи, чтобы упростить наш код.

У объектов xPDO есть методы getOne и getMany
getOne() — метод, который возвращает связанный объект
getMany() — метод, который возвращает несколько связанных объектов
Давайте, попробуем получить TV-параметр используя его связь с документом:
$res = $modx->getObject('modResource', 16);
$tvs = $res->getMany('TemplateVarResources');
foreach ($tvs as $k => $tv) {
    $tvs[$k] = $tv->toArray();
}
print '<pre>';
print_r($tvs);
Этот код выведет нам значения всех TV-параметров указанного документа. Посмотрите внимательно на параметр, который передается в метод getMany(). Это не название класса (мы знаем, что у TV класс modTemplateVarResource). Это псевдоним или, другими словами, алиас связи. Давайте посмотрим, как выглядит для MODX связь между ресурсом и TV-параметрами:
[composites]
    [TemplateVarResources]
        [class] => modTemplateVarResource
        [local] => id
        [foreign] => contentid
        [cardinality] => many
        [owner] => local
composites — в этом массиве перечислены жесткие связи (помимо TV там есть и другие связи). Это означает, что при удалении ресурса удаляются и все связанные объекты.
TemplateVarResources — это тот самый псевдоним связи.
class — это класс связанного объекта. Вот здесь мы видим, что указан класс modTemplateVarResource.
local, foreign — здесь указано, по какому полю связаны объекты. В local указывается, какое поле нашего объекта используется в связи, а в foreign указывается, какое поле в связанном объекте соответствует указанному в local.
cardinality — может быть many или one. Если many, значит связь «Один — ко многим», а если one — «Один — к одному». В данном случае один — ко многим. То есть у каждого ресурса может быть много TV-параметров.
owner — указывает, какой объект в связи главный. То есть, если мы удалим ресурс, TV-параметры тоже удалятся, но если мы удалим TV, то ресурс останется.

MODX смотрит в этот массив связей каждый раз, когда выполняет getOne или getMany. Можно представить это так:
$res = $modx->getObject('modResource', 16);
$tvs = $res->getMany('TemplateVarResources');
    // ищем связь, у которой в алиасе указано TemplateVarResources
    // смотрим сначала class - о, класс modTemplateVarResource
    $class = 'modTemplateVarResource';
    // смотрим, по каким полям связаны объекты
    $local = 'id';
    $foreign = 'contentid';
    // формируем условие выборки - должен получиться такой массив:
    // $where = array('contentid' => $res->get('id'));
    $where = array($foreign => $res->get($local));
    // и возвращаем объекты (используем getCollection, так как
    // вызван метод getMany, а не getOne):
    $output = $modx-getCollection($class, $where);

Как вы поняли, объектов в MODX много и у каждого свои поля, кроме того многие объекты связаны друг с другом. MODX-то знает все эти объекты и связи. А как нам-то узнать, например, правильный алиас связи, который надо передать в метод getOne? Или, например, по каким полям связаны объекты? Или вообще, какие поля у объекта есть? Тут надо либо заучить, либо добавить себе в закладки эту страничку: bobsguides.com/modx-object-full-reference.html

Там вы найдете все объекты MODX, у объектов перечислены все поля, указано, в какой таблице хранятся данные объекта, и перечислены все связи объектов (пункты aggregates и composites).

Например, если посмотрим объект modUser, то увидим, что он связан с объектом modUserProfile и связь там один — к одному ([cardinality] => one), соответственно мы можем получить профиль пользователя без всяких дополнительных условий, так:
$user = $modx->getObject('modUser',1);
// Не забываем, что указывается АЛИАС СВЯЗИ, а не класс
$profile = $user->getOne('Profile');

Ну и напоследок хочу добавить, что у ресурсов (у объектов класса modResource) есть метод getTVValue, который выдает значение связанного TV-параметра:
$res = $modx->getObject('modResource', 16);
$tv = $res->getTVValue(4);
return $tv;

Но он может возвращать значение не только по id TV-параметра, но и по его названию:
$res = $modx->getObject('modResource', 16);
$tv = $res->getTVValue('image');
return $tv;

Да, материал сегодня получился посложнее, чем обычно, так что по этому материалу практическое задание надо обязательно постараться выполнить самостоятельно.

Задание 1. Написать сниппет, который будет выводить на страницу заголовки, аннотации и даты публикации только тех ресурсов, у которых значение TV-параметра «Выводить на главной» равно 1. Или если таких ресурсов больше 10 будет выводить сообщение «Найдено больше 10 ресурсов»
Задание 2. Напишите сниппет, который будет при каждом просмотре страницы увеличивать значение TV-параметра «Просмотры» на 1. А потом напишите второй сниппет, который выведет общее количество просмотров всех страниц, созданных пользователем. Подсказка — текущего пользователя можно получить так:
$user = $modx->user
и в переменной $user у нас будет объект класса modUser с полями текущего пользователя.
P. S. Я жду вопросов от новичков, потому что после такого материала вопросы возникнуть должны. Не бойтесь спрашивать, в этом топике вас даже за глупые вопросы никто не заминусует. Все учимся. По отсутствию вопросов создается впечатление, что никто эти топики не читает и никому это не надо — xPDO все прекрасно и так знают.

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

Оригинал статьи: community.modx-cms.ru/blog/modx-xpdo/10268.html

60 комментариев

  1. Алексндр Наумов 18 апреля 2013, 17:14(Комментарий был изменён) # 0
    Илья, спасибо за серию статей про xPDO, все очень здорово разжевано. Не переживайте, вопросы обязательно будут, просто сначала хочется ознакомится со всеми постами вашего сайта.
    1. Denis Malafey 24 апреля 2013, 22:42(Комментарий был изменён) # 0
      Спасибо большое, Илья! Скажите, а почему многие не советую создавать не создавать TV параметры вообще? Говорили, что они сильно влияют на скорость. Это так? И если так, как без них обойтись вообще? Или как сделать так, чтоб они не влияли на скорость?
      Спасибо.
      1. Илья Уткин 25 апреля 2013, 00:19(Комментарий был изменён) # 0
        Так говорят, потому что каждое значение TV-параметра — это отдельный объект. Если вы показываете на странице 30 ресурсов, то это выборка 30 объектов. Но если у каждого ресурса есть еще по 5 TV-параметров (картинка, дата, теги, количество просмотров, количество лайков), то это уже 150 объектов, соответственно нагрузка в 5 раз больше.

        Если все сниппеты вызываются кешируемыми и изменения на сайте вносятся не очень часто (например, только раз в день), то никакой лишней нагрузки не будет. А для остальных случаев в любом случае придется писать что-то свое.

        Посмотрите на сайт fsknmsk.ru/ — там все сделано стандартно для MODX. У каждой новости могут быть заполнены ТВ-параметры: Картинка, большое изображение для слайдера на главной, галочка — показывать ли на главной, список фотографий для генерации галереи, ссылка на файл видео-записи, ссылка на аудио-запись, список прикрепленных файлов (MIGX). У страниц с обращениями вообще каждый пункт из этой формы — это отдельный TV. Но сайт работает довольно быстро, на обычном аккаунте shared-хостинга и не выдает даже 50% позволенной нагрузки.
        1. Denis Malafey 25 апреля 2013, 00:27(Комментарий был изменён) # 0
          Понял, спасибо!
          1. Denis Malafey 25 апреля 2013, 01:09(Комментарий был изменён) # 0
            Илья, а возможно ли использовать компонент Tickets только для комментариев?
            И как? Будет ли их модерация в админке?
            Все документы уже создал.

            Спасибо.
            1. Илья Уткин 25 апреля 2013, 11:43(Комментарий был изменён) # 0
              Можно. Просто устанавливаете Tickets и в шаблоне вызываете сниппет TicketsComments в том месте, где нужны комментарии. Насчет премодерации — здесь Василий пишет, что в новой версии премодерация есть. Единственное, комментарии могут оставлять только зарегистрированные пользователи.
              1. Denis Malafey 25 апреля 2013, 11:57(Комментарий был изменён) # 0
                Спасибо! Жаль, что только зарегистрированные пользователи могу оставлять. Поставлю решение Валентина, modxTalks.
        2. Виктор Якуша 25 апреля 2013, 03:34(Комментарий был изменён) # 0
          В первую очередь хочу выразить благодарность за Ваш ресурс. А теперь к делу…
          Как практическое задание решил написать такой сниппет:
          У меня есть TV (тип недвижимости, id=2) со значениями Дом||Квартира||…
          Хочу написать сниппет, который выводит все ресурсы у которого этот TV со значением — Дом. Вот код:
          <?php
          $criteria=array('id'=>2,'value'=>'Дом');
          $tvs=$modx->getCollection('modTemplateVarResource',$criteria);
          $output='';
          $output.='Всего найдено '.count($tvs).' записей.
          ';
          foreach ($tvs as $tv) {
              $resource=$tv->getOne('Resource');
              $output.='ID='.$resource->get('id').'. Название='.$resource->get('pagetitle');
          }
          return $output;
          
          Результат:
          Всего найдено 1 записей.
          ID=3. Название=Дом 1 // выводит не все, таких ресурсов 3 — Дом 1, Дом 2, Дом 3.
          Помогите решить.
          Спасибо!
          1. Илья Уткин 25 апреля 2013, 11:37(Комментарий был изменён) # 0
            Заходим сюда и в пункте fields смотрим, что у объекта modTemplateVarResource следующие поля: tmplvarid, contentid и value, а вы в массиве условий выборки указываете id (надо tmplvarid)
            1. Виктор Якуша 25 апреля 2013, 13:59(Комментарий был изменён) # 0
              Илья, спасибо Вам за быстрый ответ. Все получилось.
              P.S. жду новых статей по xPDO о ООП.
          2. Denis Malafey 26 апреля 2013, 21:27(Комментарий был изменён) # 0
            Здравствуйте, Илья.
            Мне нужно сделать похожие документы к ресурсу.
            Создал TV-параметр «same», он должен содержать id похожих ресурсов через запятую.
            Скажите, как вывести информацию о всех документах, id которых содержаться в TV-параметре?

            Пока есть такой код, но он выводит информацию только в том случае, если в значении TV-параметра содержится id только одного похожего документа.
            <?php
            
            $site_url = $modx->getOption('site_url');
            $id = $modx->resource->id;
            
            $res = $modx->getObject('modResource', $id);
            $id_res = $res->getTVValue('same');
            
            $q = $modx->newQuery('modResource');
            $q->where(array('id' => $id_res));
            $q->prepare();
            $q->stmt->execute();
            $recipe = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
            
            foreach($recipe as $res)
            {
                $output .= '<li><a href="'.$site_url.$res['modResource_uri'].'">';
                $output .= '<span>'.$res['modResource_menutitle'].'</span></a></li>';
            }
            return $output;
            Надеюсь, что внятно объяснил.
            Заранее спасибо.
            1. Илья Уткин 26 апреля 2013, 21:36(Комментарий был изменён) # 0
              Можно поменять 10 строчку так:
              $q->where(array('id:IN' => $id_res));
              Но лучше использовать сниппет getResources — будет меньше запросов и нагрузка будет поменьше, да и поддерживать такой код будет легче:
              [[getResources?
               &parents=`-1`
               &resources=`[[*same]]`
               &limit=`0`
               &tpl=`tpl.sameResources`
              ]]
              И чанк tpl.sameResources:
              <li><a href="[[~[[+id]]]]"><span>[[+menutitle]]</span></a></li>
              1. Denis Malafey 26 апреля 2013, 21:42(Комментарий был изменён) # 0
                Спасибо большое!
                Так мы наоборот отказываемся от всех сниппетов.
                Говорят, что getResources глючный и лучше писать свои сниппеты.
                А в связке с TV пишут, что getResources — это смерть, так как делает какие-то подзапросы, и производительность теряется в разы.
                Мы уже весь Wayfinder заменили своими сниппетами.
                Хотим сэкономить ресурсы и выиграть в скорости. Уже выиграли 0,3 сек.
                А вот без TV как вообще обойтись…
                1. Илья Уткин 26 апреля 2013, 22:13(Комментарий был изменён) # 0
                  Ой-ой-ой… Кто вам так голову заморочил? Wayfinder и getResources написали сами авторы MODX наиболее оптимальным образом. А чтобы выиграть в скорости, кешируйте все, что можно — целыми блоками.

                  И по вашему коду есть еще комментарий.
                  $id = $modx->resource->id;
                  
                  $res = $modx->getObject('modResource', $id);
                  $id_res = $res->getTVValue('same');
                  $modx->resource это уже объект (текущий ресурс) и можно было написать так:
                  $id_res = $modx->resource->getTVValue('same');
                  И кроме того, при использовании getResources будет всего один запрос (мы же не указываем &includeTVs=`1`).
                  1. Denis Malafey 26 апреля 2013, 23:07(Комментарий был изменён) # 0
                    Кешировать не получается ничего. Мультиязычность, Babel.
                    Я пробовал ваш метод, спасибо вам за него. Но, когда у меня всё кешируется — то не переводится :)
                    Я пробовал и решение Валентина
                    modx.im/blog/research/643.html
                    modx.im/blog/addons/663.html

                    Это просто супер, но не для меня. Мультиязычность.
                    Плюс ко всему стоит LikeDislike, HitsPage, modxTalks. То есть, некоторые блоки нельзя кешировать.

                    Я общался с пользователем Vanchelo (Ваня Брежнев, очень хороший паренёк) и читал мнения F1losofa по поводу getResources.
                    Они говорят, что нужно писать свои сниппеты.
                    Поверьте, это никак не моё мнение. Просто читаю, слушаю бывалых. Вас, конечно же, тоже слушаю.

                    Я поставил Wayfinder, getResources, и т.п. Скорость загрузки страницы отвратная. Бывает и 7 секунд простреливает. Всё кеширую, что можно. Уже напрягает. Отказался от Wayfinder — увидел, что реально выиграл в скорости. Надо пробовать.
                    А вот Сайт Вани (Vanchelo).
                    Посмотрите, летает же. А у него только свои сниппеты.
                    Или Thai, его тоже Ваня делал. Свои сниппеты. Вот это — класс.
                    Вот к таким сайтам, я считаю нужно стремится.

                    Ведь, посудите, в тех Wayfinder и getResources для простых сайтов дофига лишней фигни, которая просто не нужна. НАпример, для меню мне просто нужно вывести 5 пунктов ссылками. Всё. А там и параметры для исключения и кучу всего.
                    1. Илья Уткин 27 апреля 2013, 01:39(Комментарий был изменён) # 0
                      Для мультиязычности кеширование тоже можно применять. Надо добавить только язык к ключу файла кеша. Переделанный сниппет chunk для мультиязычности будет выглядеть так:
                      $cache_key = "chunk_".$name."_".$lang;
                      
                      $output = $modx->cacheManager->get($cache_key);
                      
                      if (empty($output)) {
                        $output = $modx->getChunk($name, $scriptProperties);
                        $modx->cacheManager->set($cache_key,$output);
                      }
                      
                      return $output;
                      (только сниппет вызывайте некешированным, чтобы $lang менялся) и тогда для каждого языка будет свой кеш. Если на сайте много блоков с одинаковой информацией на нескольких страницах, то выигрыш будет значительным. fsknmsk.ru/ тоже летает, но на нем нет нестандартных сниппетов — просто большой сайт-визитка.

                      Если вы заметили разницу в загрузке страниц после перехода на самописные сниппеты, тогда да, используйте их.

                      LikeDislike, HitsPage и ModxTalks ненагруженные сниппеты, они и разрабатывались, чтобы вызываться некешированными. Попробуйте те блоки, которые одинаковыы для всех страниц кешировать с добавлением языка к ключу и отпишитесь, поможет или нет)
                      1. Denis Malafey 27 апреля 2013, 03:08(Комментарий был изменён) # 0
                        Конечно, отпишу! Спасибо вам, Илья!
                        Ещё хотел узнать, а если свои сниппеты + ваш метод кеширования блоков, то вообще летать будет?
                        1. Denis Malafey 27 апреля 2013, 04:09(Комментарий был изменён) # 0
                          Не работает ваша модификация сниппета под мультиязычность.
                          Попробовал — всё как и было, не переключаются между языками. Только русский.
                          Пробовал и некешированным вызывать, и кешированным.
                          1. Илья Уткин 27 апреля 2013, 16:57(Комментарий был изменён) # 0
                            Блин, ну конечно. Я же не знаю, как у вас мультиязычность организована. Вы должны сами передать язык в переменную $lang
              2. Виктор Якуша 01 мая 2013, 04:53(Комментарий был изменён) # 0
                Здравствуйте, Илья.
                Подскажите, где ошибка…
                $criteria=array('tmplvarid'=>6);
                $tvs = $modx->getCollection('modTemplateVarResource',$criteria);
                $name_tv = $tvs->getOne('TemplateVar');
                $name = $name_tv->get('description');
                return $name;
                
                1. Илья Уткин 06 мая 2013, 16:50(Комментарий был изменён) # 0
                  Прошу прощения, что долго не отвечал — был далеко от компьютера на выходных)

                  Давайте посмотрим на вторую и третью строчки. Вы используете метод getCollection, который возвращает массив, соответственно к этому массиву нельзя применить метод getOne — он применяется только к объекту. Давайте попробуем пройтись по массиву и применить этот метод к первому попавшемуся объекту (написать $tvs[0] мы не можем, так как в массиве id элемента будет таким же, как и его id в базе данных):
                  $criteria=array('tmplvarid'=>6);
                  $tvs = $modx->getCollection('modTemplateVarResource',$criteria);
                  foreach ($tvs as $tv) {
                    $name_tv = $tv->getOne('TemplateVar');
                    $name = $name_tv->get('description');
                    if ($name) break;
                  }
                  return $name;
                  Получилось. Давайте смотреть дальше — зачем вы берете метод getCollection, если нужен только один объект — это только лишняя нагрузка? Поменяем getCollection на getObject:
                  $criteria=array('tmplvarid'=>6);
                  $tv = $modx->getObject('modTemplateVarResource',$criteria);
                  $name_tv = $tv->getOne('TemplateVar');
                  $name = $name_tv->get('description');
                  return $name;
                  Так, а зачем мы вообще идем от объекта modTemplateVarResource? А если наш ТВ еще не заполнен ни у одного ресурса — тогда мы не узнаем ничего об этом ТВ. Давайте работать сразу с объектом modTemplateVar:
                  $criteria=array('id'=>6);
                  $tv = $modx->getObject('modTemplateVar',$criteria);
                  $name = $tv->get('description');
                  return $name;
                  А так как мы производим поиск по id, то можно записать еще проще:
                  $tv = $modx->getObject('modTemplateVar',6);
                  return $tv->get('description');
                  1. Виктор Якуша 02 июня 2013, 19:57(Комментарий был изменён) # 0
                    Добрый день, Илья.
                    Спасибо Вам, за статьи и ответы.

                    Скажите, когда будут новые материалы, очень жду. newQuery(), select()…
                    1. Илья Уткин 14 июня 2013, 11:09(Комментарий был изменён) # 0
                      Про newQuery() и select() много материала как у bezumkin'а, так и у Fi1osof'а. У меня уроки для начинающих. Изучив их можно легко понять статьи по ссылкам. Думаю, я продолжу про xPDO, но нужно подыскать тему, которая еще не освещена в интернете.
                2. Владимир Гришин 01 июня 2013, 16:49(Комментарий был изменён) # 0
                  Илья привет. подскажи если я получаю значение тв через getObject('modTemplateVarResource', $where)
                  и результат является в таком виде: «name1:10;name2:11;name3:12»
                  как мне отсюда вытащить значение name1 равное 10?
                  1. Илья Уткин 14 июня 2013, 11:03(Комментарий был изменён) # +1
                    Сорри, что долго не отвечал. Я бы разбил строку на элементы массива и работал с ним:
                    $result = explode(";", "name1:10;name2:11;name3:12");
                    foreach ($result as $key => $val) {
                      $item = explode(":", $val);
                      $result[$item[0]] = $item[1];
                      unset($result[$key]);
                    }
                    В результате должен получиться такой массив $result:
                    array(
                        'name1' => '10'
                      , 'name2' => '11'
                      , 'name3' => '12'
                    )
                  2. Evgeny Epifanov 23 декабря 2013, 15:20(Комментарий был изменён) # 0
                    Илья, подскажите, пожалуйста, как можно высчитать md5 файла (tv-image)?
                    Если сделать так так:
                    $res = $modx->getObject('modResource', 309);
                    $tv = $res->getTVValue('image');
                    $md5 = md5($tv);
                    return $md5;
                    выводится md5 пути, а нужно именно файла.
                    1. Илья Уткин 23 декабря 2013, 15:23(Комментарий был изменён) # 0
                      Вам нужно использовать другую функцию.
                      1. Evgeny Epifanov 23 декабря 2013, 17:03(Комментарий был изменён) # 0
                        Спасибо большое!
                        $res = $modx->getObject('modResource', 309);
                        $tv = $modx->getOption('site_url').$res->getTVValue('image');
                        $md5 = md5_file($tv);
                        return $md5;
                        Отлично считает!
                        Только в «Console» кучу ошибок пишет:
                        Could not load class xpdofilecache from xpdofilecache
                        и
                        Language string not found:
                        Подозреваю, что это из-за настроек кэширования, так ли это?
                        1. Илья Уткин 23 декабря 2013, 17:09(Комментарий был изменён) # 0
                          Вот этого не знаю… Не сталкивался еще с таким… Если ошибки не пропадут попробуйте построчно останавливать скрипт и понять, на какой строке ошибка — может, вообще не этот скрипт ее генерирует.
                    2. Олег 09 июня 2014, 08:59 # 0
                      Илья, добрый день!
                      <?php
                      $criteria=array('tmplvarid'=>2,'value'=>'Дом');
                      $tvs=$modx->getCollection('modTemplateVarResource',$criteria);
                      $output='';
                      $output.='Всего найдено '.count($tvs).' записей.
                      ';
                      foreach ($tvs as $tv) {
                      $resource=$tv->getOne('Resource');
                      $output.='ID='.$resource->get('id').'. Название='.$resource->get('pagetitle');
                      }
                      return $output;

                      Приведенный выше код работает отлично в связке в GetRecources, но только по одному параметру TV, а как сделать выборку по двум и более параметрам? (чтобы между значениями Tv параметров стояло не ||, а AND )?
                      Заранее спасибо за помощь!
                      1. Илья Уткин 09 июня 2014, 09:28 # 0
                        Вам надо, чтобы скрипт нашел ресурсы, у которых и ТВ «house», и ТВ «home» равны строке 'Дом'? Я просто не совсем понимаю, что нужно-то?
                      2. Олег 09 июня 2014, 10:12 # 0
                        Добрый день еще раз!
                        Скажем у меня есть еще один tv ресурс с
                        'tmplvarid'=>5,'value'=>'здесь значение из формы'.
                        Мне нужно, чтобы у меня выдавало ресурсы, когда первый параметр = Дом и второй параметр = значению из формы. Вот как-то так. Надеюсь, смог объяснить. У меня идет выборка из формы вот такого вида:
                         <div class="checkbox-label">Страна</div>
                                                            <select name="country" class="country">
                                                                <option value="Испания" selected>Испания</option>
                                                                <option value='Италия'>Италия</option>
                                                                <option value='Чехия'>Чехия</option>
                                                                <option value='Польша'>Польша</option>
                                                                <option value='Россия'>Россия</option>
                                                                <option value='Китай'>Китай</option>
                                                            </select>
                        
                        Код, который обрабатывает, этот выбор, вот такой:
                        <?php
                        $criteria = array('tmplvarid'=>5,'value'=>$_POST['country']);
                        $templatepost = '{"template:=":3}';
                        $parent='13,21,27,50,51,64,14,52,53,54,15,55,56,16,17,57,58,59,60,61,62,63';
                        $criteriapost=array(
                            'elementClass' => 'modSnippet',
                            'element'      => 'getResources',
                            'showHidden'   =>'1',
                            'parents'      =>$parent,
                            'includeTVs'   => '1',
                            'processTVs'   => '1',
                            'limit'        => '100',
                            'tvPrefix'     =>  'tv.',
                            'tpl'          => 'LisRowTpl.poisk',
                            'tvFilters'    => '$criteria',
                            'where'        => '{"template:=":3}' 
                        );
                        
                            
                            $res=$modx->runSnippet('getResources', $criteriapost);
                            echo $res;
                        
                        Я не могу сообразить, как добавить второй параметр в массив, так чтобы шла проверка по обеим параметрам и если в случае успеха и в первом случае и во втором, то выводится объект.
                        1. Илья Уткин 09 июня 2014, 10:22 # 0
                          Здесь, в общем-то, работы с xPDO нет — вы просто задаете параметр tvFilters для getResources. Значит, надо смотреть в документацию: rtfm.modx.com/extras/revo/getresources
                          $criteria = 'hometv==Дом,country=='.$_POST['country'];
                        2. Олег 09 июня 2014, 11:16 # 0
                          Огромное спасибо за подсказку, Илья! Вы мне минимум день моей жизни сэкономили, я копал в другую сторону. )))
                          1. Андрей Иванов 08 июля 2014, 08:27 # 0
                            Илья, доброго времени суток.

                            А каким образом, например, сюда:

                            $where = array(
                                    'contentid' => 16
                                  , 'tmplvarid' => 4
                                );
                            можно передать условие AND? Ну, допустим, сравнить два параметра? Как передать «больше», «меньше» и т д?
                            1. Илья Уткин 08 июля 2014, 12:31 # 0
                              Здесь как раз и передано условие AND:
                              `contentid` = 16 AND `tmplvarid` = 4
                              Добавить условие OR можно так:
                              $where = array(
                                      'contentid' => 16
                                    , 'OR:tmplvarid' => 4
                                  );
                              Больше/меньше, LIKE:
                              $where = array(
                                      'contentid:>' => 16
                                    , 'tmplvarid:LIKE' => '%'.4.'%'
                                  );
                              Вот подсказочка: http://rtfm.modx.com/xpdo/2.x/class-reference/xpdoquery/xpdoquery.where
                              1. Андрей Иванов 09 июля 2014, 07:15 # 0
                                Илья, большое спасибо!
                            2. Мустафа 16 августа 2014, 15:31 # 0
                              Стоит задача добавить и(или) редактировать нахождение ресурса в группах.
                              Прошу подсказать реализацию.
                              1. Мустафа 16 августа 2014, 17:53(Комментарий был изменён) # 0
                                Благодарю, нашел решение покопавшись в манах. Может кому пригодится, примеры:
                                // Изменение группы ресурсов 
                                $docId='4';
                                $newGroup='2';
                                $resource = $modx->getObject('modResource', $docId);
                                $resGroups = $resource->getOne('ResourceGroupResources');
                                $resGroups->set('document_group', $newGroup);
                                $resGroups->save();
                                
                                //Получение списка групп ресурса
                                $docId='4';
                                $resource = $modx->getObject('modResource', $docId);
                                $resGroups = $resource->getMany('ResourceGroupResources');
                                $groups = array();
                                foreach ($resGroups as $group) {
                                  $groupObj = $group->getOne('ResourceGroup');
                                  $groups[] = $groupObj->get('name');
                                }
                                
                                //Добавление новой группы ресурсов
                                $group = $this->modx->newObject('modResourceGroup');
                                $groupdata = array('name'=>'NEW_GROUP_NAME','private_memgroup'=>0,'private_webgroup'=>0);
                                $group->fromArray($groupdata);
                                $group->save();
                                1. Evgeny Epifanov 09 февраля 2015, 20:56 # 0
                                  Илья, появилась такая задача:
                                  Найти все TV ресурса, которые находятся в определенной категории (сами TV находятся в категории, не ресурсы), а потом вывести их названия и значения (можно еще и порядок сортировки). В таблице все это есть (поля: category, caption, rank), а вот как все это вывести не знаю.
                                  Подскажи, пожалуйста.
                                  1. Илья Уткин 10 февраля 2015, 09:11 # 0
                                    $tvars = $modx->getCollection('modTemplateVar', array('category' => 14));
                                    $ids = array();
                                    foreach($tvars as $tvar) {
                                      $ids[] = $tvar->id;
                                    }
                                    $tvs = $modx->getCollection('modTemplateVarResource', array(
                                        'contentid' => $modx->resource->id,
                                        'tmplvarid:IN' => $ids
                                    ));
                                    foreach ($tvs as $k => $tv) {
                                        $tvs[$k] = $tv->toArray();
                                        $tvs[$k]['caption'] = $tvars[$tv['tmplvarid']]['caption'];
                                        $tvs[$k]['name'] = $tvars[$tv['tmplvarid']]['name'];
                                    }
                                    print_r($tvs);
                                    Но код не тестировал. Проверьте…
                                    1. Evgeny Epifanov 10 февраля 2015, 18:22 # 0
                                      Спасибо за ответ, Илья.
                                      Код к сожалению не работает. Выводит просто «Array ( )»
                                  2. MODX 14 сентября 2015, 11:55 # 0
                                    Такой вопрос:
                                    В сниппете А вызываю снипет Welcome и передаю ему параметры:

                                    $output = $modx->runSnippet('Welcome',array(
                                    'name' => 'John'
                                    ));

                                    Как в сниппете А принять параметр 'name' в переменную?
                                    1. Илья Уткин 14 сентября 2015, 11:57 # 0
                                      Этот параметр уже в переменной $name
                                      1. MODX 01 октября 2015, 07:56 # 0
                                        Благодарю, очень выручил.
                                    2. D.Zanzo 07 октября 2015, 21:10 # 0
                                      В описании getMany() опечатка:
                                      метод, который возвращает несколько связанных объектовДавайте, попробуем получить TV-параметр используя его связь с документом:
                                      1. Илья Уткин 08 октября 2015, 10:30 # 0
                                        Cпасибо, поправил
                                      2. Леви Ким 23 ноября 2015, 08:52 # 0
                                        подскажите, на сколько я читал, ТВ параметры очень сильно тормозят вывод всего документа?.. За счет чего это происходит? ведь это по сути дела всего один дополнительный запрос к базе.
                                        1. Илья Уткин 23 ноября 2015, 09:04 # 0
                                          Так они и не тормозят — именно потому что это всего один дополнительный запрос к базе.

                                          Раньше, когда все пользовались сниппетом getResources, проблема была — при большом количестве ТВ-шек вывод сильно подтормаживал. А теперь есть pdoResources — он выбирает все ТВ-параметры ресурса за один запрос.

                                          Конечно, 20-30 ТВ-параметров могут повлиять и на скорость pdoResources, но если настроить кеширование, то тормозить будет только первый раз.
                                          1. Леви Ким 02 декабря 2015, 15:44 # 0
                                            Скажи тогда пожалуйста, отчего же тогда я постояннь натыкаюсь вот на такие посты? с тв работает все долго, без тв — быстро
                                            modx.pro/solutions/7198-simplify-work-with-tv/#comment-50483
                                            1. Илья Уткин 02 декабря 2015, 17:32 # 0
                                              К каждому проекту свой подход. )

                                              Эта статья мне тоже очень понравилась. Решает не только вопрос скорости, но и другой минус ТВ-шек — то, что значения по умолчанию в базу данных не вносятся. В этом случае очень сложно сортировать и фильтровать по ТВ.
                                        2. Руслан 24 декабря 2015, 10:42 # 0
                                          Здравствуйте!
                                          В общем совсем я уже устал искать ответ на свой вопрос. Нигде нет описания как правильно через pdoResources вызывать тв поле с url
                                          Вот как вызываю я
                                          [[pdoResources? &parents=`5` &includeTVs=`newurl` &tpl=`new`]]
                                          Тв поле «newurl» с параметром ввода url и с параметром вывода url (ставил и параметр вывода -текст)
                                          В чанке «new» вызываю это поле так
                                          <a href="[­[+tv.newurl]]">ссылка</a>
                                          В результате имею вместо сторонней ссылки на внешний сайт ссылку вида
                                          мойсайт.ру/[­[+tv.newurl]]
                                          Илья, что я делаю не так?
                                          1. Илья Уткин 24 декабря 2015, 10:46 # 0
                                            По-моему, в pdoTools у ТВ по умолчанию нет префикса. Попробуйте так
                                            <a href="[­[+newurl]]">ссылка</a>
                                            1. Руслан 24 декабря 2015, 10:51 # 0
                                              Илья, спасибо за оперативность! Но так результат тот же.
                                              1. Руслан 24 декабря 2015, 19:08 # 0
                                                Всё разобрался. Опечатка где-то была.
                                            2. Сергей Карпук 02 января 2016, 11:23 # 0
                                              День добрый всем! Илья, огромное спасибо за данную серию статей!
                                              Вот решился несколько строк кода написать, вероятно, очень корявых. Надеюсь, дальше пойдёт веселее.
                                              Задание 1:
                                              $where = array ('tmplvarid' => 2);
                                              $tvs = $modx->getCollection('modTemplateVarResource',$where);
                                              
                                              foreach ($tvs as $k => $tv) {
                                                  $tvs[$k] = $tv->toArray();
                                                  if ($tvs[$k][value] == 1) {
                                                      $cont = $cont + 1;
                                                      $id = $tvs[$k][contentid];
                                                      $res = $modx->getObject('modResource',$id);
                                                      $output .= '<p><b>' .$res->get('pagetitle'). '.</b> ' .$res->get('introtext'). ' (' .$res->get('publishedon'). ')</p>';
                                                  }
                                              }
                                              
                                              if ($cont <= 10) {
                                                  return $output;    
                                              } else {
                                                  echo 'Найдено больше 10 документов';
                                              }
                                              1. Сергей Карпук 02 января 2016, 11:25(Комментарий был изменён) # 0
                                                Тоже задание, но уже с использованием метода getTVValue:
                                                $resource = $modx->getCollection('modResource');
                                                foreach ($resource as $k => $res) {
                                                    if (($res->getTVValue(2)) == 1) {
                                                        $cont = $cont + 1;
                                                        $output .= '<p><b>' .$res->get('pagetitle'). '.</b> ' .$res->get('introtext'). ' (' .$res->get('publishedon'). ')</p>';
                                                    }    
                                                }
                                                if ($cont <= 10) {
                                                    return $output;    
                                                } else {
                                                    echo 'Найдено больше 10 документов';
                                                }
                                                Буду очень благодарен за любые советы.
                                                1. Илья Уткин 09 января 2016, 14:25 # 0
                                                  Так вот же, комментарии как раз по первой задаче) ilyaut.ru/xpdo/xpdo-for-dummies-part-4-the-practice-of/
                                                  1. Сергей Карпук 09 января 2016, 14:34 # 0
                                                    Да, комментарии тоже прочитал. Но сначала пробовал решить самостоятельно.
                                              2. Станислав Однолетко 15 июля 2017, 02:39(Комментарий был изменён) # 0
                                                Чревато перегревом
                                                1 первое задание

                                                $i=0;
                                                $resources = $modx->getCollection('modResource',array( 'parent'=>'2'));
                                                $getTable = $modx->getCollection('modResource',array( 'parent'=>'2'));
                                                foreach($getTable as $key=>$gTab){
                                                    $val=$gTab->getTVValue('textTV');
                                                    if(!(empty($val))){
                                                         $i++;
                                                    }
                                                }
                                                    if($i>5){
                                                        echo "$i больше 5";
                                                    }else{
                                                        foreach($resources as $key=>$r){
                                                            $tv=$r->getTVValue('textTV');
                                                            if(!(empty($tv))){
                                                                print '<pre>';
                                                                 echo "id=".''.$r->get('id').' '.$r->get('pagetitle').' '.$r->get('introtext').' '.'Дата публикации:'.$r->get('publishedon').' '.'<b>Значение TV поля =</b>'.' '.$tv.'
                                                ';
                                                         }
                                                        } 
                                                    }

                                                Авторизация

                                                через сервис Loginza:

                                                Подписка или RSS

                                                Буду присылать новые статьи — никакого спама



                                                Шаблоны MODX

                                                1 2 Дальше »

                                                Объектная
                                                модель
                                                MODX