Контент


[Ko3.3] Модуль Minion

В списке официальных модулей Kohana наконец-то прибавление. RC1 для Kohana 3.3 содержит новый модуль Minion. Он предназначен для выполнения задач через CLI (обычно это задачи для Cron‘а).

Подготовка

Для начала необходимо настроить модуль для работы.

  • К сожалению, релиз RC1 содержит ссылку не на последнюю версию модуля Minion, поэтому необходимо вручную обновить модуль до последнего коммита (т.е. до HEAD). Это делается командой cd modules/Minion && git pull origin 3.3/develop.
  • Разрешаем загрузку модуля Minion в файле bootstrap.php (он там уже по умолчанию есть, но закомментирован).
  • Копируем файл minion из MODPATH/minion/ в нужное место (т.е. туда, откуда он будет запускаться планировщиком задач). Можно и не копировать. Затем вносим в него правки, чтобы переменные $application, $modules и $system указывали в правильные места (можно скопировать их из index.php, если вы решили его положить в DOCROOT).

Чтобы проверить, правильно ли все настроено, запустите из терминала команду:

./minion --help

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

Задачи в Minion

Самый простой способ понять этот механизм — создать простейшую задачу. По традиции реализуем вывод фразы «hello world!«:

// файл APPPATH/classes/Task/Welcome.php
<?php defined('SYSPATH') or die('No direct script access.');
 
/**
 * Its a test task class
 *
 * @author biakaveron
 */
class Task_Welcome extends Minion_Task {
 
	/**
	 * Test action
	 *
	 * @param array $params
	 * @return void
	 */
	protected function _execute(array $params)
	{
		Minion_CLI::write('hello world!');
	}
 
}

Вот и все. Если запустить команду ./minion --task=welcome, то в ответ увидим строку «hello world!».

Каждая задача выполняется в виде отдельного класса-потомка Minion_Task. За выполнение задачи отвечает метод _execute($params).

Передача параметров

В методе _execute() присутствует аргумент $params, который будет содержать все параметры, переданные в задачу через консоль. Все, кроме имени задачи (ключ --task) и специального ключ --help (о нем расскажу позже). Например, ./minion --task=welcome --foo=bar означает передачу параметра ‘foo‘ со значением ‘bar‘.

Имена параметров (в том числе и task) регистрозависимы, поэтому ./minion --Task=welcome и ./minion --tasK=welcome приведут к ошибке. Кроме того, имена задач тоже должны быть в нужном регистре (допускается полностью нижний регистр в имени). Например, ./minion --task=welcome и ./minion --task=Welcome сработают, а ./minion --task=welcomE нет.

Если вы попробовали запустить задачу Welcome с дополнительными параметрами, то должны были получить сообщение об ошибке Kohana. Дело в том, что необходимо для каждой задачи явно описывать допустимые параметры, а также их значения по умолчанию. Таким образом, новая версия задачи Welcome будет выглядеть примерно так:

<?php defined('SYSPATH') or die('No direct script access.');
 
/**
 * Its a test task class
 *
 * @author biakaveron
 */
class Task_Welcome extends Minion_Task {
 
	protected $_options = array(
		// param name => default value
		'foo'   => 'beautiful',
	);
 
	/**
	 * Test action
	 *
	 * @param array $params
	 * @return void
	 */
	protected function _execute(array $params)
	{
		Minion_CLI::write('hello '.$params['foo'].' world!');
	}
 
}

Теперь ./minion --task=Welcome выведет «hello beautiful world» (использовано значение по умолчанию), а ./minion --task=Welcome --foo=great напишет «hello great world«.

Ввод и вывод данных

Класс Minion_CLI содержит необходимые методы для работы с потоками ввода и вывода. Как правило, действия направлены на запрос у пользователя данных и вывод их обратно.

Чтение из потока

Используйте метод Minion_CLI::read($text = '', array $options = NULL):

// просто прочитать 1 строку
Minion_CLI::read(); 
// вывести строку 'Введите имя' и считать ответ
Minion_CLI::read('Введите имя'); 
// вывести строку 'Ваш пол [ м, ж ]' и считать ответ. Если это не 'м' или 'ж', то 
//  Minion будет выдавать сообщение 'This is not a valid option. Please try again.' до получения корректного результата.
//  Буквы в фильтре регистрозависимы, т.е. значение 'М' считается некорректным!
Minion_CLI::read('Ваш пол', array('м', 'ж'));

Запись в поток

Метод Minion_CLI::write($text = '') позволяет отправить сообщение. Переменная $text может быть массивом, в таком случае каждый элемент будет выведен с новой строки.

// выведет всем известную фразу
Minion_CLI::write('Hello world!');
// покажет строчки с известным стихотворением
Minion_CLI::write(array('Жили у бабуси', 'Два веселых гуся'));
// перейдет на следующую строчку
Minion_CLI::write();

Еще есть метод Minion_CLI::write_replace($text = '', $end_line = FALSE), который затирает предыдущую строку новым сообщением. Это может быть полезно, скажем, для имитации загрузки. Флаг $end_line стоит использовать для «фиксации» строки (будет добавлен конец строки):

Minion_CLI::write_replace('h');
Minion_CLI::wait(1);
Minion_CLI::write_replace('he');
Minion_CLI::wait(1);
Minion_CLI::write_replace('hel');
Minion_CLI::wait(1);
Minion_CLI::write_replace('hell');
Minion_CLI::wait(1);
Minion_CLI::write_replace('hello', TRUE);

Данный пример выведет слово ‘hello‘ постепенно, как бы с эффектом печатающей машинки. Minion_CLI::wait(1), как можно догадаться, означает паузу в 1 секунду.

Валидация

По умолчанию все переданные параметры проверяются только на их наличие в списке разрешенных. Такое поведение можно легко изменить с помощью метода build_validation(Validation $validation). Он подготавливает объект Validation для дальнейшей проверки параметров. Вот так он выглядит в классе Minion_Task:

public function build_validation(Validation $validation)
{
	// Add a rule to each key making sure it's in the task
	foreach ($validation->as_array() as $key => $value)
	{
		$validation->rule($key, array($this, 'valid_option'), array(':validation', ':field'));
	}
		return $validation;
}

Каждый переданный параметр проверяется с помощью метода valid_option(), который просто ищет имя параметра в списке разрешенных. Если мы захотим ограничить поле foo длиной в 10 символов, то необходимо будет создать в задаче Welcome метод build_validation():

public function build_validation(Validation $validation)
{
	return parent::build_validation($validation)
		->rule('foo', 'max_length', array(10));
}

Не забывайте вернуть объект Validation!

А вот пример для задачи без ограничений по параметрам:

public function build_validation(Validation $validation)
{
	return $validation;
}

Я просто не стал добавлять никаких правил (в том числе и определенных в классе-родителе). Теперь явно указывать параметры задачи в свойстве $_options необязательно.

Справка по задачам

Модуль имеет зарезервированный ключ --help, по которому он отображает справку по задаче (если указана в параметре --task) или по модулю в целом (мы это видели после команды ./minion). Так, вызов ./minion --task=Welcome --help для нашей задачи Welcome вернет такой текст:

Usage
=======
php minion.php --task=welcome [--option1=value1] [--option2=value2]

Details
=======
Author: biakaveron

Description
===========
Its a test task class

Легко понять откуда взялась такая информация — из PHPDOC к классу Task_Welcome. Таким вот образом разработчики Kohana облегчают работу, позволяя разом убивать двух зайцев — документировать исходники и писать man для задач.

Альтернативный запуск задач

Запускать задачи можно и без использования скрипта minion. Любые CLI-команды будут перенаправлены к модулю Minion, поэтому вместо ./minion --task=Welcome можно использовать php index.php --task=Welcome.

Заключение

Очень полезный модуль. Однако он, как и вся ветка 3.3, еще находится в стадии доработки, пока что имеются недочеты. Используйте его с осторожностью.

Google Bookmarks Digg Reddit del.icio.us Ma.gnolia Technorati Slashdot Yahoo My Web News2.ru БобрДобр.ru RUmarkz Ваау! Memori.ru rucity.com МоёМесто.ru Mister Wong

Опубликовано в Kohana3.

Теги: , , .


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

Будьте в курсе обсуждения, подпишитесь на RSS ленту комментариев к этой записи.

  1. vomchik пишет:

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

  2. Vovochka пишет:

    Спасибо за обзор, было интересно узнать о таком модуле.

    Вообще, как по мне, немного не хватает нормальных обзоров хороших модулей для различных задач.
    kohana-modules — какая-то помойка. Ни описания толкового, ничего кроме ссылки на гитхаб.

    А вот так вот, чтоб с чувством, с толком, с расстановкой.. Этого не хватает :)
    Спасибо вам :)

  3. Илья пишет:

    Здравствуйте автор поста. Скажите, данный модуль можно прикрутить к Kohana 3.1? Или он будет работать только с 3.3

  4. biakaveron пишет:

    @Илья

    Можно.

    1. Переименовываем все файлы директории classes в нижний регистр
    2. Если хотим, чтобы работал help, то правим в файле classes/task/help.php Kohana::list_files('classes/Task') на Kohana::list_files('classes/task')
    3. Не забываем добавить модуль в Kohana::modules()
    4. Проверяем, вызов ./minion --task=help должен работать.

  5. Zeelot пишет:

    Cheers :) I would suggest you replace the `echo` in the examples with Minion_CLI::write() so people are made aware of the proper way to output text in CLI tools

  6. biakaveron пишет:

    Article has been updated. Thank you, Zeelot!

  7. klay пишет:

    Шикарно! :)

  8. klay пишет:

    Вы как всегда — на высоте. Так держать

  9. seyfer пишет:

    cd modules/Minion && git pull origin 3.3/develop.

    У меня Кохана не с гита. Как скачать последнюю версию?
    А вот отсюда: https://github.com/kohana/kohana/tree/3.3/develop

    з.ы. у вас openid не работает. меня не пускает с livejournal.

  10. biakaveron пишет:

    Всегда можно пользоваться либо текущей разрабатываемой (ветка develop), либо стабильной (ветка master и созданные тэги) версией. На Гитхабе это найти достаточно просто, там удобный интерфейс. Другое дело, что без Гита придется пройтись по всем модулям и скачать их вручную.

  11. seyfer пишет:

    Он там вынесен, можно clone https://github.com/kohana/minion.git

    Я вот пробую к 3.2 прикрутить. Запускаю в консоли ./minion —help или любой таск, получаю в консоль html главной страницы о_О

  12. biakaveron пишет:

    > Он там вынесен, можно clone https://github.com/kohana/minion.git

    Как и любой другой модуль Kohana. Я про использование web-GUI от Гитхаба.

    > Запускаю в консоли ./minion —help или любой таск, получаю в консоль html главной страницы о_О

    Честно говоря, времени пока не было даже чтобы релизнутую 3.3 покрутить, а уж про портирование на 3.2 даже не задумывался ))

  13. seyfer пишет:

    В этой теме есть версия для 3.2, но и там не все гладко

    http://forum.kohanaframework.org/discussion/10947/cli-detection-and-base_url-in-bootstrap

    задал там вопрос

  14. seyfer пишет:

    Я таки прикрутил

    http://seyferseed.ru/php/modul-minion-s-kohana-3-3-na-kohana-3-2.html

  15. Андрей пишет:

    В 3.2 я запускаю задачи просто index.php --uri=controller/action/param. Вроде все прекрасно работает.

    Скажите, что мне даст использование дополнительно модуля Minion?

  16. biakaveron пишет:

    1. Не придется в коде смешивать стандартные контроллеры и CRON-контроллеры с проверками типа if (Kohana::$is_cli). Суп отдельно, мухи отдельно.
    2. Задачи в Minion позволяют поддерживать большое количество параметров, которые сложно предусмотреть в роутинге. Передавать через GET можно, но не так удобно.
    3. Зачем тратить время на HTTP-шные вещи типа заголовков, запрос/ответ и тд? Таски в Minion «заточены» под выполнение конкретных задач.
    4. Поддержка —help позволяет не ковырять исходники Вам или коллегам, которые будут сопровождать проект. Мелочь, а приятно.

    И тд.

  17. Андрей пишет:

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

  18. Invis1ble пишет:

    Иван, спасибо за обзор.
    Единственное, что я не понял — это для чего убрали Kohana::$is_cli. Хотел сделать подключение модуля в зависимости от окружения, и не нашел свойства is_cli. Будем по-старинке PHP_SAPI проверять =)

  19. biakaveron пишет:

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

  20. Invis1ble пишет:

    >> Необходимый модуль можно подключать прямо в таске

    Это понятно, я имел в виду подключение самого Minion’а :)

  21. biakaveron пишет:

    А, ну тогда только PHP_SAPI, ага

  22. Никита пишет:

    С этим то понятно. Не понятно как, например, вызвать метод из модели.
    protected function _execute(array $params)
    {
    Model::factory('City')->get_regions();
    }

    Вызывает ошибку:
    Call to undefined function mysql_connect();

    Запускаю задачу так:
    %php% -f C:\OpenServer\domains\mycohanasite\index.php — —task=welcome

  23. biakaveron пишет:

    Давно не работал с php под Windows, но вероятно проблема аналогична http://stackoverflow.com/questions/181222/php-mysql-connect-wont-work-via-command-line

  24. Gerome пишет:

    Добавил метод валидации к задаче, теперь не запускается:
    php minion --task=welcome --foo=good
    Выдает ошибку:
    ErrorException [ 2 ]: Missing argument 2 for Kohana_Valid::max_length() ~ SYSPATH\classes\Kohana\Valid.php [ 61 ]

  25. biakaveron пишет:

    Очевидно, что правило max_length описано не полностью. Там должно быть 2 параметра.

  26. Gerome пишет:

    @biakaveron, да, вот такое правильно нормально все выводит:

    ->rule('foo', 'max_length', array(':value',10));

  27. Маск пишет:

    А как необходимый модуль подключать прямо в таске? Что то я нигде не нашел…

  28. biakaveron пишет:

    Как и при обычном запросе — вызвать Kohana::modules(Kohana::modules() + array(‘foo’ => MODPATH . ‘path/to/new/module’))

Продолжение обсуждения

  1. Модуль Minion с Kohana 3.3 на Kohana 3.2 | {Нет предела совершенству} когда вокруг столько идиотов(); ссылается на эту запись on 29 октября 2012

    [...] в решении вопроса мне помог блог участника сообщества biakaveron. У него можно почитать про модуль [...]



Можно включить подсветку кода: <code><pre lang="">...</pre></code>
Разрешены некоторые HTML теги

или используйте trackback.