My questions in advance:
How does Extbase decide if the given Object should be a transient entity or modified / persistent entity?
Is there any kind of Documentation on how Extbase maps (would you say mapping?) the form data into an Object?
I’m using Etxbase to create an extension for TYPO3.
- TYPO3 v.11
- Extbase
- Fluid
I have a Model A with a relation to Model B.
Inside the database, B connected to A as "tx_vendor_ext_a {my_b int(11) unsigned
}".
A is displayed in the frontend via action controller and Fluid.
AController has a List, Show, Edit, Delete and Create Action.
When I call my editAction(A $a) change some Values of A and Save (update Action(A $newA)) everything works fine. But when I want to Change Values of A.myB instead of updating myB Extbase is creating a new Object and persisting the new Object with a new UID.
I have a different Example where the child object is updated, not recreated. Debugging the parent in the update Action Shows (think of ‘Kunde’ as myB):
But when I debug the one not working, it shows (think of ‘einstellungen’ as myB):
Notice the transient entity flag.
My Fluid looks like this in both cases
<f:form action="update" name="a" object="{a}" >
<f:form.textfield property="myB.name" value="{myB.name}" id="myB-name" />
<f:form.submit value="Save" />
</f:form>
Annotations in the model class:
field : @var venextDomainModelA
getter: @return venextDomainModelA
setter: @param venextDomainModelA
@return void
Annotations in the controller:
action: @param venextDomainModelA $newA
I have to admit, I don’t really know how Extbase is mapping the properties from the form into a domain object.
So These are my Questions:
How does Extbase decide if the given Object should be a transient entity or modified / persistent entity?
Is there any kind of Documentation on how Extbase maps (would you say mapping?) the form data into an Object?
Additionally: Where could I have made a mistake, causing Extbase to create a new Object instead of updating the old one?
2
Answers
The "transient" flag when you debug your entity only means that the entity is not yet persisted (
$b->_isNew()
returnstrue
). It’s not a special type of entity (there is only one such type) – it’s solely about the persistence state. In other words: Extbase doesn’t decide when an entity is transient vs. persistent – you make this decision by either persisting or not persisting your entity. Inferring from your description, you expect the flag to be "modified" meaning$b->_isDirty()
returnstrue
.The information you provide about your property, getter and setter indicates a problem. If your entity B is only associated with entity A through a property on entity B, then B is not going to be thawed correctly when fetching A from persistence.
Judging by your template code:
<f:form.textfield property="myB.name" value="{myB.name}" id="myB-name" />
It appears that your B entity is somehow provided separately as variable
{myB}
when the expected variable would be{a.myB}
. This could indicate that the problem I described above is relevant: if{a.myB}
does not yield the correct entity, then entity A is actually not aware of entity B and mapping would fail. By the way: specifyingvalue="..."
is redundant since Extbase would extract the current value from the aggregate root entity (further indicating a problem if you have to specify it for a value to appear).The solution therefore should be:
@var
annotation.{a.myB}
in the template (but remember that you should not need to, if the aggregate root works correctly and you reference the B entity’s properties by their property path on the aggregate root).apart from what Claus Due already explained.
Extbase Persitance Mapping is somewhat unexpected as it uses TCA in the Background. so if there is no TCA Entry for a Property or Table. extbase is not able to Persist it. and it is often not "clear" that this is the reason. so make sure you have a valid TCA definition for your data.