To avoid adding post meta values one at a time (and reduce repeat code in my theme) I wrote a simple class to store all the options so I can iterate through. The class works fine and constructs an object that I'm able to add valid options to (in much the same format one adds controls to the Customizer screen), and output the options forms in the meta box, but the values won't save. Here's how I'm trying to save the options, with some notes after. Please let me know if you have any ideas or need more info:

add_action( 'save_post', 'save_theme_options' );
function save_theme_options( $post_id ) {
    global $theme_options;
    foreach ( $theme_options->options as $option ) {
        if ( array_key_exists( $option->id, $_POST ) ) {
            update_post_meta($post_id, $option->meta_key, $_POST[$option->id]);

$theme_options is the global variable where I instantiate my object.

The $id of each option within $options requires a program-friendly string, such as "example_option". (It's not a number, like in WP objects.)

So with a single option set up like:

$theme_options->add_theme_option( 'example_text', array(
    'title'         =>  'Substrate Text Example',
    'description'   =>  'Example Description',
    'label'         =>  'Text:',
    'type'          =>  'text',
    'default'       =>  'Some text'

I expect $id to be 'example_text' and $meta_key to be '_example_text'.

Please let me know if you need more info, and thanks. (First post here.)

  • I think your code is right and should work. – JBoulhous Mar 14 '18 at 23:28
  • using a global is always a fail. first step here to to stop using it and instead get the options from a function like get_my_theme_options(). Most likely your global is not initialized at the time of save. – Mark Kaplun Mar 15 '18 at 5:14
  • @dudieboy71 I don't see metakey defined in your options block (the second code block)... unless you are implying it is generated from the id? – majick Mar 15 '18 at 11:12

Doing something like this would help make sure the theme object has been instantiated properly...

global $theme_options;
if ( (!isset($theme_options) || (!is_object($theme_options)) ) {
    $theme_options = new My_Theme_Options_Class();
  • 1
    Yes, while I instantiated the object globally, I added the options to the main object from inside a function... which meant those options were only available in the object within that function only. So in my saving function, the global object was still empty. Thanks for the check! – dudieboy71 Mar 16 '18 at 22:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.