Creating a custom scheduler task
See also
The preferred method for creating a scheduler task is as a Symfony command. Read about how to create and use Symfony commands in TYPO3 here..
Table of contents
Scheduler task registration
Custom scheduler tasks can be registered in
EXT:
in the TYPO3 configuration value
$GLOBALS
:
<?php
declare(strict_types=1);
use MyVendor\MyExtension\Tasks\MyTask;
use MyVendor\MyExtension\Tasks\MyTaskAdditionalFieldProvider;
defined('TYPO3') or die();
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][MyTask::class] = [
'extension' => 'scheduler',
'title' => 'Some title or LLL:EXT reference',
'description' => 'Some description or LLL:EXT reference',
'additionalFields' => MyTaskAdditionalFieldProvider::class,
];
Working with serialized objects
When a task is registered with the Scheduler the corresponding object instance is serialized and stored in the database (see Appendix A for more details). This is not a very common practice. There are advantages but also some pitfalls, so please read this section carefully.
A serialized object may happen to be "out of sync" with its class if the class changes some of its variables or methods. If a variable's name is changed or if variables are added or removed, the serialized object will not reflect these changes. The same goes if a method is renamed, added or deleted. Problems will also arise if the number or order of arguments used to call a method are changed. In such cases weird errors may appear, which can be very difficult to track. The only solution is to delete the registered task and register it anew.
To minimize such risks it is worth to consider implementing the
business logic in a separate class, so that the task class itself
changes as little as possible. The execute
should be as
simple as possible. Consider the following:
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\Tasks;
use MyVendor\MyExtension\BusinessLogic;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Scheduler\Task\AbstractTask;
final class MyTask extends AbstractTask
{
public function execute(): bool
{
# Dependency injection cannot be used in scheduler tasks
$businessLogic = GeneralUtility::makeInstance(BusinessLogic::class);
return $businessLogic->run('arg1', 'arg2', '…');
}
}
In such a setup the execute
is kept to the strict minimum
and the operations themselves are handled by a separate class.
Also remember that the constructor is not called when
unserializing an object. If some operations need to be run upon
unserialization, implement a __
method instead.
Saving a task's state
The task's state is saved automatically at the start of its
execution. If you need to save a task's state at some point during
its execution, you can simply call the task's own save
method.
Providing additional fields for scheduler task
If the task should provide additional fields for configuration options in
the backend module, you need to implement a second class, extending
Abstract
.
This class needs to be configured in the scheduler task registration:
<?php
declare(strict_types=1);
use MyVendor\MyExtension\Tasks\MyTask;
defined('TYPO3') or die();
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][MyTask::class] = [
'extension' => 'scheduler',
'title' => 'Some title or LLL:EXT reference',
'description' => 'Some description or LLL:EXT reference',
];
And implemented to provide the desired fields and their validation:
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\Tasks;
use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider;
use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController;
use TYPO3\CMS\Scheduler\Task\AbstractTask;
final class MyTaskAdditionalFieldProvider extends AbstractAdditionalFieldProvider
{
public function getAdditionalFields(
array &$taskInfo,
$task, SchedulerModuleController $schedulerModule,
): array {
$fieldId = 'task_myextension_someField';
$fieldName = 'tx_scheduler[scheduler_myextension_someField]';
$fieldHtml = '<input class="form-select" name="' . $fieldName . '" id="' . $fieldId . '" />';
return [
$fieldId => [
'code' => $fieldHtml,
'label' => 'Label or LLL:EXT reference',
'type' => 'select',
]
];
}
public function validateAdditionalFields(
array &$submittedData,
SchedulerModuleController $schedulerModule,
): bool {
if ($submittedData === []) {
return false;
}
// do some other tests
return true;
}
public function saveAdditionalFields(
array $submittedData,
AbstractTask $task,
): void {
$task->setTaskParameters([
'someField' => $submittedData['scheduler_myextension_someField'] ?? '',
]);
}
}