---
title: "Common tasks in Extbase"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:extbase-appendix-tasks@main"
source: "ExtensionArchitecture/Extbase/Appendix/CommonTasks.rst"
rendered: "2026-09-24T12:36:55+00:00"
---

# Common tasks in Extbase {#extbase-appendix-tasks}

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](https://docs.typo3.org/permalink/t3coreapi:add-a-field-to-a-third-party-extension-s-model@main)
-   [Query records with custom conditions](https://docs.typo3.org/permalink/t3coreapi:query-records-with-custom-conditions@main)
-   [Use a repository in a controller](https://docs.typo3.org/permalink/t3coreapi:use-a-repository-in-a-controller@main)
-   [Set a default sort order for all repository queries](https://docs.typo3.org/permalink/t3coreapi:set-a-default-sort-order-for-all-repository-queries@main)
-   [Load a relation only when needed](https://docs.typo3.org/permalink/t3coreapi:load-a-relation-only-when-needed@main)
-   [Delete related objects when the parent is deleted](https://docs.typo3.org/permalink/t3coreapi:delete-related-objects-when-the-parent-is-deleted@main)
-   [Use a native PHP enum as a model property](https://docs.typo3.org/permalink/t3coreapi:use-a-native-php-enum-as-a-model-property@main)
-   [Add a computed property that is never stored in the database](https://docs.typo3.org/permalink/t3coreapi:add-a-computed-property-that-is-never-stored-in-the-database@main)
-   [Let editors set plugin settings in a content block FlexForm](https://docs.typo3.org/permalink/t3coreapi:let-editors-set-plugin-settings-in-a-content-block-flexform@main)

## Add a field to a third-party extension's model {#extbase-persistence-custom-model}

**Goal:** A third-party extension (for example [`georgringer/news`](https://packagist.org/packages/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.

**Extension load order matters here.** The class mapping in
[`Configuration/Extbase/Persistence/Classes.php`](../../FileStructure/Configuration/Extbase/Persistence/Index.md#file-extension-configuration-extbase-persistence-classes-php) and any DI alias
(used by tools like [`friendsoftypo3/extension-builder`](https://packagist.org/packages/friendsoftypo3/extension-builder) or
[`evoweb/extender`](https://packagist.org/packages/evoweb/extender)) must be processed after the original extension
registers its own mapping. Declare the third-party extension as a dependency
in your `composer.json` to guarantee this:

**EXT:my_extension/composer.json (excerpt)**

```json
{
  "require": {
    "georgringer/news": "^11.0"
  }
}

```

Without this, the load order is undefined and your class mapping may be
silently overwritten by the original.

> [!NOTE]
> **See also**
>
> [Table and field mapping](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-model-mapping@main) for the
> [`Configuration/Extbase/Persistence/Classes.php`](../../FileStructure/Configuration/Extbase/Persistence/Index.md#file-extension-configuration-extbase-persistence-classes-php) mapping file.

## Query records with custom conditions {#extbase-appendix-tasks-custom-query}

**Goal:** `findAll()` and `findBy()` are not enough — you need
records filtered by date, a relation, or a combination of conditions.

**Short answer:** Call `$this->createQuery()` 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 `\TYPO3\CMS\Core\Database\ConnectionPool` and raw DBAL.

> [!NOTE]
> **See also**
>
> -   [Custom query methods](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-repository-custom-queries@main) for the basic knowledge.
> -   -   **[Persistence queries](https://docs.typo3.org/permalink/t3coreapi:extbase-persistence-queries) for the full query API**
>
>         including ordering, limits, and storagePid settings.

## Use a repository in a controller {#extbase-appendix-tasks-inject-repository}

**Goal:** Make a repository available inside a controller action without
using `GeneralUtility::makeInstance()`.

**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.

**EXT:my_extension/Classes/Controller/BlogPostController.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use MyVendor\MyExtension\Domain\Repository\BlogPostRepository;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class BlogPostController extends ActionController
{
  public function __construct(
    protected readonly BlogPostRepository $blogPostRepository,
  ) {}
}

```

> [!NOTE]
> **See also**
>
> -   [Dependency injection](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-repository-di@main).
> -   [Extbase controller actions](https://docs.typo3.org/permalink/t3coreapi:extbase-controller-action@main) for the full controller setup.

## Set a default sort order for all repository queries {#extbase-appendix-tasks-default-ordering}

**Goal:** Every call to `findAll()` or `findBy()` on a repository
should return records sorted by a specific property, without having to specify
ordering in every call.

**Short answer:** Set the `$defaultOrderings` class property on your
repository. It applies automatically to all queries from that repository.

**EXT:my_extension/Classes/Domain/Repository/BlogPostRepository.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Domain\Repository;

use TYPO3\CMS\Extbase\Persistence\QueryInterface;
use TYPO3\CMS\Extbase\Persistence\Repository;

class BlogPostRepository extends Repository
{
  protected $defaultOrderings = [
    'publishDate' => QueryInterface::ORDER_ASCENDING,
  ];
}

```

> [!NOTE]
> **See also**
>
> [Ordering](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-repository-ordering@main).

## Load a relation only when needed {#extbase-appendix-tasks-lazy-relation}

**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 `#[Lazy]` to the relation property. Extbase defers
the database query until the property is first accessed. For a relation to a
single object, the getter must also handle the `LazyLoadingProxy` intermediate.

> [!NOTE]
> **See also**
>
> -   [Relations and ObjectStorage](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-model-relations@main) for the full pattern
>     including the proxy-aware getter.
> -   [#\[Lazy\]](https://docs.typo3.org/permalink/t3coreapi:extbase-appendix-attributes-lazy@main) for the attribute
>     reference.
> -   [Persistence relations](https://docs.typo3.org/permalink/t3coreapi:extbase-persistence-relations@main) for the N+1 query trap
>     this prevents.

## Delete related objects when the parent is deleted {#extbase-appendix-tasks-delete-cascade}

**Goal:** When an event is deleted, its related comment records should be
deleted automatically rather than left as orphans in the database.

**Short answer:** Add `#[Cascade('remove')]` to the relation property on
the owning model. Extbase will delete the related objects through their
repository when the parent is deleted.

> [!NOTE]
> **See also**
>
> -   [Relations and ObjectStorage](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-model-relations@main).
> -   [#\[Cascade\]](https://docs.typo3.org/permalink/t3coreapi:extbase-appendix-attributes-cascade@main).

## Use a native PHP enum as a model property {#extbase-appendix-tasks-enum-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 `\TYPO3\CMS\Extbase\Property\TypeConverter\EnumConverter` handles the conversion between the
stored backing value and the enum instance automatically. No extra
configuration needed.

> [!NOTE]
> **See also**
>
> [Enum properties](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-model-enums@main).

## Add a computed property that is never stored in the database {#extbase-appendix-tasks-non-persisted-property}

**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 `#[Transient]` to the property. Extbase skips it
entirely during read and write operations.

> [!NOTE]
> **See also**
>
> -   [Non-persisted properties](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-model-transient@main).
> -   [#\[Transient\]](https://docs.typo3.org/permalink/t3coreapi:extbase-appendix-attributes-transient@main).

## Let editors set plugin settings in a content block FlexForm {#extbase-appendix-tasks-contentblock-settings}

**Goal:** Expose a plugin setting (for example "items per page") as an editable
field in a content element, so that an editor can change it without having to
write a FlexForm data structure by hand.

**Short answer:** When you register an Extbase plugin as a Content Block that
is rendered through an [EXTBASEPLUGIN](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/ContentObjects/Extbaseplugin/Index.html#cobj-extbaseplugin) and reuses
the `pi_flexform` field, a FlexForm field with an identifier like
`settings.<name>` will be converted into `$this->settings['<name>']` —
exactly like a TypoScript setting. The reusable `pages` and
`recursive` fields likewise feed `persistence.storagePid` and
`persistence.recursive`. This is a little-known mechanism and is becoming
more relevant as Content Block technology moves into the Core.

> [!NOTE]
> **See also**
>
> -   [Feeding settings from a Content Block FlexForm](https://docs.typo3.org/permalink/t3coreapi:extbase-configuration-typoscript-settings-contentblocks@main)
>     for the full example and how the wiring works.
> -   [Create Extbase plugins (Content Blocks documentation)](https://docs.typo3.org/p/friendsoftypo3/content-blocks/main/en-us/Guides/CreateExtbasePlugin/Index.html#create-extbase-plugin).
