Task #85216
closedEXT:form SaveToDatabase Finisher saves files as sys_file, not as sys_file_reference
0%
Description
Use case:
I have a model with file properies (logo) that can be filled by a form, but should also be editable via backend.
Form field configuration:
-
identifier: logo
type: ImageUpload
saveToFileMount: '1:/user_upload/myfolder/'
Finisher configuration:
finishers:
-
identifier: SaveToDatabase
options:
table: 'tx_myext_domain_model_mymodel'
mode: 'insert'
elements:
logo:
mapOnDatabaseColumn: 'logo'
My model used to have a TCA configuration for FAL using \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig. But that doesn't work with the form, because the finisher only creates a sys_file entry, so sys_file_reference. Why?
My current solution was to adjust my TCA and templates. But it just doesn't seem right not being able to use the advantages of FAL. Or am I missing some configuration?
Updated by Ralf Zimmermann over 6 years ago
- Tracker changed from Bug to Task
- Status changed from New to Needs Feedback
- Assignee set to Lidia Demin
Uploads are sys_file entities because there are no relations to other records (sys_file_reference) at this point.
Your finisher configuration has the intention to establish such a relationship, so you have to do that.
You need a second insert statement which creates the relation between the "sys_file" record and the "tx_myext_domain_model_mymodel.logo" property.
finishers: - identifier: SaveToDatabase options: - table: 'tx_myext_domain_model_mymodel' mode: 'insert' elements: logo: mapOnDatabaseColumn: 'logo' - table: 'sys_file_reference' mode: insert elements: logo: mapOnDatabaseColumn: 'uid_local' databaseColumnMappings: table_local: value: 'sys_file' tablenames: value: 'tx_myext_domain_model_mymodel' fieldname: value: 'logo' tstamp: value: '{__currentTimestamp}' crdate: value: '{__currentTimestamp}' uid_foreign: value: '{SaveToDatabase.insertedUids.0}'
Updated by Lidia Demin over 6 years ago
It works, thank you very much!
Can we add this to documentation? Even if I would guessed that the file reference has to be set manually, I wouldn't have figured out all of the settings.
Updated by Riccardo De Contardi over 6 years ago
- Sprint Focus set to On Location Sprint
Updated by Presedo Roberto over 6 years ago
This configuration is ok as long as the upload field is filled, otherwise ,if the field is not required, a broken sys_file_reference record is added with a uid_local set to 0...
I know that this is not resolving this issue, but if this example goes in the documentation, I think we should warn the users of this scenario...
The only way to resolve this situation, is not to use the SaveToDatabase finisher and create a custom one, or overwrite it, which is probably easier
As discussed on Slack, https://typo3.slack.com/archives/C093RB4P9/p1529417777000792
"the easiest way would be to create a `BaseSetup.yaml` and overwrite `TYPO3.CMS.Form.prototypes.standard.finisherDefinition.SaveToDatabase.implementationClassName = 'Your own class'`
the `SaveToDatabase` finisher has the protected method `process` which seems to be exactly what you need. Wrap that in whatever condition you need and that should work"
Updated by Lidia Demin over 6 years ago
Yes, I had also the issue with an exception for the sys_file_reference table if no file was submitted. I tried setting skipIfValueIsEmpty: true for the field in both tables without no luck. But imho it should work out of the box as well that the file field does not need to be mandatory. I'll open a feature request. Till then I agree, that this hint should go into documentation as well.
Updated by Lidia Demin over 6 years ago
- Copied to Feature #85378: EXT:form option for saving uploaded file as sys_file_reference added
Updated by Vasyl Mosiychuk over 6 years ago
- Related to Bug #85772: EXT:form SaveToDatabaseFinisher cannot handle multi value fields added
Updated by Vasyl Mosiychuk over 6 years ago
Ralf Zimmermann wrote:
Uploads are sys_file entities because there are no relations to other records (sys_file_reference) at this point.
Your finisher configuration has the intention to establish such a relationship, so you have to do that.
You need a second insert statement which creates the relation between the "sys_file" record and the "tx_myext_domain_model_mymodel.logo" property.[...]
My finisher is correct and working it at the moment
-
options:
-
table: tx_foo_domain_model_foo
mode: insert
databaseColumnMappings:
pid:
value: '0'
datetime:
value: '{__currentTimestamp}'
tstamp:
value: '{__currentTimestamp}'
crdate:
value: '{__currentTimestamp}'
elements:
categories:
mapOnDatabaseColumn: categories
title:
mapOnDatabaseColumn: title
bodytext:
mapOnDatabaseColumn: bodytext
attachment:
mapOnDatabaseColumn: fal_media
-
table: sys_category_record_mm
mode: insert
elements:
categories:
mapOnDatabaseColumn: uid_local
databaseColumnMappings:
tablenames:
value: tx_foo_domain_model_foo
fieldname:
value: categories
uid_foreign:
value: '{SaveToDatabase.insertedUids.0}'
-
table: sys_file_reference
mode: insert
elements:
attachment:
mapOnDatabaseColumn: uid_local
databaseColumnMappings:
table_local:
value: sys_file
tablenames:
value: tx_foo_domain_model_foo
fieldname:
value: fal_media
tstamp:
value: '{__currentTimestamp}'
crdate:
value: '{__currentTimestamp}'
uid_foreign:
value: '{SaveToDatabase.insertedUids.0}'
identifier: SaveToDatabase
I described it here #85378
Updated by alejandro antolinez over 6 years ago
I have a solution for all case.
You insert sys_file_reference whit skipIfValueIsEmpty: true
And after you update sys_file_reference whit your pid and your uid_foreign and uid_local=0 (if the case if you skipIfValueIsEmpty)
You set your pid and your uid_foreign to 0 and you dont have a broken sys_file_reference record
Example
identifier: SaveToDatabase
options:
1:
table: 'tx_news_domain_model_news'
mode: insert
databaseColumnMappings:
pid:
value: 41
datetime:
value: '{__currentTimestamp}'
tstamp:
value: '{__currentTimestamp}'
crdate:
value: '{__currentTimestamp}'
elements:
text-1:
mapOnDatabaseColumn: 'title'
textarea-1:
mapOnDatabaseColumn: 'bodytext'
2:
table: 'sys_file_reference'
mode: insert
databaseColumnMappings:
pid:
value: 41
tstamp:
value: '{__currentTimestamp}'
crdate:
value: '{__currentTimestamp}'
tablenames:
value: 'tx_news_domain_model_news'
table_local:
value: 'sys_file'
fieldname:
value: 'fal_media'
uid_foreign:
value: '{SaveToDatabase.insertedUids.1}'
elements:
imageupload-1:
mapOnDatabaseColumn: 'uid_local'
skipIfValueIsEmpty: true
3:
table: 'sys_file_reference'
mode: update
whereClause:
pid: 41
uid_foreign: '{SaveToDatabase.insertedUids.1}'
uid_local: 0
databaseColumnMappings:
pid:
value: 0
uid_foreign:
value: 0
But for me we need a skipActionIfValueIsEmpty to skip all the action and not just the elements.
Updated by Vasyl Mosiychuk over 6 years ago
alejandro antolinez wrote:
I have a solution for all case.
You insert sys_file_reference whit skipIfValueIsEmpty: trueAnd after you update sys_file_reference whit your pid and your uid_foreign and uid_local=0 (if the case if you skipIfValueIsEmpty)
You set your pid and your uid_foreign to 0 and you dont have a broken sys_file_reference recordExample
[...]
But for me we need a skipActionIfValueIsEmpty to skip all the action and not just the elements.
Hello, Alejandro!
Thank you for reply.
but I have question, why so...
uid_foreign:
value: '{SaveToDatabase.insertedUids.1}'
and not so...
uid_foreign:
value: '{SaveToDatabase.insertedUids.0}'
I insert 'key: 0' - record = 0... and not 'key: 1' - record = 1 ...???
And I do not understand about it... skipActionIfValueIsEmpty - what is that?
I still get error when value: '{SaveToDatabase.insertedUids.0}' - empty. I don't know how it is solve.
Updated by alejandro antolinez over 6 years ago
You can write options as an array to perform multiple database operations.
In my case 1 is
1:
table: 'tx_news_domain_model_news'
mode: insert
databaseColumnMappings:
pid:
value: 41
datetime:
value: '{__currentTimestamp}'
tstamp:
value: '{__currentTimestamp}'
crdate:
value: '{__currentTimestamp}'
elements:
text-1:
mapOnDatabaseColumn: 'title'
textarea-1:
mapOnDatabaseColumn: 'bodytext'
{SaveToDatabase.insertedUids.1}
give me the uid of my first insert.
it's the code in the documentation for multiple database operations
[[https://docs.typo3.org/typo3cms/extensions/form/ApiReference/Index.html?highlight=inserteduids#savetodatabase-finisher]]
skipActionIfValueIsEmpty not exist but in the same way of skipIfValueIsEmpty skip the value from the submitted form element with the identifier <formElementIdentifier> is empty.
We need a skipActionIfValueIsEmpty (or other name) with argument a formElementIdentifier to skip all the insert
exemple:
2:
table: 'sys_file_reference'
mode: insert
skipActionIfValueIsEmpty : imageupload-1
databaseColumnMappings:
pid:
value: 41
tstamp:
value: '{__currentTimestamp}'
crdate:
value: '{__currentTimestamp}'
tablenames:
value: 'tx_news_domain_model_news'
table_local:
value: 'sys_file'
fieldname:
value: 'fal_media'
uid_foreign:
value: '{SaveToDatabase.insertedUids.1}'
elements:
imageupload-1:
mapOnDatabaseColumn: 'uid_local'
if imageupload-1 it's empty whe skip all the insert in sys_file_reference
Updated by alejandro antolinez about 6 years ago
Try this whit your code
finishers:
-
identifier: SaveToDatabase
options:
-
table: 'tx_myext_domain_model_mymodel'
mode: insert
elements:
logo:
mapOnDatabaseColumn: 'logo'
-
table: 'sys_file_reference'
mode: insert
elements:
logo:
mapOnDatabaseColumn: 'uid_local'
skipIfValueIsEmpty: true
databaseColumnMappings:
table_local:
value: 'sys_file'
tablenames:
value: 'tx_myext_domain_model_mymodel'
fieldname:
value: 'logo'
tstamp:
value: '{__currentTimestamp}'
crdate:
value: '{__currentTimestamp}'
uid_foreign:
value: '{SaveToDatabase.insertedUids.0}'
-
table: 'sys_file_reference'
mode: update
whereClause:
uid_foreign: '{SaveToDatabase.insertedUids.0}'
uid_local: 0
databaseColumnMappings:
pid:
value: 0
uid_foreign:
value: 0
Updated by Vasyl Mosiychuk about 6 years ago
alejandro antolinez wrote:
Try this whit your code
[...]
Yes, I tried it and it is working. Now I do not get error and in the database does not created a broken records... is pretty cool...
Updated by Björn Jacob about 6 years ago
- Status changed from Needs Feedback to Closed
- Assignee deleted (
Lidia Demin)
Since everyone is happy, I am closing this issue. Hope this is fine with everyone.
Updated by Vasyl Mosiychuk about 6 years ago
Bjoern Jacob wrote:
Since everyone is happy, I am closing this issue. Hope this is fine with everyone.
...will be good if this is add to the documentation.
Updated by Kurt Dirnbauer almost 5 years ago
regarding the code from alejandro antolinez
Thank you!
there is small bug in the configuration - databaseColumnMappings: in the update-command had wrong indentation.
Of course you still get wrong (unused) entries in the sys_reference_table. I think that there is no delete-mode?
finishers:
-
identifier: SaveToDatabase
options:
-
table: 'tx_myext_domain_model_mymodel'
mode: insert
elements:
logo:
mapOnDatabaseColumn: 'logo'
-
table: 'sys_file_reference'
mode: insert
elements:
logo:
mapOnDatabaseColumn: 'uid_local'
skipIfValueIsEmpty: true
databaseColumnMappings:
table_local:
value: 'sys_file'
tablenames:
value: 'tx_myext_domain_model_mymodel'
fieldname:
value: 'logo'
tstamp:
value: '{__currentTimestamp}'
crdate:
value: '{__currentTimestamp}'
uid_foreign:
value: '{SaveToDatabase.insertedUids.0}'
-
table: 'sys_file_reference'
mode: update
whereClause:
uid_foreign: '{SaveToDatabase.insertedUids.0}'
uid_local: 0
databaseColumnMappings:
pid:
value: 0
uid_foreign:
value: 0