Extbase model - extending AbstractEntity
All classes of the domain model should inherit from the class
\TYPO3\
.
An entity is an object fundamentally defined not by its attributes, but by a thread of continuity and identity, for example, a person or a blog post.
Objects stored in the database are usually entities as they can be identified
by the
uid
and are persisted, therefore have continuity.
In the TYPO3 backend models are displayed as Database records.
Example:
class Comment extends AbstractEntity implements \Stringable
{
protected string $author = '';
protected string $content = '';
public function getAuthor(): string
{
return $this->author;
}
public function setAuthor(string $author): void
{
$this->author = $author;
}
public function getContent(): string
{
return $this->content;
}
public function setContent(string $content): void
{
$this->content = $content;
}
}
Warning
Extbase does not call the constructor when thawing objects. Therefore you cannot set default values or initialize properties in the constructor. This includes properties that are defined via constructor parameter promotion. See also Default values for model properties.
Table of content
Subpages
Persistence: Connecting the model to the database
It is possible to define models that are not persisted to the database. However in the most common use cases you want to save your model to the database and load it from there. See Persistence: Saving Extbase models to the database.
Properties of an Extbase model
The properties of a model can be defined either as public class properties:
final class Tag extends AbstractValueObject implements \Stringable
{
public int $priority = 0;
}
Or public getters:
class Info extends AbstractEntity implements \Stringable
{
protected string $name = '';
protected string $bodytext = '';
public function getName(): string
{
return $this->name;
}
public function getBodytext(): string
{
return $this->bodytext;
}
public function setBodytext(string $bodytext): void
{
$this->bodytext = $bodytext;
}
}
A public getter takes precedence over a public property. Getters have the advantage that you can make the properties themselves protected and decide which ones should be mutable.
Note
Making model's properties
private
does not work in Extbase models: The parent
classes need to access the models properties directly. If your model must
not be extended you can mark it as
final
and thereby prevent
other developers from extending your model.
It is also possible to have getters for properties that are not persisted and get created on the fly:
class Info extends AbstractEntity implements \Stringable
{
protected string $name = '';
protected string $bodytext = '';
public function getCombinedString(): string
{
return $this->name . ': ' . $this->bodytext;
}
}
One disadvantage of using additional getters is that properties that are only defined as getters do not get displayed in the debug output in Fluid, they do however get displayed when explicitly called:
Does not display "combinedString":
<f:debug>{post.info}</f:debug>
But it is there:
<f:debug>{post.info.combinedString}</f:debug>
Typed vs. untyped properties in Extbase models
In Extbase, you can define model properties using either PHP native type
declarations or traditional @var
annotations. Typed properties are
preferred, untyped properties are still supported for backward compatibility.
The example below demonstrates a basic model with both a typed and an untyped property:
<?php
declare(strict_types=1);
namespace Vendor\Extension\Domain\Model;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
class Blog extends AbstractEntity
{
/**
* Typed property (preferred)
*
* @var string
*/
protected string $title = '';
/**
* Untyped property (legacy-compatible)
*
* @var bool
*/
protected $published = false;
// Getters and Setters
}
$title
is a typed property, using PHP’s type declaration. This is the recommended approach as it enforces type safety and improves code readability.$published
is an untyped property, defined only with a docblock. This remains valid and is often used in older codebases.
For persisted properties (those stored in the database), ensure that the property type matches the corresponding TCA Field type to avoid data mapping errors.
Nullable and Union types are also supported.
Note
Typed properties are strongly encouraged in all new TYPO3 extensions.
Default values for model properties
When Extbase loads an object from the database, it does not call the constructor.
This is explained in more detail in the section thawing objects of Extbase models.
This means:
- Property promotion in the constructor (for example
__
) does not workconstruct (public string $title = '') - Properties must be initialized in a different way to avoid runtime errors
Good: Set default values directly
You can assign default values when defining the property. This works for simple types such as strings, integers, booleans or nullable properties:
class Blog extends AbstractEntity
{
protected string $title = '';
protected ?\DateTime $modified = null;
}
Good: Use initializeObject()
for setup
If a property needs special setup (for example, using new Object
),
you can put that logic into a method called initialize
. Extbase
calls this method automatically after loading the object:
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\Domain\Model;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
class Blog extends AbstractEntity
{
protected ObjectStorage $posts;
public function __construct()
{
$this->initializeObject();
}
public function initializeObject(): void
{
$this->posts = new ObjectStorage();
}
}
Avoid: Constructor property promotion
This will not work when the object comes from the database:
public function __construct(protected string $title = '') {}
Since the constructor is never called during hydration, such properties remain uninitialized and can cause errors like:
Error: Typed property MyVendorMyExtensionDomainModelBlog::$title must not be accessed before initialization
To prevent this, always initialize properties either where they are defined or
inside the initialize
method.
TCA default values
If the TCA configuration of a field defines a
default value, that value is applied after
initialize
has been called, and before data from the database is
mapped to the object.
Extending existing models
It is possible, with some limitations, to extend existing Extbase models in another extension. See also Tutorial: Extending an Extbase model.