WordPress serializes options and meta for you

When tracking down a potential bug last week, I noticed that many plugin authors were making the same mistake and were making their lives much more difficult in the process. The issue was related to the serialization of data (here’s the PHP manual entry). In the most basic use case, serialization is a way to store arrays and objects directly in the database, which can only store numbers, text, and dates. Serialization takes an array and turns it into a serialized string. For example:

$data = array( 'apple', 'banana', 'orange' );
echo serialize( $data );
// Result is a string we can unserialize into an array:
// a:3:{i:0;s:5:"apple";i:1;s:6:"banana";i:2;s:6:"orange";}

WordPress has a few helper functions that we use instead of serialize() and unserialize() — maybe_serialize() and maybe_unserialize(). The first only serializes data that needs to be serialized — arrays and objects — and the second only unserializes data that is already serialized. (We have a lot of handy functions like these.) At some point in 3.0, something changed, and it caused an error for plugins using get_post_meta(). Matt Martz and I tracked this down to a change in maybe_serialize():

It comes out of a change to maybe_serialize() in r13673, which for a long while serialized already serialized data, and now no longer does. We’ll probably revert this. [Which I did in r14074.]

This shouldn’t have broken plugins however, at least not in this case. But here’s what the plugin was doing:

update_post_meta( '_my_plugin_meta', serialize( array( 'foo', bar' ) ) );
unserialize( get_post_meta( '_my_plugin_meta' ) );

The unserialize and serialize bits are unnecessary. The post, comment and user meta functions, and the functions for options and transients (and site meta) all transparently serialize and unserialize data for you. Thus, this works:

update_post_meta( '_my_plugin_meta', array( 'foo', bar' ) );
get_post_meta( '_my_plugin_meta' );

I explained what was going on in #12930. Thanks to Ipstenu for raising the ticket, as we would have received a lot of complaints due to the change:

More or less, that means that you’re serializing the data, then update_option is serializing serialized data, then get_option is unserializing it once, and unserialize is unserializing it again. r13673 breaks this, as update_option doesn’t serialize the data a second time any more, causing the plugin’s unserialize() to attempt to perform a second unserialize() on data that was only serialized once.

In this case, the change was accidental, and we already went through this once nearly two years ago (see #7347r8100r8372, and others). But sometimes plugin developers that the API incorrectly or make bad assumptions makes it significantly more difficult for us to improve WordPress, as we are very mindful of plugins we may break — even if the plugin is “Doing It Wrong.” So please, don’t make it harder for us to make it easier for you.