---
title: "Annotations"
manual: "TYPO3 Explained"
version: "12.4"
permalink: "https://docs.typo3.org/permalink/t3coreapi:extbase-annotations@12.4"
source: "ExtensionArchitecture/Extbase/Reference/Annotations.rst"
rendered: "2026-10-21T15:29:37+00:00"
---

> [!WARNING]
> **Attention**
>
> TYPO3 v12 has reached end-of-life as of April 30th 2026 and
> is no longer being maintained. Use the version switcher on the top
> left of this page to select documentation for a supported version of TYPO3.
>
> Need more time before upgrading?
> You can purchase Extended Long Term Support (ELTS) for TYPO3 v12 here:
> [TYPO3 ELTS](https://typo3.com/services/extended-support-elts).

# Annotations {#extbase-annotations}

All available annotations for Extbase delivered by TYPO3 Core are placed within
the namespace `\TYPO3\CMS\Extbase\Annotation`.

<!-- TODO: no Markdown rendering for "versionchanged" -->

Starting with TYPO3 v12.0 Extbase annotations can be supplied as
PHP 8 native attributes.

> [!WARNING]
> **Attention**
>
> Even if you use PHP 8.0 with TYPO3 v11 LTS native attributes do not work below
> TYPO3 v12.0. To stay compatible with both TYPO3 v11 and v12, continue to use
> the Extbase annotations as doc-block comments.

Example in [EXT:blog_example](https://github.com/typo3-documentation/blog_example)
for the annotation `Lazy`:

**EXT:blog_example/Classes/Domain/Model/Blog.php, modified**

```php
<?php

declare(strict_types=1);

namespace T3docs\BlogExample\Domain\Model;

use TYPO3\CMS\Extbase\Annotation\ORM\Lazy;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;

class Post extends AbstractEntity
{
    /**
     * @var ObjectStorage<Post>
     */
    #[Lazy()]
    public ObjectStorage $relatedPosts;

    /**
     * Use annotations instead for compatibility with TYPO3 v11:
     * @var ObjectStorage<Post>
     * @Lazy
     */
    public ObjectStorage $relatedPosts2;
}

```

## Annotations provided by Extbase {#annotations-provided-by-extbase}

The following annotations are provided Extbase:

### Validate {#extbase-annotation-validate}

`\TYPO3\CMS\Extbase\Annotation\Validate`: Allows to configure validators
for properties and method arguments. See [Validation](https://docs.typo3.org/permalink/t3coreapi:extbase-validation@12.4) for details.

Can be used in the context of a model property.

**Example:**

**EXT:blog_example/Classes/Domain/Model/Blog.php, modified**

```php
<?php

declare(strict_types=1);

namespace T3docs\BlogExample\Domain\Model;

use TYPO3\CMS\Extbase\Annotation\Validate;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;

class Blog extends AbstractEntity
{
    #[Validate([
        'validator' => 'StringLength',
        'options' => ['maximum' => 150],
    ])]
    public string $description = '';

    /**
     * Use annotations instead for compatibility with TYPO3 v11:
     *
     * @Validate("StringLength", options={"maximum": 150})
     */
    public string $description2 = '';
}

```

`Validate` annotations for a controller action are executed additionally
to possible domain model validators.

### IgnoreValidation {#extbase-annotation-ignore-validation}

`\TYPO3\CMS\Extbase\Annotation\IgnoreValidation()`: Allows to ignore
all Extbase default validations for a given argument (for example a domain
model object).

Used in context of a controller action.

**Example:**

**EXT:blog_example/Classes/Controller/BlogController.php, modified**

```php
<?php

declare(strict_types=1);

namespace T3docs\BlogExample\Controller;

use Psr\Http\Message\ResponseInterface;
use T3docs\BlogExample\Domain\Model\Blog;
use TYPO3\CMS\Extbase\Annotation\IgnoreValidation;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

final class BlogController extends ActionController
{
    #[IgnoreValidation(['argumentName' => 'blog'])]
    public function editAction(Blog $blog): ResponseInterface
    {
        // Do something
        $this->view->assign('blog', $blog);
        return $this->htmlResponse();
    }

    /**
     * Use annotations instead for compatibility with TYPO3 v11:
     * @IgnoreValidation("blog")
     */
    public function editAction2(Blog $blog): ResponseInterface
    {
        // Do something
        $this->view->assign('blog', $blog);
        return $this->htmlResponse();
    }
}

```

You can not exclude specific properties of a object specified in an argument.

If you need to exclude certain validators of a domain model, you could adapt
the concept of a "Data Transfer Object" (DTO). You would create a distinct
model variant of the main domain model, and exclude all the properties that
you do not want validation for in your Extbase context, and transport
the contents from and between your original domain model to this instance.
Read more about this on [https://usetypo3.com/dtos-in-extbase/](https://usetypo3.com/dtos-in-extbase/) or see a
CRUD example for this on
[https://github.com/garvinhicking/gh_validationdummy/](https://github.com/garvinhicking/gh_validationdummy/)

> [!WARNING]
> `IgnoreValidation()` must not be used for domain models supporting
> extbase file uploads, because this leads to a property mapping error.

### ORM (object relational model) annotations {#extbase-annotation-orm}

The following annotations can only be used on model properties:

#### Cascade {#extbase-annotation-cascade}

`\TYPO3\CMS\Extbase\Annotation\ORM\Cascade("remove")`: Allows to remove
child entities during deletion of aggregate root.

Extbase only supports the option "remove".

**Example:**

**EXT:blog_example/Classes/Domain/Model/Blog.php, modified**

```php
<?php

declare(strict_types=1);

namespace T3docs\BlogExample\Domain\Model;

use TYPO3\CMS\Extbase\Annotation\ORM\Cascade;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;

final class Blog extends AbstractEntity
{
    /**
     * @var ObjectStorage<Post>
     */
    #[Cascade(['value' => 'remove'])]
    public $posts;

    /**
     * Use annotations instead for compatibility with TYPO3 v11:
     *
     * @var ObjectStorage<Post>
     * @Cascade("remove")
     */
    public $posts2;
}

```

#### Transient {#extbase-annotation-transient}

`\TYPO3\CMS\Extbase\Annotation\ORM\Transient`: Marks property as transient
(not persisted).

**Example:**

**EXT:blog_example/Classes/Domain/Model/Post.php, modified**

```php
<?php

declare(strict_types=1);

namespace T3docs\BlogExample\Domain\Model;

use TYPO3\CMS\Extbase\Annotation\ORM\Transient;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;

final class Person extends AbstractEntity
{
    #[Transient()]
    protected string $fullname = '';

    /**
     * Use annotations instead for compatibility with TYPO3 v11:
     * @Transient
     */
    protected string $fullname2 = '';
}

```

#### Lazy {#extbase-annotation-lazy}

`\TYPO3\CMS\Extbase\Annotation\ORM\Lazy`: Marks model property to be loaded
lazily on first access.

> [!NOTE]
> Lazy loading can greatly improve the performance of your actions.

**Example:**

**EXT:blog_example/Classes/Domain/Model/Post.php, modified**

```php
<?php

declare(strict_types=1);

namespace T3docs\BlogExample\Domain\Model;

use TYPO3\CMS\Extbase\Annotation\ORM\Lazy;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;

class Post extends AbstractEntity
{
    /**
     * @var ObjectStorage<Post>
     */
    #[Lazy()]
    public ObjectStorage $relatedPosts;

    /**
     * Use annotations instead for compatibility with TYPO3 v11:
     * @var ObjectStorage<Post>
     * @Lazy
     */
    public ObjectStorage $relatedPosts2;
}

```

## Combining annotations {#extbase-annotation-combine}

Annotations can be combined. For example, "lazy loading" and "removal on cascade"
are frequently combined:

**EXT:blog_example/Classes/Domain/Model/Post.php, modified**

```php
<?php

declare(strict_types=1);

namespace T3docs\BlogExample\Domain\Model;

use TYPO3\CMS\Extbase\Annotation\ORM\Cascade;
use TYPO3\CMS\Extbase\Annotation\ORM\Lazy;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;

class Post extends AbstractEntity
{
    #[Lazy()]
    #[Cascade(['value' => 'remove'])]
    /**
     * @var ObjectStorage<Comment>
     */
    public ObjectStorage $comments;

    /**
     * @var ObjectStorage<Comment>
     * @Lazy
     * @Cascade("remove")
     */
    public ObjectStorage $comments2;
}

```

Several validations can also be combined. See [Validation](https://docs.typo3.org/permalink/t3coreapi:extbase-validation@12.4)
for details.
