Balessan
Balessan

Reputation: 2616

Wordpress: How to flush cached option value

I am currently working on a plugin, and I am stuck with an issue. I executed an SQL request on my database through PhpMyAdmin (which I implemented later through a plugin update mechanism), the request looked like this:

UPDATE `wp_options` 
    SET `option_value` = replace( `option_value` , 'model', 'ldp_model' ) 
WHERE `option_name` LIKE 'ldp_container%'

As you can see, I am updating all options value having name beginning by 'ldp_container'. Later in the code execution, when I am retrieving the option value, I am getting a value being false using:

$termId = $term->term_id;
$termMeta = get_option("ldp_container_$termId"); // $termMeta = false

I looked in this issue, and I got to the point where it seems that when I update/create this option, as I used:

update_option("ldp_container_$termID", $termMeta);

instead of

update_option("ldp_container_$termID", $termMeta, false);

The value of this option become part of the alloptions cache. So, retrieving it always return false now, and I do not know how to flush this cache.

Using a plugin update mechanism based on version number, I tried to flush the Wordpress object cache using:

$flush_cache = wp_cache_flush(); // returns true

And the Database query cache too:

$wpdb->flush();

I also tried explicitely deleting those options keys from the cache using a query then looping on results and calling wp_cache_delete:

  $result = $wpdb->get_results(
      "SELECT 'option_name'
       FROM $wpdb->options
       WHERE 'option_name' LIKE '%ldp_container_%';"
    );

    foreach ( $result as $current ) {
      wp_cache_delete($current, 'options');
    }

Still, no luck.

Does anybody have a clue for me here ?

Thanks,

EDIT:

Seems like my error is somewhere else.

After some debugging using Atom and Xdebug, it points out that the issue is with the unserialize method applied to the string retrieved from the database in the file /wp-includes/option.php as follows:

return apply_filters( 'option_' . $option, maybe_unserialize( $value ) );

maybe_unserialize do that:

if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
    return unserialize( $original );
return $original;

The call to the unserialize fails, so it returns false and then the false value is cached...

Using an online unserializer it confirms that the string is not correct, but I do not get why yet.

Upvotes: 4

Views: 3798

Answers (1)

Balessan
Balessan

Reputation: 2616

So, as I assumed my issue was due to the modification in serialized objects I was executing directly on the database. Because of the nature of serialized objects, looking like this:

a:1:{s:9:"ldp_model";s:1651:"{...

The 1651 being the number of characters in the ldp_model string, if you change anything inside this sting, then unserializing using unserialize() will return false, because the actual number of characters is different from the one indicated.

In my case, the solution was to instead of executing a database update of this kind:

$wpdb->query(
   "UPDATE $wpdb->options
    SET `option_value` = replace( `option_value` , 'ldp_', '' );"
);

To use the Options API as follows:

$result = $wpdb->get_results(
  "SELECT `option_name`
   FROM $wpdb->options
   WHERE `option_name` LIKE '%ldp_container_%';"
);

foreach ( $result as $current ) {
  $option = get_option($current->option_name);
  if (!empty($option) && !empty($option['ldp_model'])) {
    $option['ldp_model'] = str_replace('ldp_', '', $option['ldp_model']);
    update_option($current->option_name, $option, false);
  }
}

So that the serialized objects stays correct, and the Options API takes care of serialization and unserialization.

Lots of learning here for me ;-)

Upvotes: 2

Related Questions