Preparation

Let’s say we have the store method which creates a photo.

We also have an intention to protect the route by Throttle middleware.

  1. Define a route (Configuration/Routes.yml)

    demo_photos-store:
      path:         api/demo/photos
      controller:   Vendor\Demo\Controller\PhotoApiController::store
      methods:      POST
      format:       json
      requirements:
        url:
      defaults:
        plugin:     PhotoApi
        url:
      options:
        middleware:
          - auth
          - LMS\Routes\Middleware\Api\Throttle:10,1
    
  2. Register Plugin namespace (ext_localconf.php)

    use Vendor\Demo\Controller\PhotoApiController;
    
    \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
        'Demo',
        'PhotoApi',
        [
            PhotoApiController::class => 'store'
        ],
        [
            PhotoApiController::class => 'store'
        ]
    );
    

    Tip

    Plugin registration in Configuration/TCA/Overrides/tt_content.php is optional.

  3. Create photo table (ext_tables.sql)

    CREATE TABLE tx_demo_domain_model_photo (
      url varchar(128) DEFAULT '' NOT NULL
    );
    
  4. Create TCA (Configuration/TCA/tx_demo_domain_model_photo.php)

    <?php
        declare(strict_types = 1);
    
        return [
            'ctrl' => [
                'title' => 'Photo',
                'label' => 'url',
                'crdate' => 'crdate',
                'delete' => 'deleted',
                'searchFields' => 'url'
            ],
            'types' => [
                '1' => [
                    'showitem' => '
                        url
                    '
                ]
            ],
            'columns' => [
                'url' => [
                    'exclude' => true,
                    'label' => 'Url',
                    'config' => [
                        'type' => 'input',
                        'eval' => 'trim'
                    ]
                ]
            ]
        ];
    
  5. Create model (Classes/Domain/Model/Photo.php)

    <?php
        declare(strict_types = 1);
    
        namespace LMS\Demo\Domain\Model;
    
        class Photo extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
        {
            protected string $url = '';
    
            public function setUrl(string $url): void
            {
                $this->url = $url;
            }
    
            public function getUrl(): string
            {
                return $this->url;
            }
        }
    
  6. Create a repository (Classes/Domain/Repository/PhotoRepository.php)

    <?php
        declare(strict_types = 1);
    
        namespace LMS\Demo\Domain\Repository;
    
        class PhotoRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
        {
            // ...
        }
    
  7. Create Controller (Classes/Controller/PhotoApiController.php)

    <?php
        declare(strict_types = 1);
    
        namespace LMS\Demo\Controller;
    
        use LMS\Demo\Domain\Model\Photo;
        use Psr\Http\Message\ResponseInterface;
    
        class PhotoApiController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
        {
            public function storeAction(string $url): ResponseInterface
            {
                $created = (bool)Photo::create(compact('url'));
    
                return $this->jsonResponse(
                    (string)json_encode(
                        compact('created')
                    )
                );
            }
        }
    

Tip

Steps 3, 4, 5, 6 are required only if you deal with a model.