9. Developer corner

Target group: Developers

Modify data sets on synchronisation

The records that are synchronised with the table types Simple synchronisation or Synchronisation in custom table can be adapted to the needs of the website or rejected during synchronisation. This can be useful if only records with a date column are used where the date is relevant in the future. Another scenario would be to match the content of one column with the content of another table.


A PSR-14 event listener can be used for this case. In the following example, a record is rejected under a certain condition and a static string is added to each “position” column value.

  1. Create the event listener

    namespace MyVendor\MyExtension\EventListener;
    use Brotkrueml\JobRouterData\Event\ModifyDatasetOnSynchronisationEvent;
    final class AdjustJobsDataset
       public function __invoke(ModifyDatasetOnSynchronisationEvent $event): void
          // Only the table with the handle "jobs" should be considered
          if ($event->getTable()->handle !== 'jobs') {
          $dataset = $event->getDataset();
          if ($dataset['jrid'] === 3) {
             // For some reason we don't like jrid = 3, so we reject it
             // and it doesn't get synchronised
          $dataset['POSITION'] .= ' (approved by me™)';
  2. Register your event listener

             - name: event.listener
               identifier: 'adjustJobsDataset'

Transfer data sets to a JobRouter installation

Sometimes it is necessary to transfer data sets from TYPO3 to a JobRouter® installation. An API and a transmit command are available for this use case.

Data sets are transferred asynchronously, since a JobRouter® installation may be unavailable or in maintenance mode and to avoid long page loads. Let’s take a look at the flow:

Transferring data sets

Transferring data sets

As you can see from the diagram, you can prepare multiple data sets. The different data sets can be transmitted to different JobRouter® installations – depending on the configuration of the table link in the Data module.

Preparing the data sets

If you want to transfer data sets programmatically to a JobRouter® installation, you can use the Preparer class within TYPO3, e.g. in an Extbase controller:


namespace MyVendor\MyExtension\Controller;

use Brotkrueml\JobRouterData\Exception\PrepareException;
use Brotkrueml\JobRouterData\Transfer\Preparer;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use Psr\Http\Message\ResponseInterface;

final class MyController extends ActionController
   public function __construct(
      private readonly Preparer $preparer,
   ) {

   public function myAction(): ResponseInterface
      // ... some other code

      try {
             // The table link uid
            // Some descriptive identifier for the source of the dataset
            'some identifier',
            // Your JSON encoded data set
            '{"your": "data", "to": "transfer"}'
      } catch (PrepareException $e) {
         // In some rare cases an exception may be thrown

      // ... some other code

The transmit command must be activated with a cron job to periodically transmit the data sets to the JobRouter® installation(s).


It is not advised to insert the data sets directly into the transfer table, as the table schema can be changed in future versions. Use the API described above.

Using the JobDataRepository

The \Brotkrueml\JobRouterData\Domain\Repository\JobRouter\JobDataRepository provides methods to access the JobData REST API in TYPO3, e.g. in a command or a controller.

The following methods are available:

add(string $tableHandle, array $dataset): array

Adds a dataset to a JobData table and returns the stored dataset.

remove(string $tableHandle, int ...$jrid): void

Removes one or more datasets from a JobData table.

update(string $tableHandle, int $jrid, array $dataset): array

Updates the dataset with the given jrid for a JobData table and returns the stored dataset.

findAll(string $tableHandle): array

Returns all datasets of the JobData table;

findByJrId(string $tableHandle, int $jrid): array

Returns the dataset for the given jrid of a JobData table.



namespace MyVendor\MyExtension\Command;

final class MyCommand extends Command
   public function __construct(
      private readonly JobDataRepository $jobDataRepository,
   ) {

   protected function execute(InputInterface $input, OutputInterface $output): int
      $datasets = $this->jobDataRepository->findAll('some_handle');

      // ... your logic

      return 0;

Customising the formatting of a table column in the content element

The extension comes with four formatters that are used when rendering the column content in the content element:

  • DateFormatter

  • DateTimeFormatter

  • DecimalFormatter

  • IntegerFormatter

These are implemented as PSR-14 event listeners and are located in the Classes/EventListener folder of this extension. They receive a Brotkrueml\JobRouterData\Event\ModifyColumnContentEvent event with the following methods:


The table entity.

Return value

The entity class of a table (Brotkrueml\JobRouterData\Domain\Entity\Table).


The column entity.

Return value

The entity class of a column (Brotkrueml\JobRouterData\Domain\Entity\Column).


The content of a table cell.

Return value

The value of the content (types: float, int, string).


Set a content for a table cell.


float|int|string $content The formatted content of a table cell.


The locale of the website page.

Return value

The locale (for example, “de-DE” or “en-US”) is retrieved from the configured site language field locale.


Using TYPO3 v11, the locale might be something like “de_DE.utf8” or “en_US”. With the introduction of the Locale class in TYPO3 v12 the locale follows the IETF RFC 5646 language tag standard.

Custom formatters

As a PSR-14 event is dispatched for formatting a cell content, a custom event listener can be used. Have a look into the existing formatter event listeners.


Only the first suitable formatter is used. When the content is adjusted with the setContent() method of the event the propagation of other events is stopped. So be sure to add your custom event listener before existing ones.