Problem:
Relation Field select causes PDO exceptions when using relation fields that can have an unlimited number of values.
How to reproduce:
- Create a relation with fields, such that one of the field is a node reference which can have an
unlimited number of values ; - Create a content type that has a relation select field using the created relation ;
- Add a new entry for that content type.
Result:
The entry is not saved, and there is an error in the log of the form :
PDOException: SQLSTATE[HY000]: General error: 1366 Incorrect integer value: 'add_more' for column 'delta' at row 2:
Analysis
When the multi-valued field is saved, the form structure that is returned looks like this:
array(
'und' => array(
'0' => array(....),
'1' => array(....),
'add more' => 'Add another item'
)
)
Relation select tries to save the 'add more' field.
The problem happens in relation_select_field_insert. The code in there has three different cases:
- If it is a new relation, it simply copies the values from the form ;
- If it is an existing relation, but a new field, it simply copies the values from the form ;
- If it is an existing relation with an existing field, it processes the input via 'field_default_submit'
before saving it.
Case 3. is the only case that works. (This can be tested by first creating the relation, then later adding the multi-valued node reference), as field_default_submit calls _field_filter_items which removes undesirable values from the array. The patch provided ensures that field_default_submit is called in all cases.
| Comment | File | Size | Author |
|---|---|---|---|
| relation_select.patch | 2.93 KB | Alice Heaton |
Comments
Comment #1
Alice Heaton commentedI have realised this fix doesn not work in PHP 5.3, though it works in PHP 5.4
Given the following code:
This will output "empty" with PHP 5.4 but "full" with PHP 5.3
The code that cleans up the input array calls node_reference_field_is_empty, which returns empty($item['nid']) - this will give a different result on PHP 5.3 than PHP 5.4 if $item is not array.
The function however is called directly from _field_invoke in /modules/field/field.attach.inc, so it is up to the function to clean up the array.
Comment #2
Alice Heaton commentedSo I now see the 'add_more' field should never have made it that far. Trying to remove it at that stage is doing the work that should have been done in field_attach_submit. Relation Select needs to implement hook_field_attach_submit.
Comment #3
steveoliver commentedAlice,
Thank you for checking in to this.
You'll see I experimented with cleaning up Relation Select's field handing in 7.x-1.x--develop-normalize
I don't have much else to contribute to this task at the moment other than to point to that branch where I was trying to implement the proper entity/form-building flow, following what field_collection module was doing.
If you decide to tackle this, this branch may be working checking out.
Sorry I can't help out more on Relation / Relation Select -- there's been a lot of great momentum in the project(s) recently
Alice++++ :)
Comment #4
Alice Heaton commentedSo if I understand the code well, what the relation_select module does is create the relation entity when field_insert is called. This has the disadvantage of not having the form information at the point anymore.
I have looked at the field_collection module and they do this when 'validate' is called - which means they do it when they still have the form information. However creating the entity in validate does not seem right either.
So a quick fix for my problem would be to unset add_more in relation_select_field_insert in the same way that field_default_extract_form_values does.
But a proper fix, I think, would require moving the logic of creating the relation entity and mapping the fields into hook_field_attach_submit.
Here is a stub version (all it does is remove the 'add_more' field) :
Comment #5
Alice Heaton commented@steveoliver: Thanks for you reply. From what you say, I think my suggestion above is one that would go into the normalize branch, and the main branch should keep using the current architecture until the normalize branch is ready.
In that case I'd suggest for the main branch that relation_select_field_insert should look for and unset 'add_more' when present.
Comment #6
steveoliver commentedYep, it sounds like it. If you roll a patch for both branches, I'd be happy to test them out.
Comment #7
nwom commented