Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Let me set the scene:

I have a CPT that will work on a multi-site installation and some of the sites will be in a different language. For example my CPT is Case Studies I would use a URL structure like: /case-studies/%post_id%/%postname%/ but if the site language is different then case-studies is no longer that.

In WP settings you can set a page as your posts page. This essentially sets the front to your permalink structure. What I want to do is add an extra drop down for my CPT that allows to set the front page for the posts of that CPT. Thus if the language is different then the permalink structure can match that language.

Add setting here

So is it possible to extend the settings using the Settings API in the location shown in the above image? If yes then how would I do that? If no then where would be a suitable place to place my CPT setting? (Bonus points if you can provide some code samples)

share|improve this question
add comment

2 Answers

It appears that the options-reading.php file is hard-coding its options, rather than using the Settings API.

And that option is using wp_dropdown_pages() specifically. The Codex lists the following arguments for wp_dropdown_pages():

$args = array(
    'depth'            => 0,
    'child_of'         => 0,
    'selected'         => 0,
    'echo'             => 1,
    'name'             => 'page_id'); 

The Codex page also indicates that this function theoretically can take any argument that can be passed to get_pages(), which includes a post_type argument:

$args = array(
    'child_of'     => 0,
    'sort_order'   => 'ASC',
    'sort_column'  => 'post_title',
    'hierarchical' => 1,
    'exclude'      => ,
    'include'      => ,
    'meta_key'     => ,
    'meta_value'   => ,
    'authors'      => ,
    'exclude_tree' => ,
    'post_type' => 'page',

...which means that theoretically wp_dropdown_menu() could be modified to return your Custom Post Type posts.

Note that wp_dropdown_pages() does have an output filter hook, wp_dropdown_pages:

$output = apply_filters('wp_dropdown_pages', $output);

...so maybe you could use the filter somehow to target the page_on_front select form field specifically:

wp_dropdown_pages( array( 'name' => 'page_on_front', 'echo' => 0, 'show_option_none' => __( '&mdash; Select &mdash;' ), 'option_none_value' => '0', 'selected' => get_option( 'page_on_front' ) ) ) );


From this comment:

What I want to do is set a page as posts page for my CPT, just like you can do for posts

I'm still not sure that the core settings are really extensible in this manner, but you do have alternatives.

The most obvious one would be to create a custom Page template that is a "page for Posts", in which you query your specific Custom Post Type.

Mostly copy-pasta from the Codex link; you'll want to modify the markup to fit in with your Theme:

 * Template Name: Case Studies

<?php get_header(); ?>

<div id="content">

$type = 'case-studies'; // Use the correct CPT slug here
  'post_type' => $type,
  'post_status' => 'publish',
  'paged' => $paged,
  'caller_get_posts'=> 1 // do not show sticky posts
// This bit is a "hack" to allow pagination to work properly
$temp = $wp_query;    
$wp_query = null;
$wp_query = new WP_Query($args); 


 get_template_part( 'loop', 'index' );
 // Restore the original $wp_query
 $wp_query = $temp

</div><!-- #content -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>

Then, of course, just create a page, and assign it the "Case Studies" template.

share|improve this answer
I've had a delve into options-reading.php and saw it was hard coded so accepted that I'll have to make a settings page of my own. –  Brady Nov 2 '11 at 14:35
I think you have miss-understood me on the CPT posts dropdown thing. What I want to do is set a page as posts page for my CPT, just like you can do for posts. So all I have to do is use wp_dropdown_pages() as its was meant as I want to list the pages. No need to filter or hook here –  Brady Nov 2 '11 at 14:37
Oh, you're right! Let me modify my answer to provide an alternative. –  Chip Bennett Nov 2 '11 at 14:47
add comment
up vote 0 down vote accepted

I've gone with this the following approach:

I already had a theme options page using the Settings API and because this CPT I have setup is part of the theme it only made sense to add this option to the theme options. Below is the code if anyone wants to use:

// Add settings to menu
add_action( 'admin_menu', 'sc_hi_rezz_theme_options_add_page' );
function sc_hi_rezz_theme_options_add_page() {
        __( 'Theme Options', 'hi-rezz' ),
        __( 'Theme Options', 'hi-rezz' ),

// see https://make.wordpress.org/themes/2011/07/01/wordpress-3-2-fixing-the-edit_theme_optionsmanage_options-bug/
function hi_rezz_get_options_page_cap() {
    return 'edit_theme_options';
add_filter( 'option_page_capability_hi-rezz-options', 'hi_rezz_get_options_page_cap' );

// Fix Cap to allow editors to edit theme options
function sc_hi_rezz_get_options_page_cap() {
    return 'edit_theme_options';
add_filter( 'option_page_capability_hi-rezz-options', 'sc_hi_rezz_get_options_page_cap' );

// Options Page Layout
function sc_hi_rezz_theme_options_do_page() {
    <div class="wrap">
        <?php screen_icon(); ?>
        <h2><?php _e( 'Theme Options', 'hi-rezz' ) ?></h2>
        <form action="options.php" method="post">
            settings_fields( "hi_rezz_theme_options" );
            do_settings_sections( "theme_options" );
            <?php submit_button( __( "Save changes", "hi-rezz" ), "primary", "submit", true ); ?>

// Register Settings
add_action( 'admin_init', 'sc_hi_rezz_theme_settings_register' );
function sc_hi_rezz_theme_settings_register() {
    register_setting("hi_rezz_theme_options", "hi_rezz_theme_options", "sc_hi_rezz_theme_settings_validate"); // Register Main Settings
    add_settings_section("sc_hi-rezz_text", __("Text / Copy", "hi-rezz"), "hi_rezz_theme_settings_dummy", "theme_options"); // Make settings text section
    add_settings_section("sc_hi-rezz_cpt_settings", __("Custom Post Type Settings", "hi-rezz"), "hi_rezz_theme_settings_dummy", "theme_options"); // Make settings text section
    add_settings_field("hi_rezz_theme_settings_footer_copy", __("Footer copy", "hi-rezz"), "hi_rezz_theme_settings_footer_copy_field", "theme_options", "sc_hi-rezz_text");
    add_settings_field("hi_rezz_theme_settings_cpt_cs_page", __("Page for case studies", "hi-rezz"), "hi_rezz_theme_settings_cpt_cs_field", "theme_options", "sc_hi-rezz_cpt_settings");
function hi_rezz_theme_settings_dummy() { }

// Validate Settings
function sc_hi_rezz_theme_settings_validate($input) {
    $valid = get_option("hi_rezz_theme_options");
    $valid['sc_footer_copy'] = wp_filter_post_kses( $input['sc_footer_copy'] );
    $valid['sc_cpt_cas_study_page'] = (int) $input['sc_cpt_cas_study_page'];
    return $valid;

//Settings Fields
function hi_rezz_theme_settings_footer_copy_field() {
    $options = get_option("hi_rezz_theme_options");
    ?><textarea rows="4" cols="50" name="hi_rezz_theme_options[sc_footer_copy]" id="hi_rezz_theme_settings_footer_copy"><?php echo esc_textarea($options['sc_footer_copy']); ?></textarea><?php
function hi_rezz_theme_settings_cpt_cs_field() {
    $options = get_option("hi_rezz_theme_options");
             'name' => 'hi_rezz_theme_options[sc_cpt_cas_study_page]',
             'echo' => 1,
             'show_option_none' => __( '&mdash; Select &mdash;' ),
             'option_none_value' => '0',
             'selected' => $options['sc_cpt_cas_study_page']

The above gives me:

My CPT settings

share|improve this answer
add comment

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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