0

I have created a way of choosing different layouts for posts(sidebar right, sidebar left, full width). This is done through a meta box that displays radio buttons with an image for each layout type. When I, for example, select the first layout image single.php file is loaded, when I chose the second image single-template-1.php file is loaded and when I chose the third image single-template-2.php is loaded.

Now, this all works well, but I can't stop thinking that this might be a messy approach as the only difference between the 3 single templates is that single-template-1.php displays the sidebar on the left and single-template-2.php doesn't display sidebar at all.

I am just wondering if this is the way to go about it or if there is a way to incorporate this functionality in just one single.php file which could be a cleaner solution.

meta box code which is responsible for loading the different single templates:

<?php

function my_theme_add_meta_box_post_template_switcher() {

add_meta_box( 'my_theme-post-layout', __( 'Post template', 'my_theme' ), 'my_theme_show_post_template_switcher', 'post', 'normal', 'high' );
}

add_action( 'add_meta_boxes', 'my_theme_add_meta_box_post_template_switcher' );


function my_theme_show_post_template_switcher( $post ) {
$template = get_post_meta( $post->ID, '_my_theme_post_template', true );

// Default template for new posts
if( empty( $template ) ) {
    $template = 'default';
}

wp_nonce_field( 'save_post_template', 'post_template' );

?>
<fieldset class="clearfix">
<div class="post-layout">
    <label for="default-post" id="default-post-layout">
        <input type="radio" id="default-post" name="_my_theme_post_template" value="default" <?php checked( $template, 'default' ); ?> />
        <img width="150" height="100" src="<?php echo get_template_directory_uri(); ?>/admin/images/default.png" >
        <span> <?php _e( 'Default', 'my_theme' ); ?> </span>
    </label>
</div>
<div class="post-layout">
    <label for="sidebar-left-post">
        <input type="radio" id="sidebar-left-post" name="_my_theme_post_template" value="template-1" <?php checked( $template, 'template-1' ); ?> />
        <img width="150" height="100" src="<?php echo get_template_directory_uri(); ?>/admin/images/left-sidebar.png" >
        <span> <?php _e( 'Sidebar left', 'my_theme' ); ?> </span>
    </label>
</div>
<div class="post-layout">
    <label for="full-width-post">
        <input type="radio" id="full-width-post" name="_my_theme_post_template" value="template-2" <?php checked( $template, 'template-2' ); ?> />
        <img width="150" height="100" src="<?php echo get_template_directory_uri(); ?>/admin/images/full-width-layout.png" >
        <span> <?php _e( 'Full width', 'my_theme' ); ?> </span>
    </label>
</div>
</fieldset>
<?php
}

function my_theme_save_post_template( $post_id ) {
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
    return;
}

if( !isset( $_POST['post_template'] ) || !wp_verify_nonce( $_POST['post_template'], 'save_post_template' ) ) {
    return;
}

if( !current_user_can( 'edit_post' ) ) {
    return;
}

if( isset( $_POST['_my_theme_post_template'] ) ) {
    update_post_meta( $post_id, '_my_theme_post_template', esc_attr( strip_tags( $_POST['_my_theme_post_template'] ) ) );
}
}

add_action( 'save_post', 'my_theme_save_post_template' );


function my_theme_get_post_template_for_template_loader( $template ) {
$post = get_queried_object();

if ( $post ) {

    $post_template = get_post_meta( $post->ID, '_my_theme_post_template', true );

    if ( !empty( $post_template) && $post_template != 'default' ) {
      $template = get_stylesheet_directory() . "/single-{$post_template}.php";
    }
}

return $template;
}

My single.php file:

<?php get_header(); ?>

<div class="main-content col-md-8" role="main">

    <?php while (have_posts()) : the_post(); ?>

        <?php get_template_part( 'content', get_post_format() ); ?>

        <?php comments_template(); ?>
    <?php endwhile; ?>
</div> <!-- end .main-content -->


<?php get_sidebar(); ?>

<?php get_footer(); ?>

My single-template-1.php, the sidebar left template:

<?php get_header(); ?>

<?php get_sidebar(); ?>

<div class="main-content col-md-8" role="main">

    <?php while (have_posts()) : the_post(); ?>

        <?php get_template_part( 'content', get_post_format() ); ?>

        <?php comments_template(); ?>
    <?php endwhile; ?>
</div> <!-- end .main-content -->

<?php get_footer(); ?>

My single-template-2.php, full width template:

<?php get_header(); ?>

<div class="main-content col-md-12" role="main">

    <?php while (have_posts()) : the_post(); ?>

        <?php get_template_part( 'content', get_post_format() ); ?>

        <?php comments_template(); ?>
    <?php endwhile; ?>
</div> <!-- end .main-content -->

<?php get_footer(); ?>

I am just wondering if this is a good approach or if there is a better way.

1

The differences does not seem to be big enough to make it worth 3 different templates.

You can probably just use the body_class filter to add a class based on the meta and adjust the CSS to hide or show the sidebar at a specific location based on the class.

  • Yes, that's what I thought, the differences don't justify 3 different templates.. I am thinking that the ideal solution would be for meta boxes to load different sections of the same single.php file instead of different single templates. just haven't figured out how to tweak this code to work like that yet. – Madeirense Nov 27 '15 at 11:36
  • Or even have different single.php parts loaded according to the meta box item selected. – Madeirense Nov 27 '15 at 11:38
  • different parts are possible but then you are going in the direction of different templates. The main question is if the no sidebar option is something that is going to be used a lot, in which case hiding it with CSS is not optimal. If your default is to have a sidebar then I would stay with only CSS styling instead of having more php fragments. – Mark Kaplun Nov 27 '15 at 11:53
  • I think using different parts would be ideal. So what I am thinking is to have one single.php then have different parts called into single.php. Then tweak the meat boxes code to load different parts according to which type of layout I wish to display the posts as. I am just struggling how to tweak the meta boxes code to associate the selectable images with the different parts of single.php instead of associating them with different single templates. – Madeirense Nov 27 '15 at 12:02
  • Do you reckon it is possible to achieve this? – Madeirense Nov 27 '15 at 12:08
0

You won't need three template files, just one will do. Save your meta value as class names. For example, default value as col-md-8, left sidebar as col-md-8 pull-right and full width as col-xs-12.

Then a function to echo the classes to main content div.

function wpse_210044_layout_classes() {
    global $post;
    $template = get_post_meta( $post->ID, '_my_theme_post_template', true );

    esc_attr_e( $template );

    //Or you can just compare the existing values and echo relavant classes.
    //In that case, you don't need to save the meta value as class names.
}

Then at single.php

<?php get_header(); ?>

<div class="main-content <?php wpse_210044_layout_classes();?>" role="main">

    <?php while (have_posts()) : the_post(); ?>

        <?php get_template_part( 'content', get_post_format() ); ?>

        <?php comments_template(); ?>
    <?php endwhile; ?>
</div> <!-- end .main-content -->


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

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.