Check if an option exists and get its value in one hit

I have an option admins_settings that has an array of sub-options that is stored in the wp_options table. Before I get its value from the table, I check if this field exists by running this code:

if ( !isset( get_option( 'admins_settings' )['option_name'] ) ) {
    return false;
} else {
    return get_option( 'admins_settings' )['option_name'];
}

Here, I'm hitting the table 2 times (if the field exists) to get its value. Is there any way to get the value of the field with one hit?

I know that the get_option function accepts a default value if the option doesn't exist. But this works with the simple values:

get_option( 'admins_settings', false );

But not with array values:

get_option( 'admins_settings' )['option_name'];

Because the option admins_settings could be there, but it doesn't have that item option_name.

Again, is there any way to get the sub-value of the field with one hit?

Topic options database query Wordpress

Category Web


I'm hitting the table 2 times (if the field exists) to get its value.

No, you aren't, and there is no evidence for this. You may not be hitting the database at all if it has autoload enabled. WordPress caches things in memory during the same request, and it bulk fetches options set to autoload for performance reasons.

The same is true of other things such as post meta. WordPress will attempt to store this data in WP Cache to avoid going back to the database again. E.g. when you fetch a post, it also fetches its post meta and its terms all at once to avoid lots of small database queries. This is also why object caches have such a huge boost to performance as it allows that cache to stay alive across multiple requests.

But this works with the simple values:

But not with array values:

They are all simple values, and they are always simple values. Options are strings, and have always been strings. If you try to save an array/object then WordPress will attempt to turn it into a string using PHP serialize, then deserialize it when you fetch it. This has security consequences.

There is no such thing as "sub-options", "nested options", or "child options". There is just options. admins_settings is your option, and WordPress sees the entire array as the value, not a series of values, but a singular value that must be serialized. You cannot provide defaults for sub-values this way because options cannot have sub-values. That your value contains structured data is coincidental.

Instead, you have 2 options

  1. Store separate values as separate values, ideally with a prefix
  2. Treat you array as an array and not a weird sub-option ( because there's no such thing as sub-options )

So you would check it the same way you would check an array has a value:

$data = [];
if ( isset( $data['test'] ) ) {
    return $data;
} else {
    return false;
}

Remember, the options table uses plaintext for the value column, the idea that you can store objects and arrays is an illusion WordPress provides to make life easier, and one that would be near impossible to fix after nearly 2 decades.


Upon entering the if() statement of your code, it will return to the calling function either way. So, you could simply use:

return get_option('admins_settings')['option_name'];

which will return boolean false if the option doesn't exist or it will return the option value if it does exist.

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.