4

I have added some custom options to my WordPress CMS within the Reading admin page. I am using these options to set some additional pages that I then have bound to custom operations. This method allows me to not maintain a constants file with a bunch of hard-coded page IDs and grants the end user more flexibility over what pages perform what functions.

When these options change, I need to be able to flush the permalinks so that any references to these pages are updated and the permalinks throughout the site work properly.

I have written the following in an attempt to do this:

function qd_flush_rules() { 
   flush_rewrite_rules(); 
} 
add_action('update_option_qd_news_page', 'qd_flush_rules');

qd_news_page is the name of the option that I created and I can confirm this setting is created properly and working. I am also pretty sure that this function is firing after the data is saved, because any echo I place in the qd_flush_rules function outputs the value of the setting properly.

Regardless, the rewrite rules are not flushing and my permalinks are returning 404. If I refresh the permalinks within the WordPress Permalinks admin page, everything works right away.

Complete code:

function qd_settings_api_init() {
  add_settings_section(
    'qd_theme_setting_section',
    'Theme Reading Settings',
    'qd_theme_setting_section_callback_function',
    'reading'
  );

  add_settings_field(
    'qd_news_page',
    'News Page',
    'qd_news_page_dropdown_cbf',
    'reading',
    'qd_theme_setting_section'
  );
  register_setting( 'reading', 'qd_news_page' );

}

add_action( 'admin_init', 'qd_settings_api_init' );

//FLUSH THE PERMALINKS WHEN THIS OPTION IS SAVED
function qd_flush_rules() { 
  flush_rewrite_rules(); 
  echo "News Page updated - " . get_option('qd_news_page');
} 

add_action('update_option_qd_news_page', 'qd_flush_rules');

function qd_theme_setting_section_callback_function() {
    echo "<p>Setting Instructions</p>";
}

function qd_news_page_dropdown_cbf() {
  $args = array(
    'depth'                 => 0,
    'child_of'              => 0,
    'selected'              => get_option( 'qd_news_page' ),
    'echo'                  => 1,
    'name'                  => 'qd_news_page',
    'id'                    => 'qd_news_page', // string
    'show_option_none'      => '&mdash; Select &mdash;', // string
    'show_option_no_change' => null, // string
    'option_none_value'     => '0', // string
  );
  wp_dropdown_pages( $args );
} 

update 12/8/15 11:24am est

Want to clarify that the custom settings are not directly creating permalink structure, but are being used by custom post types to assign their rewrite rules.

An excerpt of this code is below:

function qd_custom_post_types() { 
    $post_type_slug = "/" .  get_page_uri( get_option('qd_news_page') );

    register_post_type( 'qd_news', 
        array( 'labels' => array(
            ...
            'rewrite'   => array( 'slug' => $post_type_slug . '/article', 'with_front' => false ),
            ...
        )
    );  
}
add_action( 'init', 'qd_custom_post_types');`
5
  • Maybe I'm off, but do options really need to be flushed? What happens when you use flush_rewrite_rules(true)? That should adjust your .htaccess file (assuming you have permissions to write). Also, try to flush them on shutdown instead of right away. What are you doing to actually change your permalinks?
    – jgraup
    Commented Dec 8, 2015 at 4:12
  • If I had to guess, you're flushing rewrites before your rules are added. What action do you add rules on?
    – Milo
    Commented Dec 8, 2015 at 5:09
  • @Milo, I am using the update_option_qd_news_page action, which does fire. It also does seem to fire after the setting is saved, because when it performs the echo in the qd_flush_rules function, it outputs the correct page ID from the custom setting.
    – Eric K
    Commented Dec 8, 2015 at 13:38
  • you're adding rules on the update_option action?
    – Milo
    Commented Dec 8, 2015 at 15:19
  • I've updated the question to add some additional clarification to how this setting is being used.
    – Eric K
    Commented Dec 8, 2015 at 16:28

1 Answer 1

4
+50

Does this work for you? Seems to work when I try it.

  function qd_settings_api_init() {
  add_settings_section(
    'qd_theme_setting_section',
    'Theme Reading Settings',
    'qd_theme_setting_section_callback_function',
    'reading'
  );

  add_settings_field(
    'qd_news_page',
    'News Page',
    'qd_news_page_dropdown_cbf',
    'reading',
    'qd_theme_setting_section'
  );
  if (delete_transient('qd_flush_rules')) flush_rewrite_rules(); // * Added
  register_setting( 'reading', 'qd_news_page', 'qd_sanitize' ); // * Changed

}

/* Added this function. */
function qd_sanitize($input) {
    set_transient('qd_flush_rules');
    return $input;
}

add_action( 'admin_init', 'qd_settings_api_init' );

//FLUSH THE PERMALINKS WHEN THIS OPTION IS SAVED
function qd_flush_rules() { 
  flush_rewrite_rules(); 
  echo "News Page updated - " . get_option('qd_news_page');
} 

add_action('update_option_qd_news_page', 'qd_flush_rules');

function qd_theme_setting_section_callback_function() {
    echo "<p>Setting Instructions</p>";
}

function qd_news_page_dropdown_cbf() {
  $args = array(
    'depth'                 => 0,
    'child_of'              => 0,
    'selected'              => get_option( 'qd_news_page' ),
    'echo'                  => 1,
    'name'                  => 'qd_news_page',
    'id'                    => 'qd_news_page', // string
    'show_option_none'      => '&mdash; Select &mdash;', // string
    'show_option_no_change' => null, // string
    'option_none_value'     => '0', // string
  );
  wp_dropdown_pages( $args );
} 

//

function qd_custom_post_types() { 
    $post_type_slug = "/" .  get_page_uri( get_option('qd_news_page') );

    register_post_type( 'qd_news', 
        array(
            'labels' => array(
            'name' => __( 'Articles' ),
            'singular_name' => __( 'Article' )
        ),
        'public' => true,
        'has_archive' => true,
        'rewrite'   => array( 'slug' => $post_type_slug . '/article', 'with_front' => false ),
    )
  );
}
add_action( 'init', 'qd_custom_post_types');
3
  • For explanation, see wordpress.stackexchange.com/a/47750/57034
    – bonger
    Commented Dec 12, 2015 at 15:01
  • 1
    Genius! I don't think I know about WordPress Transients, so this has helped me learn that concept too. Thanks for the great answer!
    – Eric K
    Commented Dec 15, 2015 at 17:12
  • 1
    Thanks, Megan, That solved my puzzle :)
    – Ahmad Wael
    Commented Mar 8, 2023 at 21:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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