Repository

A basic repository can be quite a short class. The shortest possible repository is an empty class inheriting from \TYPO3\CMS\Extbase\Persistence\Repository :

EXT:tea/Classes/Domain/Repository/Product/TeaRepository.php (simplified)
<?php

declare(strict_types=1);

namespace TTN\Tea\Domain\Repository\Product;

use TYPO3\CMS\Extbase\Persistence\Repository;

/**
 * @extends Repository<Tea>
 */
class TeaRepository extends Repository {}
Copied!

The model the repository should deliver is derived from the namespace and name of the repository. A repository with the fully qualified name \TTN\Tea\Domain\Repository\Product\TeaRepository therefore delivers models with the fully qualified name \TTN\Tea\Domain\Model\Product\Tea without further configuration.

A special class comment (not mandatory), @extends Repository<Tea> tells your IDE and static analytic tools like PHPStan that the find-by methods of this repository return objects of type \Tea.

The repository in the tea extension looks like this:

EXT:tea/Classes/Domain/Repository/Product/TeaRepository.php
<?php

declare(strict_types=1);

namespace TTN\Tea\Domain\Repository\Product;

use TYPO3\CMS\Extbase\Persistence\Repository;

/**
 * @extends Repository<Tea>
 */
class TeaRepository extends Repository {}
Copied!

We override the protected parameter $defaultOrderings here. This parameter is also defined in the parent class \TYPO3\CMS\Extbase\Persistence\Repository and used here when querying the database.

Then we also add a custom find-by method. See also chapter "Repository" in the Extbase reference.

Using the repository

The \TeaRepository can now be used in a controller or another class, for example a service.

Require it via Dependency Injection in the constructor:

EXT:tea/Classes/Controller/TeaController.php
<?php

declare(strict_types=1);

namespace TTN\Tea\Controller;

use Psr\Http\Message\ResponseInterface;
use TTN\Tea\Domain\Repository\Product\TeaRepository;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

final class TeaController extends ActionController
{
    public function __construct(private TeaRepository $teaRepository) {}

    public function indexAction(): ResponseInterface
    {
        $this->view->assign('teas', $this->teaRepository->findAll());
        return $this->htmlResponse();
    }
}
Copied!

The method $this->teaRepository->findAll() that is called here is defined in the parent class \TYPO3\CMS\Extbase\Persistence\Repository .