Scheduler tasks should now be registered as native task types using TCA.
This provides a more integrated and maintainable approach to task configuration.
Example migration: Scheduler task with additional fields suppporting TYPO3 13 and 14
Remove the registration from ext_localconf.php once TYPO3 13 support is
dropped:
packages/my_extension/ext_localconf.php
<?php
declare(strict_types=1);
use MyVendor\MyExtension\Task\MyTask;
if ((new \TYPO3\CMS\Core\Information\Typo3Version())->getMajorVersion() < 14) {
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][MyTask::class] = [
'extension' => 'my_extension',
'title' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:myTask.title',
'description' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:myTask.description',
'additionalFields' => \MyVendor\MyExtension\Task\MyTaskAdditionalFieldProvider::class,
];
}
And also remove the
MyTaskAdditionalFieldProvider class once
TYPO3 13 support is dropped.
Create a TCA override file in Configuration/TCA/Overrides/scheduler_my_task_type.php:
EXT:my_extension/Configuration/TCA/Overrides/scheduler_my_task_type.php
<?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'])) {
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',
],
],
]
);
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',
'iconOverlay' => 'content-clock',
'group' => 'my_extension',
],
'
--div--;core.form.tabs: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--;core.form.tabs:access,
disable,
--div--;core.form.tabs:extended,',
[],
'',
'tx_scheduler_task'
);
}
Update your (existing) task class to implement the new methods:
packages/my_extension/Classes/MyTask.php
<?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
{
$businessLogic = GeneralUtility::makeInstance(BusinessLogic::class);
return $businessLogic->run($this->myField, $this->emailList, '…');
}
public function getTaskParameters(): array
{
return [
'my_extension_field' => $this->myField,
'my_extension_email_list' => $this->emailList,
];
}
public function setTaskParameters(array $parameters): void
{
$this->myField = $parameters['myField'] ?? $parameters['my_extension_field'] ?? '';
$this->emailList = $parameters['emailList'] ?? $parameters['my_extension_email_list'] ?? '';
}
public function validateTaskParameters(array $parameters): bool
{
$isValid = true;
$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
{
$info = [];
if ($this->myField !== '') {
$info[] = 'Field: ' . $this->myField;
}
if ($this->emailList !== '') {
$info[] = 'Emails: ' . $this->emailList;
}
return implode(', ', $info);
}
public function setMyField(string $myField): void
{
$this->myField = $myField;
}
public function setEmailList(string $emailList): void
{
$this->emailList = $emailList;
}
}
The new TCA-based approach uses three key methods for parameter handling:
- getTaskParameters(): array
-
This method is already implemented in AbstractTask to handle task class
properties automatically, but can be overridden in task classes for custom
behavior.
The method is primarily used:
- For migration from old serialized task format to new TCA structure
- For non-native (deprecated) task types to store their values in the legacy
parameters field
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.
- setTaskParameters(array $parameters): void
-
Sets field values from an associative array. This method handles:
- Migration from old AdditionalFieldProvider field names to new TCA field names
- Loading saved task configurations when editing or executing tasks
- Parameter mapping during task creation and updates
- The method should always be implemented, especially for native tasks
The migration pattern is:
$this->myField = $parameters['oldName'] ?? $parameters['new_tca_field_name'] ?? '';
- validateTaskParameters(array $parameters): bool
-
Optional method. Only implement this for validation that cannot be handled by FormEngine.
- Basic validation (required, trim, etc.) should be done via TCA configuration (
required property and eval options)
- Use this method for complex business logic validation (e.g., email format validation, external API checks)
- Return
false and add FlashMessage for validation errors
- FormEngine automatically handles standard TCA validation rules
For a complete working example, see
\TYPO3\CMS\Reports\Task\SystemStatusUpdateTask
and its corresponding TCA configuration in
EXT:reports/Configuration/TCA/Overrides/scheduler_system_status_update_task.php.