Repository¶
All Extbase repositories inherit from
\TYPO3\
.
A repository is always responsible for precisely one type of domain object.
The naming of the repositories is important:
If the domain object is, for example, Blog (with full name
\Friends
),
then the corresponding repository is named BlogRepository (with the full name
\Friends
).
The \TYPO3\
already offers a large
number of useful functions. Therefore, in simple classes that extend the
Repository
class and leaving the class empty otherwise is sufficient.
The Blog
sets some default orderings and is otherwise empty:
class BlogRepository extends Repository
{
}
Table of contents
Magic find methods¶
The Repository
class creates "magic" methods to find by attributes of
model.
find
By [Property] - Finds all objects with the provided property.
find
One By [Property] - Returns the first object found with the provided property.
count
By [Property] - Counts all objects with the provided property.
If necessary, these methods can also be overridden by implementing them in the concrete repository.
Custom find methods¶
Custom find methods can be implemented. They can be used, for example, to filter by multiple properties or apply a different sorting. They can also be used for complex queries.
Attention
As Extbase repositories turn the results into objects, querying large amounts of data is resource-intensive.
Example:
The Post
of the EXT:blog example extension implements
several custom find methods, two of them are shown below:
use FriendsOfTYPO3\BlogExample\Domain\Model\Blog;
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
class PostRepository extends Repository
{
public function findByTagAndBlog(
string $tag,
Blog $blog
): QueryResultInterface {
$query = $this->createQuery();
return $query
->matching(
$query->logicalAnd(
$query->equals('blog', $blog),
$query->equals('tags.name', $tag)
)
)
->execute();
}
public function findAllSortedByCategory(array $uids): QueryResultInterface
{
$q = $this->createQuery();
$q->matching($q->in('uid', $uids));
$q->setOrderings([
'categories.title' => QueryInterface::ORDER_ASCENDING,
'uid' => QueryInterface::ORDER_ASCENDING,
]);
return $q->execute();
}
}
Query settings¶
If the query settings should be used for all methods in the repository,
they should be set in the method initialize
method.
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface;
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
class CommentRepository extends Repository
{
public function initializeObject()
{
/** @var QuerySettingsInterface $querySettings */
$querySettings = GeneralUtility::makeInstance(Typo3QuerySettings::class);
// Show comments from all pages
$querySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($querySettings);
}
}
Attention
Depending on the query settings, hidden or even deleted objects can become visible. This might cause sensitive information to be disclosed. Use with care.
Attention
Since introduction of dependency injection via Services.yaml with TYPO3 v10 you may have to flush cache in maintenance module of TYPO3 to register that method to be loaded while instanciating that object.
If you only want to change the query settings for a specific method, they can be set in the method itself:
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
class CommentRepository extends Repository
{
public function findAllIgnoreEnableFields(): QueryResultInterface|array
{
$query = $this->createQuery();
$query->getQuerySettings()->setIgnoreEnableFields(true);
return $query->execute();
}
}
Repository API¶
- class Repository ¶
-
- Fully qualified name
-
\TYPO3\
CMS\ Extbase\ Persistence\ Repository
The base repository - will usually be extended by a more concrete repository.
- injectPersistenceManager ( ) ¶
- add ( object $object) ¶
-
Adds an object to this repository
- param object $object
-
The object to add
- remove ( object $object) ¶
-
Removes an object from this repository.
- param object $object
-
The object to remove
- update ( object $modifiedObject) ¶
-
Replaces an existing object with the same identifier by the given object
- param object $modifiedObject
-
The modified object
- findAll ( ) ¶
-
Returns all objects of this repository.
- countAll ( ) ¶
-
Returns the total number objects of this repository.
- removeAll ( ) ¶
-
Removes all objects of this repository as if remove() was called for all of them.
- findByUid ( int $uid) ¶
-
Finds an object matching the given identifier.
- param int $uid
-
The identifier of the object to find
- findByIdentifier ( mixed $identifier) ¶
-
Finds an object matching the given identifier.
- param mixed $identifier
-
The identifier of the object to find
- setDefaultOrderings ( array<non-empty-string, QueryInterface::ORDER_*>) ¶
-
Sets the property names to order the result by per default.
Expected like this: array( 'foo' => TYPO3CMSExtbasePersistenceQueryInterface::ORDER_ASCENDING, 'bar' => TYPO3CMSExtbasePersistenceQueryInterface::ORDER_DESCENDING )
:param array<non-empty-string, QueryInterface::ORDER_*>: $defaultOrderings The property names to order by
- setDefaultQuerySettings ( TYPO3\\CMS\\Extbase\\Persistence\\Generic\\QuerySettingsInterface defaultQuerySettings) ¶
-
Sets the default query settings to be used in this repository.
A typical use case is an initializeObject() method that creates a QuerySettingsInterface object, configures it and sets it to be used for all queries created by the repository.
Warning: Using this setter fully overrides native query settings created by QueryFactory->create(). This especially means that storagePid settings from configuration are not applied anymore, if not explicitly set. Make sure to apply these to your own QuerySettingsInterface object if needed, when using this method.
- param TYPO3\\CMS\\Extbase\\Persistence\\Generic\\QuerySettingsInterface $defaultQuerySettings
-
the defaultQuerySettings
- createQuery ( ) ¶
-
Returns a query for objects of this repository
- __call ( non-empty-string $methodName, array<int, mixed> $arguments) ¶
-
Dispatches magic methods (findBy[Property]())
- param non-empty-string $methodName
-
The name of the magic method
- param array<int,mixed> $arguments
-
The arguments of the magic method
Typo3QuerySettings and localization¶
Extbase renders the translated records in the same way as TypoScript rendering.
Changed in version 11.0
Setting Typo3Query
was deprecated and does
not influence how Extbase queries records.
Typo3QuerySettings->languageOverlayMode
= true¶
Setting Typo3Query
to true
will fetch records from the default language and overlay them
with translated values. If a record is hidden in the default language,
it will not be displayed in the translation. Also, records without translation
parents will not be shown.
For relations, Extbase reads relations from a translated record
(so it is not possible to inherit a field value from translation source)
and then passes the related records through
$page
.
For example: when you have a translated tt_
record with a
FAL relation, Extbase will show only those sys_
records which are connected to the translated record (not caring
whether some of these files have l10n_
set).
Typo3QuerySettings->languageOverlayMode
= false¶
Setting Typo3Query
to false
will fetch aggregate root records from a given language only.
Extbase will follow relations (child records) as they are, without checking
their sys_
fields, and then pass these
records through $page
.
This way, the aggregate root record's sorting and visibility do not depend on the default language records.
Moreover, the relations of a record, which are often stored using default language uids are translated in the final result set (so overlay happens).
Example: Given a translated tt_
record having a relation to two
categories (in the mm table the translated tt_
record is connected
to the category uid in the default language), and one of the categories is translated.
Extbase will return a tt_
model with both categories.
If you want just the translated category to be shown, remove the
relation in the translated tt_
record in the TYPO3 backend.
Setting the Typo3QuerySettings->languageOverlayMode
¶
Note
By default, Typo3Query
uses the
site language configuration.
You need to change Typo3Query
manually only, if your Extbase
code should behave differently to tt_
rendering.
Setting set
on a query influences only
fetching of the aggregate root. Relations are always fetched with
set
.
When querying data in translated language, and having
set
, the relations (child objects) are overlaid
even if the aggregate root is not translated.
$repository->findByUid()
and language overlay modes¶
$repository->find
internally sets respect
.
Therefore it behaves differently than a regular query by uid
.
Note
$query->matching
and
$repository->find
behave different in some language
scenarios:
The regular query will return null
, if passed uid
does not
match the language set in the $query
method.
The bottom line is you can use $repository->find
with the translated
record uid to get the translated content, independently of the language set in the
global context.
Debugging an Extbase query¶
When using complex queries in Extbase repositories it sometimes comes handy to debug them using the Extbase debug utilities.
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\Domain\Repository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\CMS\Extbase\Persistence\Repository;
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
final class MyRepository extends Repository
{
public function findBySomething(string $something, bool $debugOn = false): QueryResultInterface
{
$query = $this->createQuery();
$query = $query->matching($query->equals('some_field', $something));
if ($debugOn) {
$typo3DbQueryParser = GeneralUtility::makeInstance(Typo3DbQueryParser::class);
$queryBuilder = $typo3DbQueryParser->convertQueryToDoctrineQueryBuilder($query);
DebuggerUtility::var_dump($queryBuilder->getSQL());
DebuggerUtility::var_dump($queryBuilder->getParameters());
}
return $query->execute();
}
}
Please note that \TYPO3\
is marked as @internal
and subject to unannounced changes.