ilyautkin 11 июня 2015 1 1
Сегодня вышла новая версия дополнение Console для MODX.

Обновление коснулось возможности отправлять повторные циклические запросы на сервер и выполнять один и тот же код несколько раз — до тех пор, пока все, что вам нужно не будет обработано.

Вот небольшая демонстрация того, как это новшество можно использовать:


Включить этот функционал очень просто. Нужно определить переменную $_SESSION['Console']['completed'] и присвоить ей значение false — тогда консоль будет выполнять скрипт до тех пор, пока значение этой переменной не станет равной true.

Вот код, который выполнялся в видео. Здесь происходит пошаговая обработка ресурсов, причем за один шаг обрабатывается только один ресурс. Такой код поможет вам обработать неограниченное число объектов даже на слабом сервере — нужно только время.
<?php
$q = $modx->newQuery('modResource', array('published' => 0));
$q->limit(1);
if ($resources = $modx->getCollection('modResource', $q)) {
    foreach ($resources as $resource) {
        print "Публикую ресурс <b>".$resource->get('pagetitle')."</b>";
        $resource->set('published', 1);
        $resource->save();
    }
    // Говорим консольке, что обработка еще не завершена
    $_SESSION['Console']['completed'] = false;
} else {
    // Останавливаем обработку
    $_SESSION['Console']['completed'] = true;
    print "Готово";
}

А вот пример посложнее — уже с использованием offset:
<?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');
$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>";
    sleep(0.5);
}
// Меняем 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";

Единственный нюанс в том, что код можно продолжать редактировать по ходу выполнения скрипта. Но я еще не определился — баг это или фича)
1 комментарий
Fi1osof1
Fi1osof 11 июня 2015г в 12:49 #
Илья, спасибо за пулл-реквест! Полезная штука :)
Вот только думаю надо немного механизм изменить. Вот получается, что есть $_SESSION['Console']['completed'] === false, то скрипт опять выполняется в цикле. А вот рассмотрим такой пользовательский сценарий:
1. Запускаем циклический скрипт, устанавливающий $_SESSION['Console']['completed'] = false;
2. Этот скрипт при выполнении разваливается или еще по какой причине не доходит до того, чтобы установить $_SESSION['Console']['completed'] = true.
3. Запускаем новый скрипт на выполнение, не циклический. Он все равно начнет отрабатываться бесконечно, потому как $_SESSION['Console']['completed'] === false, и true он не устанавливает.
Правильней не $_SESSION['Console']['completed'] === false проверять, а $this->getProperty('progress') == true. То есть в процессе выполнения ты смотришь, если надо повторно выполнить скрипт, то устанавливаешь $this->setProperty('progress', true); И действовать это будетолько на текущий шаг. И так в каждом последующем шаге.
Авторизуйтесь или зарегистрируйтесь (можно через соцсети ), чтобы оставлять комментарии.