Задание. Представьте, что вы сделали клиенту сайт, он его заполнил, в раздел «Статьи» уже выложил около 50 статей, после чего звонит вам и просит, чтобы в разделе статьи URL были такими:/articles/23/то есть, чтобы псевдонимом у статей был id ресурса. Напишите код, который надо выполнить в консоли, чтобы у всех существующих статей исправить псевдонимы.
Для более продвинутых пользователей — напишите плагин, который будет устанавливать нужное значение для всех создаваемых документов в разделе «Статьи»
Итак, первая часть задания.
Для того, чтобы у нескольких ресурсов изменить значение какого-то поля, нужно их сначала получить:
$resources = $modx->getCollection('modResource',array('parent' => 22));и после этого внести изменения:$resources = $modx->getCollection('modResource',array('parent' => 22));
foreach ($resources as $res) {
$res->set('alias', $res->get('id'));
$res->set('isfolder', 1);
$res->save();
}Заодно и сделали все статьи контейнерами, чтобы URL заканчивался не на .html, а на /Теперь вторая часть задачи.
Здесь мы уже определили, что при создании плагина надо указать, что он срабатывает на событие OnDocFormSave:
/* Сначала проверяем на всякий случай,
нужное ли нам событие произошло и что ресурс находится в "статьях" */
if ($modx->event->name != "OnDocFormSave"
|| $resource->get('parent') != 22) {return;}
// Устанавливаем новые значения
$resource->set('alias', $resource->get('id'));
$resource->set('isfolder', 1);
// и сохраняем объект
$resource->save();
return;
Объектная
$modx->invokeEvent('OnDocFormSave', array( 'mode' => 'new', // или upd 'id' => $id, // id ресурса 'resource' => $resource, // сам ресурс 'reloadOnly' => false ));$resource = $modx->getObject('modResource', $id);Необходимо пересохранять ресурсы
Вложенность ресурсов 5 уровней и больше. Указывая один корневой раздел и условие по id шаблона (независимо от уровня вложенности) обновить/пересохранить. Не подскажете?
====
То есть раздел, у которого id=2 и внутри него пересохранить все ресурсы, у которых template=4
====
Должно, вроде бы, работать, но Consloe не может завершить, и висит на «Loading...»
<?php ini_set('max_execution_time', 0); ignore_user_abort(true); $c = 'modResource'; $q = $modx->newQuery($c); $resources = $modx->getChildIds(2, 10, array('context'=>'web')); $q->where(array('id:IN' =>$resources)); $q->where(array('template' => 4)); $q->sortby('id'); $q->select(array( "{$c}.*", )); $s = $q->prepare(); $s->execute(); while($row = $s->fetch(2)) { $response = $modx->runProcessor('resource/update', $row); if($response->isError()){ print_r($response->getResponse()); return; } $modx->error->reset(); }Заранее большое спасибо.<?php // Отвечаем только на Ajax if ($_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') {return;} // Можно передавать в скрипт разный action и выполнять разные действия. $action = $_POST['action']; if (empty($action)) {return;} // Получаем от клиента номер итерации $offset = $_POST['offset'] ? (int) $_POST['offset'] : 0; $limit = 10; // Составляем список ресурсов для обработки в текущей итерации $q = $modx->newQuery('modResource', array('parent' => 2)); $q = $modx->newQuery('modResource', array('template' => 4)); $q->sortby('id'); $s = $q->prepare(); // Узнаем, сколько всего ресурсов $count = $modx->getCount('modResource', $q); // Обрабатываем только часть, пропуская уже обработанные $q->limit($limit,$offset); $q->prepare(); $q->stmt->execute(); $res = $q->stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($res as $v) { $properties = array( 'id' => $v['modResource_id'] , 'context_key' => 'web' ); // Теперь можно, напирмер, поменять псевдоним ресурса $properties['alias'] = $v['modResource_pagetitle']; $response = $modx->runProcessor('resource/update', $properties); } // Проверяем, все ли строки обработаны $offset = $offset + $limit; if ($offset >= $count) { $sucsess = 1; } else { $sucsess = round($offset / $count, 2); } // И возвращаем клиенту данные (номер итерации и сообщение об окончании работы) $output = Array('offset' => $offset, 'sucsess' => $sucsess); echo json_encode($output); die();У меня есть ресурсы с товаром(у них шаблон с ID=4), на странице есть два поля, price_dollar(цена в долларах) и price(цена в рублях). А на главной странице есть curs(курс рубля). Что надо написать в плагине, что бы при смене курса поле цены в рублях пересчитывалось у всех ресурсов с ID=4?
Пробовал сделать, но почему-то не работает… вот код:
<?php if ($modx->event->name != "OnDocFormSave" || $resource->get('template') != 2) {return;} $where = array('template' => 4); $res = $modx->getCollection('modResource',$where); foreach ($res as $resource) { $id = $resource->get('id'); $wh1 = array( 'contentid' => $id , 'tmplvarid' => 25 ); $tv1 = $modx->getObject('modTemplateVarResource', $wh1); $doll = $tv1->get('value'); $wh2 = array( 'contentid' => 1 , 'tmplvarid' => 26 ); $tv2 = $modx->getObject('modTemplateVarResource', $wh2); $curs = $tv2->get('value'); $newdoll = $doll * $curs; $resource->setTVValue('price',$newdoll) } return;А вообще, давай, попробуем по-проще написать.
<?php if ($modx->event->name != "OnDocFormSave" || $resource->get('template') != 2) {return;} // Сначала узнаем курс $mainpage = $modx->getObject('modResource', 1); $curs = $mainpage->getTVValue('curs'); // Потом выберем все товары $where = array('template' => 4); $res = $modx->getCollection('modResource',$where); // Ну и каждому товару укажем новую цену foreach ($res as $product) { $price = $product->getTVValue('price_dollar'); $product->setTVValue('price', $price * $curs); } return;Спасибо за статьи, начал только изучать modx. Очень помогли. Подскажите, мне нужно обработать 2 шаблона ($where = array('template' => 4);$where = array('template' => 8);)
Как загнать в один массив для обработки?
$where = array('template:IN' => array(4,8));https://rtfm.modx.com/xpdo/2.x/class-reference/xpdoquery/xpdoquery.whereПрошу Вашей помощи.
На сайте компании сделан пересчёт цены товара в зависимости от курса валюты. Пересчёт происходит при сохранении карточки товара. Часто приходится импортировать товар, соответственно он появляется без цены, нужно заходить в каждый товар и нажимать сохранить. Мне посоветовали использовать следующий скрипт:
<?php foreach($modx->getIterator('modResource',array('template' => 4)) as $res){ $modx->invokeEvent('OnDocFormSave', array( 'mode' => 'upd', 'id' => $res->id, 'resource' => $res, 'reloadOnly' => false )); }Пересчёт действительно идёт, но ни с того вдруг затыкается на каком-то товаре и дальше пересчёт не идёт. Если зайти в товар с id следующим после последнего пересчитаного и сохранить карточку, то цена появляется. Но при дальнейшем запуске скрипта пересчёт всё равно уже не идёт:(
Подскажите, пожалуйста, что можно предпринять в данном случае?
Спасибо большое!
<?php // Сколько ресурсов обрабатывать за раз $step = 1; // Если процесс уже остановлен, сбрасываем OFFSET if (!isset($_SESSION['Console']['completed'])) { $_SESSION['console_offset'] = 0; } $offset = isset($_SESSION['console_offset']) && $_SESSION['console_offset'] ? $_SESSION['console_offset'] : 0; // Формируем запрос $q = $modx->newQuery('modResource',array('template' => 4)); $total = $modx->getCount('modResource', $q); // Пропускаем все уже обработанные объекты $q->limit($step, $offset); $resources = $modx->getCollection('modResource', $q); // Обработка foreach ($resources as $resource) { print "<p>Processing resource <b>".$resource->get('pagetitle')."</b></p>"; $modx->invokeEvent('OnDocFormSave', array( 'mode' => 'upd', 'id' => $resource->id, 'resource' => $resource, 'reloadOnly' => false )); } // Меняем offset $_SESSION['console_offset'] = $offset + $step; if ($_SESSION['console_offset'] >= $total) { $sucsess = 100; $_SESSION['Console']['completed'] = true; } else { $sucsess = round($_SESSION['console_offset'] / $total, 2) * 100; $_SESSION['Console']['completed'] = false; } for ($i=0; $i<=100; $i++) { if ($i <= $sucsess) { print '='; } else { print '_'; } } print "\n"; print $sucsess.'% ('.$_SESSION['console_offset'].')'."\n\n";if (.....|| $resource->get('parent') != 20) {return;}что делает resource? и get'parent' != 20 — это как я понимаю каждый раз false??? И что retuurn возвращает? Заранее, спасибо)return не просто возвращает, а ещё и прекращает дальнейшее выполнение кода. Соответственно, если условие не верно, дальше код выполнен не будет
$resources = $modx->getCollection('modResource',array('parent' => 19)); foreach ($resources as $res) { $res->set('template', 3); $res->save(); }$resources = $modx->getCollection('modResource',array('parent' => 22)); foreach ($resources as $res) { $res->set('introtext', $res->get('id')); $res->save(); }<?php $resources = $modx->getCollection('modResource',array('parent' => 4)); foreach ($resources as $res) { $id = $res->get('id'); $product = $modx->getObject('msProduct', $id); //Получаем объект класса msProduct $options = $product->getMany('Options'); //Так как композитная связь один ко многим, то применяем getMany() //Прокодим циклом по опциям foreach ($options as $option) { //Ищем поле с нашим ключем if($option->get('key') == 'drive'){ //Проверяем на пустоту if($option->get('value') != ''){ $drive = $option->get('value'); //Получаем значение опции с ключом drive например $pagetitle = $res->get('pagetitle'); //Получаем поле с заголовком $res->set('introtext', 'Текст '.$drive.' текст '.$pagetitle.' текст.'); $res->save(); }else{ echo 'Не заполнено drive'; continue; } } } }1) Я создал контейнер статьи с айди7 и поместил туда несколько дочерних ресурсов.
2) В «элементы — плагин — создать плагин» добавил плагин и назвал его test
3) Написал туда код
/* Сначала проверяем на всякий случай, нужное ли нам событие произошло и что ресурс находится в "статьях" */ if ($modx->event->name != "OnDocFormSave" || $resource->get('parent') != 7) {return;} // Устанавливаем новые значения $resource->set('alias', $resource->get('id')); $resource->set('isfolder', 1); // и сохраняем объект $resource->save(); return;4) Начал создавать ресурсы алиас не меняется.Пришел к выводу что то не работает.
Что я сделал не так?
<?php
// Выполняем поиск по заголовку
$resource = $modx->getObject('modResource', array('pagetitle' => 'Заголовок 1', 'pagetitle' => 'Заголовок 2'', 'pagetitle' => 'Заголовок 3'));
if (is_object($resource)) {
// преобразуем объект в массив
$resource = $resource->toArray();
// изменим публикацию (опубликована/не опубликована) страницы
$resource[«published»] = '1';
// выполнение процессора
$response = $modx->runProcessor('resource/update', $resource);
// если ошибка
if($response->isError()){
echo «Произошла ошибка». $response->getMessage();
}
else{
echo «Документ изменен»;
}
} else {
echo «Документ не найден»;
}