Needs review
Project:
Address Field
Version:
7.x-1.x-dev
Component:
Code
Priority:
Normal
Category:
Bug report
Assigned:
Unassigned
Reporter:
Created:
7 Sep 2011 at 16:16 UTC
Updated:
3 Mar 2020 at 04:40 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
wesnick commentedI was trying to do something similar, and getting field exceptions on save. This patch works for me. Marking needs review.
Comment #2
damien tournoud commentedWe should use a different name between the serialized version and the unserialized: for example, name the serialized version
data_serialized, and keepdatafor the unserialized (we will have to update the columns in an update function, but that's ok).The problem is that by changing data like this, we quickly end up in situations where the data is serialized while it shouldn't or isn't while it should (for example when you save the same entity twice). There is no good way around it.
Comment #3
rbayliss commentedI guess I just assumed that there was no utility in the data column as-is (since it is flagged in the schema as being serialized), but I think what you're saying is that people may already have data in there, which is certainly possible. My only issue with adding the data_serialized column is that you'll end up with a form structure like:
$format['mycustomfield_block']['data_serialized']['mycustomfield'], which doesn't seem very intuitive, but if it avoids collisions with existing data it's probably worth it.Marking as needs work so I remember to come back and add a data_serialized column and update hook.
Comment #4
damien tournoud commentedI suggest we do that. Would it work for everyone?
Comment #5
wesnick commentedI think I get this. We need to handle the data serialization differently that it is handled in Entity API, for example, since we don't have __sleep()/__wakeup() magic methods or other class helpers to let us know if the data is currently serialized or not? Or is it because people might already have strings stored in there?
Comment #6
damien tournoud commentedThe problem is that we don't control the workflow of the field, so we might get stuff that we don't expect: an entity can be saved twice, for example.
Comment #7
wesnick commentedThis patch seems to work nicely, however under some conditions the update will not work correctly.
Unfortunately, I am not using the dev version right now, so I can't reroll this patch, but I have attached a patch that will fix this if you encounter it.
Comment #8
davidwhthomas commented@Damien, great to see a good patch in this direction.
In your example of an entity being saved twice, can you please explain in more detail the problem there?
It seems to me, if the data field is unserialized on field load and serialized on field presave then the data column itself could be used for storing the serialized data?
Looking forward to a solution to this.
cheers,
David
Comment #9
rbayliss commentedIt took me 6 months or so, but I finally see your point here. I'm not sure it's anything I've run into before, but kudos for being on the safe side. Just tried your version of the patch and it works fine.
For anyone wondering, I'll try to explain the reason for the change because I was confused too... Hook_field_presave() alters by reference, so if you use data as the key for both the serialized and unserialized values, there's always the chance that you still have a reference to this entity out there somewhere, and would call entity_save() on it again. But since data would already be serialized, you'd hit an error. Plus, you'd run into some errors if you're still holding onto the entity and need to access something in data (trying to treat a string as an array). With Damien's change, data will always be an array, and data_serialized will always be a string. Only "data_serialized" will be written to the database, and only "data" will be directly accessed by developers.
Comment #10
bucefal91 commentedGentlemen,
Any chances on this to be expanded into a general case and committed into core? I am not sure whether it still can be committed into D7? and I am not familiar with D8 and how its core works.
I think since in Schema API it is stated that 'serialize' property means data being serialized and stored as a serialized string, it should be respected including by Field API. Damien's approach on defining an extra property for keeping unserialized information in the original property, while maintaining a serialized copy in another property seems a very good idea to me.
I've been working on a custom field type and I ended up needing this kind of feature for one of the columns of my custom field type. I was searching on the web and google brought me to this issue queue. Though I understand it's been a year since last comment.
And Damien's approach worked for my column. I am pretty confident it can be expanded into a general case, based on whether 'serialize' is set to TRUE in the schema of a field type.
P.S. I could volunteer myself for this general case patch... would be my 1st patch into core.
Comment #11
ciss commentedRerolled patch coming.
Comment #12
ciss commentedThis patch incorporates all of the previous patches (initial, #4, #7), rerolled against the latest release.
Additionally it adds an update hook to serialize any unserialized stored data.
Unless I'm missing something the data isn't namespaced in any way, currently, meaning that plugins could easily overwrite each other's data. This should probably be covered in a separate issue, though.
@bucefal91: Core only respects a schema's "serialize" definition in drupal_write_record(). I'm not sure there's a way to fix this in core without breaking existing implementations.
Comment #13
ciss commentedUpdating status.
Comment #14
jkuma commentedThe last patch is working like a charm and I have nothing to say regarding some improvements we may add to it... I update this issue to RTBC.
Comment #15
jkuma commentedComment #16
cwoky commentedHello,
I use addressfield with Drupal Commerce for my customer profiles.
My shipping profiles have data serialized for phone numbers.
My billing profiles have only basic address information and don't have data serialized.
With this patch (https://www.drupal.org/files/issues/1272168-12-data-field.patch), I have the following warning :
Notice : Undefined index: data dans addressfield_field_presave() (ligne 449 dans /var/www/sites/all/modules/contrib/addressfield/addressfield.module).
I also tried on simplytest.me and I had the same warning.
I modified the patch to fix this warning.
Comment #17
jenlamptonNeeded a reroll.
Comment #18
socialnicheguru commenteddrush updatedb
Addressfield 7002 Serialize existing values in the data_serialized column.
Addressfield 7003 Rename the data column.
Do you wish to run all pending updates? (y/n): y
SQLSTATE[42S22]: Column not found: 1054 Unknown column 't.commerce_customer_address_data_serialized' in 'field list' [error]
Performed update: addressfield_update_7002
I cannot update addressfield
Comment #19
socialnicheguru commented#16 worked - https://www.drupal.org/node/1272168#comment-9224151
I did have to renumber the updates but it did work
Comment #20
ciss commented@SocialNicheGuru then please set the status back.
Comment #21
socialnicheguru commentedIn the latest release, it looks like the data column is serialized
in the addressfield.install
Comment #22
socialnicheguru commentedComment #23
bojanz commentedComment #24
ciss commented@SocialNicheGuru That has been in there since forever, but has no effect outside of drupal_write_record().
@bojanz Why has this been marked as outdated? As far as I can tell there is still not a single serialize() call in addressfield (outside of addressfield.migrate.inc).
Comment #25
ciss commentedPatch now redeclares addressfield_field_load(). Function was added in #2169863: Fix duplicate saving of customer profiles.
Comment #26
ciss commentedHad to move some things around to incorporate the recent changes. No changes to the update hook though.
Comment #27
jenlamptonThe updates only run for me if they are in the opposite order. Patch attached for review.