Skip to content

Commit 08615d2

Browse files
authored
[TASK] Move Domain chapters to subpages (#5534)
* [TASK] Move Domain chapters to subpages Content remains unchanged Releases: main, 13.4 * [TASK] Move Domain chapters to subpages Content remains unchanged Releases: main, 13.4 * [TASK] Move Domain chapters to subpages Content remains unchanged Releases: main, 13.4
1 parent 5af93d8 commit 08615d2

File tree

12 files changed

+350
-323
lines changed

12 files changed

+350
-323
lines changed

Documentation/ExtensionArchitecture/Extbase/Reference/Domain/Index.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
.. index:: Extbase; Domain
44
.. _extbase-domain:
55

6-
================
6+
==============
77
Model / Domain
8-
================
8+
==============
99

1010
The Application domain of the extension is always located below
1111
:file:`Classes/Domain`. This folder is structured as follows:
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
:navigation-title: Hydrating
2+
3+
.. include:: /Includes.rst.txt
4+
.. _extbase-model-hydrating:
5+
6+
=============================================
7+
Hydrating / Thawing objects of Extbase models
8+
=============================================
9+
10+
Hydrating (the term originates from `doctrine/orm`_), or in Extbase terms thawing,
11+
is the act of creating an object from a given database row. The responsible
12+
class involved is the :php:`\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper`.
13+
During the process of hydrating, the :php:`DataMapper` creates objects to map
14+
the raw database data onto.
15+
16+
Before diving into the framework internals, let us take a look at models from
17+
the user's perspective.
18+
19+
.. _doctrine/orm: https://github.com/doctrine/orm
20+
21+
.. _extbase-model-constructor:
22+
23+
Creating model objects with constructor arguments
24+
=================================================
25+
26+
Imagine you have a table :sql:`tx_extension_domain_codesnippets_blog` and a
27+
corresponding model or entity (entity is used as a synonym here)
28+
:php:`\MyVendor\MyExtension\Domain\Model\Blog`.
29+
30+
Now, also imagine there is a domain rule which states, that all blogs must have
31+
a title. This rule can easily be followed by letting the blog class have a
32+
constructor with a required argument :php:`string $title`.
33+
34+
.. literalinclude:: _codesnippets/_Blog1.php
35+
:caption: EXT:my_extension/Classes/Domain/Model/Blog.php
36+
37+
This example also shows how the `posts` property is initialized. It is done in
38+
the constructor because PHP does not allow setting a default value that is of
39+
type object.
40+
41+
.. _extbase-model-constructor-hydration:
42+
43+
Hydrating objects with constructor arguments
44+
============================================
45+
46+
Whenever the user creates new blog objects in extension code, the aforementioned
47+
domain rule is followed. It is also possible to work on the :php:`posts`
48+
:php:`ObjectStorage` without further initialization. :php:`new Blog('title')` is
49+
all one need to create a blog object with a valid state.
50+
51+
What happens in the :php:`DataMapper` however, is a totally different thing.
52+
When hydrating an object, the :php:`DataMapper` cannot follow any domain rules.
53+
Its only job is to map the raw database values onto a :php:`Blog` instance. The
54+
:php:`DataMapper` could of course detect constructor arguments and try to guess
55+
which argument corresponds to what property, but only if there is an easy
56+
mapping, that means, if the constructor takes the argument :php:`string $title`
57+
and updates the property `title` with it.
58+
59+
To avoid possible errors due to guessing, the :php:`DataMapper` simply ignores
60+
the constructor at all. It does so with the help of the library
61+
`doctrine/instantiator`_.
62+
63+
But there is more to all this.
64+
65+
.. _doctrine/instantiator: https://github.com/doctrine/instantiator
66+
67+
.. _extbase-model-initializing:
68+
69+
Initializing objects
70+
====================
71+
72+
Have a look at the :php:`$posts` property in the example above. If the
73+
:php:`DataMapper` ignores the constructor, that property is in an invalid state,
74+
that means, uninitialized.
75+
76+
To address this problem and possible others, the :php:`DataMapper` will call the
77+
method :php:`initializeObject(): void` on models, if it exists.
78+
79+
Here is an updated version of the model:
80+
81+
.. literalinclude:: _codesnippets/_Blog2.php
82+
:caption: EXT:my_extension/Classes/Domain/Model/Blog.php
83+
84+
This example demonstrates how Extbase expects the user to set up their models.
85+
If the method :php:`initializeObject()` is used for initialization logic that
86+
needs to be triggered on initial creation **and** on hydration. Please mind
87+
that :php:`__construct()` **should** call :php:`initializeObject()`.
88+
89+
If there are no domain rules to follow, the recommended way to set up a model
90+
would then still be to define a :php:`__construct()` and
91+
:php:`initializeObject()` method like this:
92+
93+
.. literalinclude:: _codesnippets/_Blog3.php
94+
:caption: EXT:my_extension/Classes/Domain/Model/Blog.php
95+
96+
.. _extbase-model-mutation:
97+
98+
Mutating objects
99+
================
100+
101+
Some few more words on mutators (setter, adder, etc.). One might think that
102+
:php:`DataMapper` uses mutators during object hydration but it **does not**.
103+
Mutators are the only way for the user (developer) to implement business rules
104+
besides using the constructor.
105+
106+
The :php:`DataMapper` uses the internal method
107+
:php:`AbstractDomainObject::_setProperty()` to update object properties. This
108+
looks a bit dirty and is a way around all business rules but that is what the
109+
:php:`DataMapper` needs in order to leave the mutators to the users.
110+
111+
.. warning::
112+
While the :php:`DataMapper` does not use any mutators, other parts of
113+
Extbase do. Both, :ref:`validation <extbase_domain_validator>` and property
114+
mapping, either use existing mutators or gather type information from them.
115+
116+
.. _extbase-model-visibility:
117+
118+
Property visibility
119+
===================
120+
121+
One important thing to know is that Extbase needs entity properties to be
122+
protected or public. As written in the former paragraph,
123+
:php:`AbstractDomainObject::_setProperty()` is used to bypass setters.
124+
However, :php:`AbstractDomainObject` is not able to access private properties of
125+
child classes, hence the need to have protected or public properties.
126+
127+
.. _extbase-model-dependency-injection:
128+
129+
Dependency injection
130+
====================
131+
132+
Without digging too deep into :ref:`dependency injection <DependencyInjection>`
133+
the following statements have to be made:
134+
135+
* Extbase expects entities to be so-called prototypes, that means classes that
136+
do have a different state per instance.
137+
* :php:`DataMapper` **does not** use dependency injection for the creation of
138+
entities, that means it does not query the object container. This also
139+
means, that dependency injection is not possible in entities.
140+
141+
If you think that your entities need to use/access services, you need to find
142+
other ways to implement it.
143+
144+
.. _extbase-model-event:
145+
146+
Using an event when a object is thawed
147+
======================================
148+
149+
The PSR-14 event :ref:`AfterObjectThawedEvent` is available to modify values
150+
when creating domain objects.

Documentation/ExtensionArchitecture/Extbase/Reference/Domain/Model/_codesnippets/_Hydrating/_Blog1.php renamed to Documentation/ExtensionArchitecture/Extbase/Reference/Domain/Model/Hydrating/_codesnippets/_Blog1.php

File renamed without changes.

Documentation/ExtensionArchitecture/Extbase/Reference/Domain/Model/_codesnippets/_Hydrating/_Blog2.php renamed to Documentation/ExtensionArchitecture/Extbase/Reference/Domain/Model/Hydrating/_codesnippets/_Blog2.php

File renamed without changes.

Documentation/ExtensionArchitecture/Extbase/Reference/Domain/Model/_codesnippets/_Hydrating/_Blog3.php renamed to Documentation/ExtensionArchitecture/Extbase/Reference/Domain/Model/Hydrating/_codesnippets/_Blog3.php

File renamed without changes.

0 commit comments

Comments
 (0)