Creating a custom scheduler task
Important
Changed in version 14.0
Custom scheduler tasks can be registered as TCA types in table
tx_
.
See also: Changelog Feature: #107526 - Custom TCA types for scheduler tasks.
Table of contents
See also
Symfony console commands can also be executed as scheduler task: See Create and use Symfony commands in TYPO3.
Implementation of a custom scheduler task
All scheduler task implementations must extend
\TYPO3\
.
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\Task;
use MyVendor\MyExtension\BusinessLogic;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Scheduler\Task\AbstractTask;
final class MyTask extends AbstractTask
{
/**
* MUST be implemented by all tasks
*/
public function execute(): bool
{
# Dependency injection cannot be used in scheduler tasks
$businessLogic = GeneralUtility::makeInstance(BusinessLogic::class);
return $businessLogic->run('arg1', 'arg2', '…');
}
public function getAdditionalInformation()
{
$this->getLanguageService()->sL('LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:myTaskInformation');
}
}
A custom task implementation must override the method execute
.
It is the main method that is called when a task is executed.
This method Should return true
on successful execution, false
on error.
Note
There is no error handling by default, errors and failures are expected to be handled and logged by the client implementation.
Method get
should be implemented to provide
additional information in the schedulers backend module.
Scheduler task implementations that provide additional fields
should implement additional methods, expecially get
.
Scheduler task registration and configuration
Deprecated since version 14.0
Registering tasks and additional field providers via
$GLOBALS
has
been deprecated.
Custom scheduler tasks can be registered via TCA overrides, for example in
EXT:
<?php
declare(strict_types=1);
use MyVendor\MyExtension\Task\MyTask;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
defined('TYPO3') or die();
if (isset($GLOBALS['TCA']['tx_scheduler_task'])) {
ExtensionManagementUtility::addRecordType(
[
'label' => 'My Custom Task',
'description' => 'Description of what this task does',
'value' => MyTask::class,
'icon' => 'my-custom-icon',
'group' => 'my_extension',
],
$GLOBALS['TCA']['tx_scheduler_task']['0']['showitem'],
[],
'',
'tx_scheduler_task'
);
}
Warning
If your extension overrides the TCA of the scheduler extension, it must be loaded after typo3/cms-scheduler , otherwise the configuration might take no effect.
Providing additional fields for scheduler task
Deprecated since version 14.0
Registering tasks and additional field providers via
$GLOBALS
has
been deprecated.
The
Additional
and
Abstract
have also
been deprecated.
Tasks in general and additional fields for tasks are registered via TCA instead.
See also: Migrating tasks with AdditionalFieldProviders to TCA registration
Additional fields for scheduler tasks are handled via FormEngine and can be configured via TCA.
If the task should provide additional fields for configuration options in
the backend module, you need to implement a second class, extending
Abstract
.
The task needs to be registered via TCA override:
<?php
declare(strict_types=1);
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use MyVendor\MyExtension\Task\MyTask;
defined('TYPO3') or die();
if (isset($GLOBALS['TCA']['tx_scheduler_task'])) {
// Add custom fields to the tx_scheduler_task table
ExtensionManagementUtility::addTCAcolumns(
'tx_scheduler_task',
[
'my_extension_field' => [
'label' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:field.label',
'config' => [
'type' => 'input',
'size' => 30,
'required' => true,
'eval' => 'trim',
'placeholder' => 'Enter value here...',
],
],
'my_extension_email_list' => [
'label' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:emailList.label',
'config' => [
'type' => 'text',
'rows' => 3,
'required' => true,
'placeholder' => 'admin@example.com',
],
],
]
);
// Register the task type
ExtensionManagementUtility::addRecordType(
[
'label' => 'Some title or LLL:EXT reference',
'description' => 'Some description or LLL:EXT reference',
'value' => MyTask::class,
'icon' => 'mimetypes-x-tx_scheduler_task_group',
'group' => 'my_extension',
],
'
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general,
tasktype,
task_group,
description,
my_extension_field,
my_extension_email_list,
--div--;LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:scheduler.form.palettes.timing,
execution_details,
nextexecution,
--palette--;;lastexecution,
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access,
disable,
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:extended,',
[],
'',
'tx_scheduler_task'
);
}
And implemented the following methods in your scheduler task if needed:
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\Task;
use MyVendor\MyExtension\BusinessLogic;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Scheduler\Task\AbstractTask;
final class MyTask extends AbstractTask
{
protected string $myField = '';
protected string $emailList = '';
public function execute(): bool
{
# Dependency injection cannot be used in scheduler tasks
$businessLogic = GeneralUtility::makeInstance(BusinessLogic::class);
return $businessLogic->run($this->myField, $this->emailList, '…');
}
/**
* Set field values from associative array.
*
* @param array $parameters Values from TCA fields
*/
public function setTaskParameters(array $parameters): void
{
$this->myField = $parameters['my_extension_field'] ?? '';
$this->emailList = $parameters['my_extension_email_list'] ?? '';
}
/**
* Validate task parameters.
* Only implement this method for validation that cannot be handled by FormEngine.
* Basic validation like 'required' should be done via TCA 'eval' configuration.
*/
public function validateTaskParameters(array $parameters): bool
{
$isValid = true;
// Example: Custom email validation (beyond basic 'required' check)
$emailList = $parameters['my_extension_email_list'] ?? '';
if (!empty($emailList)) {
$emails = GeneralUtility::trimExplode(',', $emailList, true);
foreach ($emails as $email) {
if (!GeneralUtility::validEmail($email)) {
GeneralUtility::makeInstance(FlashMessageService::class)
->getMessageQueueByIdentifier()
->addMessage(
GeneralUtility::makeInstance(
FlashMessage::class,
'Invalid email address: ' . $email,
'',
ContextualFeedbackSeverity::ERROR
)
);
$isValid = false;
}
}
}
return $isValid;
}
public function getAdditionalInformation(): string
{
return sprintf(
'Field: %s, Emails: %s',
$this->myField,
$this->emailList
);
}
}
Note
Method get
should be implemented when
migrating tasks
For native TCA tasks, this method is typically no longer needed in custom tasks after the migration has been done, since field values are then stored directly in database columns.
See also
There are additional examples in described in the Changelog Feature: #107526 - Custom TCA types for scheduler tasks.