Fi1osof
2 июля 2013 г., 17:48

MIGX. Выборка getImageList с условиями.

В блоге Blog by Fi1osof

Данный топик — ответ вот этому: community.modx-cms.ru/blog/9281.html
Я не буду особо лезть в детали, с какими мы здесь трудностями сталкивается, а хочу только сказать, что даже со средними знаниями php можно обходить многие эти сложности. При этом ваши скрипты будут выполняться гораздо быстрее, и будут они более гибкими в использовании.
Справедливости ради приведу работающий вызов этого сниппета на уровне MODX-синтаксиса.
$output= '[[getImageList? &tvname=`afisha` &tpl=`Tpl` &docid=`338` &limit=`3` &sort=`[{"sortby":"data","sortdir":"ASC"}]` &where=`{"data:>":"[[!today]]"}` ]]';
Заметка автору: [[!today]] в вашем случае должен возвращать полную дату, например 2012-12-18 22:00:00, а не time(). И вам внимательно надо продумать правильное кеширование всего этого.
Самые главные минусу нативного решения: 1) В условие where можно прописать только одно поле. 2) Хоть мы и указываем limit, выборка происходит все равно всех элементов, а потом уже на уровне перебора массива срабатывает limit. Хотя здесь как правило небольшое количество элементов, но этот минус справедлив для многих подобных решений.
А теперь мой скрипт на замену:
if(!$doc_id) {return '';} $output = ''; // Получаем TV по ID документа $q = $modx->newQuery('modTemplateVar'); $q->innerJoin('modTemplateVarResource', 'v', 'v.tmplvarid = modTemplateVar.id'); $q->where(array( 'v.contentid' => $doc_id, 'modTemplateVar.id' => $tv_id, )); $q->limit(1); $q->select(array('modTemplateVar.*', 'v.value')); if(!$tv = $modx->getObject('modTemplateVar', $q)){ return ''; } // Получаем его значение $value = $tv->get('value'); // Получаем массив из JSON-строки $array = $modx->fromJSON($value); // Пробегаемся по всему массиву и фильтруем по дате $data = array(); $now = time(); $i = 0; foreach($array as $r){ $time = strtotime($r['data']); if($time < $now){continue;} $data[$time] = $r; if(++$i == $limit){break;} } // Сортируем массив по ключу (чтобы по дате отсортировать) ksort($data); foreach($data as $r){ $output .= $modx->getChunk($tpl, $r); } return $output;
Да, он чуть сложнее, чем работа на уровне синтаксиса, но если вы освоите API MODX, то вы сможете работать с любыми объектами. Честно скажу, что у меня написание этого сниппета заняло меньше времени, чем изучение сниппета getImageList и выяснение, почему же &where=`[{«data:>»:"[[!today]]"}]` не работает, а &where=`{«data:>»:"[[!today]]"}` работает (пришлось лезть в код модуля и выяснять, что он не умеет принимать массив условий, а только одно условие ключ->значение).
При этом решение на уровне таких сниппетов и более гибкое, и работает быстрее, и кеширование гибкое прописать можно. В общем здесь куча плюсов.
При вызове getImageList в шаблоне вывода процессора web/getdata, путь к изображению выводится одинаковый. Кто-нибудь сталкивался с таким поведением снипета?
Мы сам getImageList не вызываем. Выкладывайте листинг вашего кода, глянем что там у вас.
Для каждого ресурса в шаблоне следующий вызов getImageList. Путь в источнике файлов задан [[migxResourceMediaPath? &pathTpl=`assets/images/{id}/`]]
{assign var=getImageListParam value=[ 'tvname' => Images, 'tpl' => '@CODE: ', 'limit' => 1, 'randomize' => true, 'docid' => {$object_sale.id} ]} {snippet name='getImageList' assign=image params=$getImageListParam parse=true} {$image}
1. Вот такой код у меня в консоли выполняется:
switchContext('web'); $modx->resource = $modx->getObject('modResource', 4); $s = $modx->runSnippet('getImageList', array( 'tvname' => 'gallery', 'tpl' => '@CODE: ', 'limit' => 1, 'randomize' => true, 'docid' => 4 )); print $s;
То есть выводится рандомная картинка. 4 — это id документа с мигх-картинками. Собственно это ваш код, поэтому все должно работать.
2. Я, как обычно, формирую пути в процессоре. А потом просто использую массив картинок $object.gallery
путь к изображению выводится одинаковый.
То есть картинка выводится, но не работает рандом или что?
То есть картинка выводится, но не работает рандом или что?
Картинка выводится та, но путь к ней не тот. Выводит так:
А должен так:
Ваш код, у меня в консоли, выдает ошибку: Call to a member function getSource() on a non-object in Z:\domains\phoenix\core\cache\includes\elements\modsnippet\3.include.cache.php
Я уже весь мозг себе сломал ((
Выяснил вот какую особенность. Поставил modx. Установил только Console, MIGX. Создал TV параметр MIGX. Следующий код выполнился успешно:
switchContext('web'); $modx->resource = $modx->getObject('modResource', 1); $s = $modx->runSnippet('getImageList', array( 'tvname' => 'gallery', 'tpl' => '@CODE: ', 'limit' => 1, 'randomize' => true, 'docid' => 1 )); print $s;
Затем поставил modxSite, modxSmarty. И вышеприведенный код перестал работать. Удаление установленных пакетов не повлияло на работоспособность кода. Он просто перестал работать и все.
Ваш код, у меня в консоли, выдает ошибку: Call to a member function getSource() on a non-object in Z:\domains\phoenix\core\cache\includes\elements\modsnippet\3.include.cache.php
Здесь два варианта: 1. Вы не меняли id документа, и документа с id 4 просто нет. $modx->resource = $modx->getObject('modResource', 4); 2. Нет указанного медиасурса.
Затем поставил modxSite, modxSmarty. И вышеприведенный код перестал работать. Удаление установленных пакетов не повлияло на работоспособность кода. Он просто перестал работать и все.
Великие сомнения на счет того, что эти пакеты при установке на что-то могли повлиять. Они просто не цепляют ядра. Тем не менее пришлите в личку доступ к админке, где установлены эти пакеты и этот код не работает. Я посмотрю.
Прошу прощения. Действительно имя TV параметра указал неверный.
В итоге что, вопрос полностью решился или как?
Не совсем.
{processor action="web/getdata" ns="shopmodx" assign=value} {foreach $value.object as $obj} [[!getImageList?docid=`{$obj.id}`&tpl=`@CODE: `&limit=`1`&randomize=`true`&tvname=`gallery`]] {/foreach}
Пути некорректно выводит. Как будто id ресурса не меняется при каждом вызове getImageList. При этом имя изображения правильное. В консоли выводит как положено, при изменении id ресурса выводит путь тот который должен быть.
Ваш код я уверен что будет работать, т.к. в одном проекте я делал похожим образом и путь формировался корректно. Написал свой процессор с логикой как у getImageList. Но если вызывать его по id ресурса, так же некорректно выводит путь. При этом имена файлов правильные.
Сорри, но больше ничем не помогу. Придется вам копать сам сниппет getImageList, проверяя где какие значения проходят.
Но если вызывать его по id ресурса, так же некорректно выводит путь.
Он скорее всего плейсхолдер берет не переданного значения id, а id текущего документа.
В конце концов разобрался. И все стало работать. Необходимо путь в источнике файлов делать некешируемым [[!migxResourceMediaPath? &pathTpl=`assets/images/{id}/`]]
Код процессора который я написал для себя:
setDefaultProperties(array( 'tvname' => '', 'id' => 0, //id ресурса 'randomize' => 0, 'limit' => 0, 'nameMS' => '' //имя MediaSource )); return parent::initialize(); } private function GetPath(){ $this->modx->setPlaceholder('docid', $this->getProperty('id')); $source = $this->modx->getObject('modMediaSource', array('name'=>$this->getProperty('nameMS'))); $this->modx->resource = $this->modx->getObject('modResource', $this->getProperty('id')); $source->initialize(); $value = $source->getBaseUrl(); //unset($source); return $value; } private function FindFields(xPDOObject $object) { $migx = new MIGX($this->modx); $config_r = $object->get('input_properties'); $config = $config_r['configs']; // $q = $this->modx->getObject('migxConfig', array('name'=>$config)); $data = $this->modx->fromJSON(trim($q->get('formtabs'), '[]')); $res_field = array(); foreach($data['fields'] as $field){ if ($field['inputTVtype'] == 'image' || $field['inputTVtype'] == 'file') $res_field = $res_field + array($field['field']); } unset($migx); return $res_field; } private function GetTVValue($path){ $q = $this->modx->newQuery('modTemplateVar'); $q->innerJoin('modTemplateVarResource', 'v', 'v.tmplvarid = modTemplateVar.id'); $q->where(array('modTemplateVar.name'=> $this->getProperty('tvname'), 'v.contentid' => $this->getProperty('id'))); $q->select(array('v.*, modTemplateVar.input_properties')); $q->prepare(); $tv = $this->modx->getObject('modTemplateVar', $q); $keys = $this->FindFields($tv); $object = $this->modx->fromJSON($tv->get('value')); $list = array(); $index = 0; if ($this->getProperty('randomize') != 0) shuffle($object); foreach ($object as $tv){ for ($i = 0; count($keys) > $i; $i++){ if(array_key_exists($keys[$i], $tv)){ $tv[$keys[$i]] = implode("", array($path, $tv[$keys[$i]])); } } array_push($list, $tv); $index++; if ($this->getProperty('limit') != 0 && $this->getProperty('limit') == $index) break; } //$list['count'] = $index; return array("count" => $index, "object" => $list); } public function process(){ $path = $this->GetPath(); $tv_objects = $this->GetTVValue($path); return $tv_objects; } } return 'GetDataMIGxProcessor';
Необходимо путь в источнике файлов делать некешируемым [[!migxResourceMediaPath? &pathTpl=`assets/images/{id}/`]]
Да уж, обычный случай для MODX :)
Спасибо тебе мужик! Дай свой кошелек, я тебе на пиво скину! Три дня боролся с этой проблемой, почитал твой ответ и подумал «НЕЕЕЕ, У МЕНЯ ВСЕ ГУД, ЭТО Я ТОЧНО НЕ ЗАБЫЛ СДЕЛАТЬ!» =) Эта мелочь мне изрядно попортила пару ночей, но теперь все гуд), еще раз спасибо)
Всегда пожалуйста!
Внизу форма для донейтов. Туда ОК :)

Добавить комментарий