Common tasks in Extbase
Note
This page is a work in progress. Content will be added as part of the Extbase documentation rewrite for TYPO3 v14.
This page answers the "how do I…" questions that come up repeatedly when building or maintaining Extbase extensions. Each entry states the goal, gives a short direct answer, and links to the full explanation.
If you know what you want to achieve but are not sure which chapter covers it, start here.
On this page
Add a field to a third-party extension's model
Goal: A third-party extension (for example georgringer/news ) has a model you want to extend with an extra database field — without forking the extension.
Short answer: You need three things working together: a TCA override that adds the column to the table, a class mapping override in your own extension that tells Extbase to use your subclass instead of the original, and your subclass extending the third-party model with the new property and getter/setter. No changes to the original extension required.
See also
Table and field mapping for the
Configuration/Extbase/Persistence/Classes.php mapping file.
Query records with custom conditions
Goal:
find and
find are not enough — you need
records filtered by date, a relation, or a combination of conditions.
Short answer: Call
$this->create in your repository method,
build constraints with
$query->matching, and return
$query->execute. For anything the Extbase query API cannot express
(aggregates, complex joins), drop down to
Connection and raw DBAL.
See also
- Custom query methods for the basic knowledge.
- Persistence queries for the full query API
- including ordering, limits, and storagePid settings.
Use a repository in a controller
Goal: Make a repository available inside a controller action without
using
General.
Short answer: Declare the repository as a constructor parameter with
protected readonly. TYPO3's DI container injects it automatically — no
annotation, no factory call needed.
class BlogPostController extends ActionController
{
public function __construct(
protected readonly BlogPostRepository $blogPostRepository,
) {}
}
See also
- Dependency injection.
- Extbase controller actions for the full controller setup.
Set a default sort order for all repository queries
Goal: Every call to
find or
find on a repository
should return records sorted by a specific property, without having to specify
ordering in every call.
Short answer: Set the
$default class property on your
repository. It applies automatically to all queries from that repository.
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
use TYPO3\CMS\Extbase\Persistence\Repository;
class BlogPostRepository extends Repository
{
protected $defaultOrderings = [
'publishDate' => QueryInterface::ORDER_ASCENDING,
];
}
See also
Load a relation only when needed
Goal: A model has a related object or collection that is expensive to load and not always needed — for example, the comments on an event in a list view. You want to avoid loading them unless the template actually uses them.
Short answer: Add
# to the relation property. Extbase defers
the database query until the property is first accessed. For 1:1 relations,
the getter must also handle the
Lazy intermediate.
See also
- Relations and ObjectStorage for the full pattern including the proxy-aware getter.
- #[Lazy] for the attribute reference.
- Persistence relations for the N+1 query trap this prevents.
Use a native PHP enum as a model property
Goal: A model property should hold one of a fixed set of values — for
example a status or salutation — and you want to use a native PHP 8.1 backed
enum (an enum with an underlying
string or
int value that can be
stored in the database) rather than a plain string or integer.
Short answer: Declare the property with the enum type and a default case.
Extbase's built-in
Enum handles the conversion between the
stored backing value and the enum instance automatically. No extra
configuration needed.
See also
Add a computed property that is never stored in the database
Goal: A model needs a property that holds a computed or temporary value — for example a formatted label derived from other properties — that should never be written to the database.
Short answer: Add
# to the property. Extbase skips it
entirely during read and write operations.
See also