Сниппет для Выборки ресурсов по МIGX значению Новый

Дополнение: MIGX pdoTools

Добрый вечер, у меня есть ресурсы с TV (MIGX) в котором используются checkbox и radio. Задача состоит в том что мне нужно выводить ресурсы в зависимости от значений этих checkbox и radio.


Например мне нужно вывести все игры у которых в Жанре выбран "Экшен", а еще лучше если будет возможность сделать выборку по 2 критериям (Например, что бы были ресурсы у которых есть жанр Экшен и Гонки, либо Жанр => Экшен и Способ активации => Steam), но даже если я смогу фильтровать по 1 критерию тоже буду очень рад.

А теперь перейду к тому с чего началась загвоздка.
Я изначально думал что всё легко и просто возьму сниппет pdoResources подключу к нему TV через &includeTVs и воспользуюсь &tvFilters. Но т.к TV сделано через MIGX то оно хранится в базе как JSON и хотя сниппет его преобразует в массив мне не воспользоваться параметром &tvFilters и с помощью &where тоже не как т.к в базе хранится JSON.
Например то что лежит в базе
[{"MIGX_id":"1","image":"http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/271590\/header.jpg?t=1459273772","alt_image":"GTAV","title_image":"GTAV","video":"1","janre":["\u042d\u043a\u0448\u0435\u043d ","\u0421\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b ","\u0424\u0430\u0439\u0442\u0438\u043d\u0433\u0438 ","\u0414\u0438\u0437\u0430\u0439\u043d "],"activation":"Origin","platform":"Windows ","region":"\u0412\u0435\u0441\u044c \u043c\u0438\u0440 ","rejim":"\u041c\u0443\u043b\u044c\u0442\u0438\u043f\u043b\u0435\u0435\u0440 ","news":"1"}]
В виде массива:
[tovar_info] => Array
                (
                    [0] => Array
                        (
                            [MIGX_id] => 1
                            [image] => http://cdn.akamai.steamstatic.com/steam/apps/271590/header.jpg?t=1459273772
                            [alt_image] => GTAV
                            [title_image] => GTAV
                            [video] => 1
                            [janre] => Array
                                (
                                    [0] => Экшен 
                                    [1] => Симуляторы 
                                    [2] => Файтинги 
                                    [3] => Дизайн 
                                )

                            [activation] => Origin
                            [platform] => Windows 
                            [region] => Весь мир 
                            [rejim] => Мультиплеер 
                            [news] => 1
                        )

                )
А теперь самое сложно для меня
Т.к я не могу воспользоваться уже готовыми сниппетами и наверно все же не умею создавать правильные запросы в &where и &tvFilters решил что пора написать свой сниппет (Чем сложнее тем лучше, учесть что PHP я только поверхностно знаю, а начинку MODX я вообще не знаю).

Так вот в моей голове с начало крутилась мысль, что нужно использовать функционал pdoResources и добавить в него свой фильтр (Для меня это функция которая принимает значения (массив в данном случае) и еще одна переменная это ключ который мы будет искать в этом массиве. Ну это наверно не совсем правильно, на вход все же нужно 3 значения например:
function migxFilter($array, $key, $val){
	
}
Где $array массив полученный из MIGX преобразованный уже MODX как нибудь так:
$val = $resource->getTVValue(2);
$val = $modx->fromJSON($val);
$key — должен быть КЛЮЧОМ что бы не получить лишнее и искать именно в определенном месте( в данном случае в категория например Жанр что в массиве [janre]).
Ну и конечно $val само значение по которому мы будем фильтровать (Например «Экшен»).
Ладно пробежались по массиву нашли совпадение… Получается на выход нам достаточно получить boolean (true || false). То есть у нас есть полученный ресурс, а вернее наверно лучше ресурсы с этим TV.
Например:
$pdo = $modx->getService('pdoFetch');
$parameters = array(
	'showUnpublished' => 1,
	'parents' => 2,
	'templates' => 4,
	'includeTVs' => 'Нужные TV',
);
$res = $pdo->getCollection('modResource', null, $parameters);
В переменной $res будет храниться Многомерный массив:

Array
(
    [0] => Array
        (
            [id] => 3
            [type] => document
            [contentType] => text/html
            [pagetitle] => Grand Theft Auto V
            [longtitle] => Купить игру GTA 5 / ГТА 5 / Grand Theft Auto V для STEAM
            [description] => 
            [alias] => grand-theft-auto-v
            [link_attributes] => 
            [published] => 1
            [pub_date] => 0
            [unpub_date] => 0
            [parent] => 4
            [isfolder] => 0
            [introtext] => 
            [content] => 
            [richtext] => 1
            [template] => 4
            [menuindex] => 0
            [searchable] => 1
            [cacheable] => 1
            [createdby] => 1
            [createdon] => 1468714413
            [editedby] => 1
            [editedon] => 1470168281
            [deleted] => 0
            [deletedon] => 0
            [deletedby] => 0
            [publishedon] => 1468714380
            [publishedby] => 1
            [menutitle] => 
            [donthit] => 0
            [privateweb] => 0
            [privatemgr] => 0
            [content_dispo] => 0
            [hidemenu] => 1
            [class_key] => modDocument
            [context_key] => web
            [content_type] => 1
            [uri] => grand-theft-auto-v.html
            [uri_override] => 0
            [hide_children_in_tree] => 0
            [show_in_tree] => 1
            [properties] => Array
                (
                    [autoredirector] => Array
                        (
                            [old_uri] => grand-theft-auto-v.html
                        )

                )

            [tovar_info] => Array
                (
                    [0] => Array
                        (
                            [MIGX_id] => 1
                            [image] => http://cdn.akamai.steamstatic.com/steam/apps/271590/header.jpg?t=1459273772
                            [alt_image] => GTAV
                            [title_image] => GTAV
                            [video] => 1
                            [janre] => Array
                                (
                                    [0] => Экшен 
                                    [1] => Симуляторы 
                                    [2] => Файтинги 
                                    [3] => Дизайн 
                                )

                            [activation] => Origin
                            [platform] => Windows 
                            [region] => Весь мир 
                            [rejim] => Мультиплеер 
                            [news] => 1
                        )

                )
        )

    [1] => Array
        (
            [id] => 6
            [type] => document
            [contentType] => text/html
            [pagetitle] => Far Cry Primal
            [longtitle] => Far Cry Primal
            [description] => 
            [alias] => far-cry-primal
            [link_attributes] => 
            [published] => 1
            [pub_date] => 0
            [unpub_date] => 0
            [parent] => 4
            [isfolder] => 0
            [introtext] => 
            [content] => 
            [richtext] => 1
            [template] => 4
            [menuindex] => 0
            [searchable] => 1
            [cacheable] => 1
            [createdby] => 1
            [createdon] => 1469990988
            [editedby] => 1
            [editedon] => 1470357649
            [deleted] => 0
            [deletedon] => 0
            [deletedby] => 0
            [publishedon] => 1468714380
            [publishedby] => 1
            [menutitle] => 
            [donthit] => 0
            [privateweb] => 0
            [privatemgr] => 0
            [content_dispo] => 0
            [hidemenu] => 1
            [class_key] => modDocument
            [context_key] => web
            [content_type] => 1
            [uri] => far-cry-primal.html
            [uri_override] => 0
            [hide_children_in_tree] => 0
            [show_in_tree] => 1
            [properties] => Array
                (
                    [autoredirector] => Array
                        (
                            [old_uri] => far-cry-primal.html
                        )

                )

            [tovar_info] => Array
                (
                    [0] => Array
                        (
                            [MIGX_id] => 1
                            [image] => http://cdn.akamai.steamstatic.com/steam/apps/371660/header.jpg?t=1460460176
                            [alt_image] => Far Cry Primal
                            [title_image] => Far Cry Primal
                            [video] => 1
                            [janre] => Array
                                (
                                    [0] => Ролевые 
                                    [1] => Казуальные 
                                )

                            [activation] => Steam
                            [platform] => Array
                                (
                                    [0] => Windows 
                                    [1] => Linux 
                                    [2] => Mac
                                )

                            [region] => Весь мир 
                            [rejim] => Array
                                (
                                    [0] => Мультиплеер 
                                    [1] => Кооператив 
                                )

                            [news] => Array
                                (
                                    [0] => Предзаказ 
                                    [1] => Скидки 
                                )

                        )

                )
        )

)
В этих ресурсах мы должны получить наш массив из TV (tovar_info) применить к нему наш фильтр (который увы я сам не смог написать, вернее смог сделать функцию которая пробегается по массиву и ищет нужное значение, а на выход даёт либо true либо false)
function janr($array, $string){
      if(!is_array($array)){
        return false;  
      }
      static $da = false;
      foreach($array as $k=>$v){
          if(is_array($v)){
            janr($v, $string);  
          }else{
            if(trim($v) === $string){
              $da = true;
            }  
          }
          
      }
      return $da;
  }
И здесь мои знания полностью иссякли т.к я не знаю как мне отфильтровать или этот фильтр добавить в pdoResources. Если подумать можно пробежаться foreach по самим ресурсам дать ресурсу ключ TV что бы получить значения этого TV и если совпадение есть то вывести уже на экран этот ресурс используя Чанк.
foreach($res as $tovar){
    $array = $tovar[tovar_info];
    if(janr($array,"Ролевые")){
     $pdo->getChunk(Чанк, $res)  //Вывoдим Чанк этого ресурса
    }  
}
Но теперь у меня возникла проблема как мне в чанке вывести плейсхолдеры. Неужели придется писать там [[+tovar_info.0.rejim.0]]
Вообщем время уже поездное 4:39, выразить свои мысли не могу, да и наверно не умею. Поэтому попрошу Вас добрых людей, помогите пожалуйста с такими вопросами?
  1. Как грамотно написать сниппет? Что бы был похоже на pdoResources но с возможностью добавить свой фильтр в виде функции
  2. Как доработать фильтр который принимал бы 3 переменные? (Если конечно это не сложно и Вас не затрудни написать)
  3. Как сделать потом нормальные плейсхолдеры? Напрмер [[+tovar_info.janre]] или просто [[+janre]]
  4. И что нужно изучить, что бы можно было самому писать Плагины снипеты и дорабатывать сам движок MODX под свои нужды? И есть ли люди которые могу поучить? либо указать верное направления для достижения целей как в программирование так и в самом MODX. Сам парень я не ленивый, но самообучение даётся не легко, знаю что если кто то помогает то в разы быстрее научиться можно
06 августа 2016, 04:41    Дмитрий   
1    713 0

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

  1. vmpr_7 07 августа 2016, 13:12 # +1
    На своем проекте я делал так:
    &where=`{"active:=":"1","category:find":"New"}`
    т.е. у меня есть категория, в которой несколько значений (тоже чекбоксы) и он выбирает только те, которые отмечены «New».
    При этом я использовал pdoPage, т.к. нужна была ajax подгрузка элементов из MIGX.
    [[!pdoPage?
    	&element=`getImageList`
    	...
    	...
    	&where=`{"active:=":"1","category:find":"New"}`
    
    Думаю, Вы и со своей выборкой справитесь.
    1. Дмитрий 07 августа 2016, 16:48 # 0
      Извиняюсь за вопрос но у меня не получается сделать выборку. И я предполагаю что &where обращается именно в БД а там у меня лежит JSON строка т.к я использовал MIGX.
      Ладно пропущу выборку а как вы добились того что бы выводились все ресурсы с pdoPage если мы подключаем element=`getImageList` то выборки будет показан только 1 товар, до других он не доберётся.
      1. vmpr_7 07 августа 2016, 17:34 # 0
        мы подключаем getImageList, в параметр tvname пишем имя TV migx
        &tvname=`здесь имя TV migx`
        и в параметр tpl указываем шаблон
        &tpl=`здесь имя чанка`
        тем самым сниппет выведет все значения tv migx, которые будут с определенным шаблоном, который вы прописали в чанке tpl.
        А вообще скиньте код посмотреть, как Вы пытаетесь вывести.
        1. Дмитрий 07 августа 2016, 18:12 # 0
          [[!pdoPage?
                                                  &element=`getImageList`
                                                  &tvname=`tovar_info`
                                                  &tpl=`block-tovar__tovar--tpl`
                                              ]]
          Выводится только 1 товар
          А так то у меня сейчас 2 ресурса с этим.




          Если не сложно то я мог бы дать доступ от Админки что бы могли там посмотреть. Ну и в скайпе смогли бы обьяснить. Если конечно вас это не затруднит.
          1. Дмитрий Середюк 07 августа 2016, 19:03 # 0
            возможно вам необходимо дописать в вызове
            &parents=`[[*id]]`
            &where=`{"template:=":id шаблона игрушки}`
            
            так же у сниппета getImageList есть параметр &docid=`[[*id]]`// с ним так же нужно поиграть.
            1. Дмитрий 07 августа 2016, 19:22 # 0
              Тоже пытался так сделать но нечего не получается. У сниппета getImageList нет &parents и у pdoPage тоже нет. И как раз тут загвоздка с &docid т.к в pdoPage не может передавать id обрабатываемого ресурса. Поэтому не вывести.
              1. Дмитрий Середюк 07 августа 2016, 19:32 # 0
                getImageList я так подозреваю необходимо вызывать в чанке то есть к примеру общий вызов выглядит примерно так:

                [[!pdoPage?
                &parents=`[[*id]]`
                &tpl=`block-tovar__tovar--tpl`
                &where=`{"template:=":id шаблона игрушки}`
                ]
                

                чанк block-tovar__tovar--tpl:
                <div class="wrap-rows">
                
                [[getImageList ?
                &docid=`[[+id]]`
                &tvname=`tovar_info`
                &tpl=`game-infaTpl`
                ]]
                ..kod
                </div>
                
    Вы должны авторизоваться, чтобы оставлять комментарии.