Все началось с того, что мне потребовалось автоматически обновлять статусы задач в зависимости от текущей даты на выполненные или невыполненные. Система задач написана на Symfony 2, и хотелось обойтись без команды wget в задании cron. Было бы неплохо выполнять обновление статусов и вручную через консоль Symfony 2. Я решил эту задачу, написав пару классов: сервис и команду.
Чтобы добавить свою команду в app/console, необходимо написать класс, расширяющий \Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand. В нем важными методами являются configure(), где происходит инициализация команды в системе и execute(), где происходит исполнение команды.
Далее напишем класс, выполняющий действие обновления записей. Это будет подключаемым через контейнер DI сервисом.
Конструктор данного класса принимает в качестве параметра контейнер DI, из которого мы получаем Doctrine Entity Manager. Прописываем конфигурацию подключения сервиса в services.yml.
Перейдя в консоль и выполнив команду $ php app/console, мы должны увидеть в списке новоиспеченную команду demo:tasks:state:update. Последнее, что осталось сделать, это добавить задание в cron. Я установил выполнение команды раз в сутки в 00:00.
При создании данной статьи я пользовался официальной документацией Symfony 2.0.
Чтобы добавить свою команду в app/console, необходимо написать класс, расширяющий \Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand. В нем важными методами являются configure(), где происходит инициализация команды в системе и execute(), где происходит исполнение команды.
<?php
namespace Acme\DemoBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class UpdateStateTaskCommand extends ContainerAwareCommand {
public function configure() {
$this
->setDefinition(array())
->setDescription('Update states for tasks for Demo Bundle')
->setName('demo:tasks:state:update'); //здесь прописываем имя нашей будущей команды
}
protected function execute(InputInterface $input, OutputInterface $output) {
//получаем сервис, который будет непосредственно обновлять статусы
$stateUpdater = $this->getContainer()->get('acme_demo.state_updater');
$stateUpdater->update();
//записываем событие в лог
$logger = $this->getContainer()->get('logger');
$logger->info('Fired update system tasks for disciplines');
}
}
Далее напишем класс, выполняющий действие обновления записей. Это будет подключаемым через контейнер DI сервисом.
<?php
namespace Acme\DemoBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Сервис для управления состоянием задач
*
*/
class State {
private $container;
public function __construct(ContainerInterface $container) {
$this->container = $container;
}
public function update(){
$em = $this->container
->get('doctrine')
->getEntityManager();
$currentDate = new \DateTime('now');
//запрос на все задачи
$query = $em->createQueryBuilder()
->select('t')
->from('AcmeDemoBundle:Task', 't')
->getQuery()
;
$tasks = $query->getResult();
if($tasks) {
foreach($tasks as $task) {
$diff = $task->getPlan()->getTimestamp() - $currentDate->getTimestamp();
if($diff > 0 && (($diff / 86400) > 1)) {
//если просрочена планируемая дата, то ставим статус Не выполнено
$state = $em->getRepository('AcmeDemoBundle:State')->findOneByName('Не выполнено');
if($state) {
$task->setState($state);
}
} else {
$task->setState(null);
}
}
$em->flush();
}
}
}
Конструктор данного класса принимает в качестве параметра контейнер DI, из которого мы получаем Doctrine Entity Manager. Прописываем конфигурацию подключения сервиса в services.yml.
services:
#....
acme_demo.state_updater:
class: Acme\DemoBundle\Controller\State
arguments: ['@service_container']
Перейдя в консоль и выполнив команду $ php app/console, мы должны увидеть в списке новоиспеченную команду demo:tasks:state:update. Последнее, что осталось сделать, это добавить задание в cron. Я установил выполнение команды раз в сутки в 00:00.
0 0 * * * cd /home/username/site.ru && /usr/bin/php app/console demo:tasks:state:update
При создании данной статьи я пользовался официальной документацией Symfony 2.0.