• I want to display 3 posts on the homepage of my website. I don’t think the widget is the best approach though as I want to display them in the same format they’re on the actually post page with image, meta data, heading and excerpt.

    I thought I’d be able to duplicate the code and dump it on the homepage but that doesn’t seem to work and I’d still need to limit the amount of posts.

    Apologies if this isn’t the right code/the code you need to make a call on this, but I think this is my post list code:

    
    <!-- article -->
    <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    
    	<!-- post thumbnail -->
    	<?php if ( has_post_thumbnail()) : // Check if thumbnail exists ?>
    		<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
    			<?php the_post_thumbnail(array(120,120)); // Declare pixel size you need inside the array ?>
    		</a>
    	<?php endif; ?>
    	<!-- /post thumbnail -->
    
    	<!-- post title -->
    	<h2>
    		<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a>
    	</h2>
    	<!-- /post title -->
    
    	<!-- post details -->
    	<span class="date"><?php the_time('F j, Y'); ?> <?php the_time('g:i a'); ?></span>
    	<span class="author"><?php _e( 'Published by', 'html5blank' ); ?> <?php the_author_posts_link(); ?></span>
    	<span class="comments"><?php if (comments_open( get_the_ID() ) ) comments_popup_link( __( 'Leave your thoughts', 'html5blank' ), __( '1 Comment', 'html5blank' ), __( '% Comments', 'html5blank' )); ?></span>
    	<!-- /post details -->
    
    	<?php html5wp_excerpt('html5wp_index'); // Build your custom callback length in functions.php ?>
    
    	<?php edit_post_link(); ?>
    
    </article>
    <!-- /article -->
    

    Also, I have a custom post type that I also want to pull into the homepage. Another problem I have this this is setting a parent page for it. If I create a post I can see there is an index page but I don’t know how to set this in the main nav?

    In my functions.php I have the follow which looks like it creates the Custom Post Type:

    
    function create_post_type_html5()
    {
        register_taxonomy_for_object_type('category', 'html5-blank'); // Register Taxonomies for Category
        register_taxonomy_for_object_type('post_tag', 'html5-blank');
        register_post_type('html5-blank', // Register Custom Post Type
            array(
            'labels' => array(
                'name' => __('HTML5 Blank Custom Post', 'html5blank'), // Rename these to suit
                'singular_name' => __('HTML5 Blank Custom Post', 'html5blank'),
                'add_new' => __('Add New', 'html5blank'),
                'add_new_item' => __('Add New HTML5 Blank Custom Post', 'html5blank'),
                'edit' => __('Edit', 'html5blank'),
                'edit_item' => __('Edit HTML5 Blank Custom Post', 'html5blank'),
                'new_item' => __('New HTML5 Blank Custom Post', 'html5blank'),
                'view' => __('View HTML5 Blank Custom Post', 'html5blank'),
                'view_item' => __('View HTML5 Blank Custom Post', 'html5blank'),
                'search_items' => __('Search HTML5 Blank Custom Post', 'html5blank'),
                'not_found' => __('No HTML5 Blank Custom Posts found', 'html5blank'),
                'not_found_in_trash' => __('No HTML5 Blank Custom Posts found in Trash', 'html5blank')
            ),
            'public' => true,
            'hierarchical' => true, // Allows your posts to behave like Hierarchy Pages
            'has_archive' => true,
            'supports' => array(
                'title',
                'editor',
                'excerpt',
                'thumbnail'
            ), // Go to Dashboard Custom HTML5 Blank post for supports
            'can_export' => true, // Allows export in Tools > Export
            'taxonomies' => array(
                'post_tag',
                'category'
            ) // Add Category and Post Tags support
        ));
    }
    

    I hope that helps you, help me 😉 It’s all very new to me.

    Will the Custom Post Type also use the same code as the default Post type? I’ll need different classes on it so I was wondering if I’ll need to use a different template.

Viewing 15 replies - 1 through 15 (of 31 total)
  • For display post you have to use post loop
    Add the following code where you want to show 3 blog post

    <?php
    $args = array( 'post_type' => 'post', 'posts_per_page' => 3 );
    $loop = new WP_Query( $args );
    while ( $loop->have_posts() ) : $loop->the_post(); ?>
          <!-- article -->
    <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    
    	<!-- post thumbnail -->
    	<?php if ( has_post_thumbnail()) : // Check if thumbnail exists ?>
    		<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
    			<?php the_post_thumbnail(array(120,120)); // Declare pixel size you need inside the array ?>
    		</a>
    	<?php endif; ?>
    	<!-- /post thumbnail -->
    
    	<!-- post title -->
    	<h2>
    		<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a>
    	</h2>
    	<!-- /post title -->
    
    	<!-- post details -->
    	<span class="date"><?php the_time('F j, Y'); ?> <?php the_time('g:i a'); ?></span>
    	<span class="author"><?php _e( 'Published by', 'html5blank' ); ?> <?php the_author_posts_link(); ?></span>
    	<span class="comments"><?php if (comments_open( get_the_ID() ) ) comments_popup_link( __( 'Leave your thoughts', 'html5blank' ), __( '1 Comment', 'html5blank' ), __( '% Comments', 'html5blank' )); ?></span>
    	<!-- /post details -->
    
    	<?php html5wp_excerpt('html5wp_index'); // Build your custom callback length in functions.php ?>
    
    	<?php edit_post_link(); ?>
    
    </article>
    <!-- /article -->
      
    <?php endwhile; ?>

    Follow this link to create a custom post type in WordPress
    https://codex.ww.wp.xz.cn/Function_Reference/register_post_type

    To display custom post type you have to almost use the same code as default post type just change the post-type from post to your custom slug

    Moderator bcworkz

    (@bcworkz)

    The list code you posted is essentially the internals of the standard WP loop, which is setup to display the results of the main query. In the case of your front page, the main query is the front page. And without the loop mechanism to drive the internals, nothing will work. To get other posts displayed on the front page template, you need to make custom queries, then run a similar but different sort of loop to display the results. See Class Reference/WP Query. Inside this similar loop, the internals you posted will then work correctly for the most part, regardless of what post type was queried. There may be specifics that do not apply, such as post format.

    Whatever you want the query to get, custom post type, number of posts, particular class, etc., it is all specified in the WP_Query arguments passed when a new WP_Query object is instantiated.

    The index page for custom post types are not actual pages that will be listed on the menu screen. To add one to the menu, use a custom link menu widget and simply enter the URL to the page along with your preferred label.

    Thread Starter moymadethis

    (@moymadethis)

    Is that covered in the code provided by @poonam9?

    I think this might be a little too advanced for me, so maybe I’m getting ahead of myself a little!

    I get what you’re saying about the custom post types. If I create a Custom Post and ‘view’ it. I can see part of the URL is /html5-blank/. So I created a page called “Case Studies” and edited the URL to match that and it seems to work. Is that the way you meant me to do it?

    Do Custom Post Types use the same loop as the default post type? If so, I guess I’ll need to duplicate that php file and set the Custom Post Type to use that instead?

    Thread Starter moymadethis

    (@moymadethis)

    I figured out I could just duplicate loop.php, rename it to loop-custom.php (for example), change what I needed and then load it on my Custom Post page with <?php get_template_part('loop-custom'); ?>. Didn’t realise get_template_part would pull in a php file of that name …see, that’s how much of a noob I am!

    If I paste <?php get_template_part('loop'); ?> onto the homepage it will load all the posts onto that page as it would the blog page, minus pagination, correct?

    Is there away of wrapping that snippet of code in a condition to only show the latest 3 posts? Rater than pasting the contents of loop.php onto the homepage? Figured maybe it’s not a good idea to maintain 2 identical loops over 2 pages?

    EDIT

    Sorry, I forgot that the homepage was the main query like you said. So I need to look at another approach. Am I on the right track with something like:

    
    <?php
        $latest_blog_posts = new WP_Query( array( 'posts_per_page' => 3 ) );
        if ( $latest_blog_posts->have_posts() ) : while ( $latest_blog_posts->have_posts() ) : $latest_blog_posts->the_post();
    
            get_template_part('loop');
    
        endwhile; endif;
    ?>
    

    Though this just spits out 3 posts with the heading “Home” for now!

    • This reply was modified 9 years, 2 months ago by moymadethis.
    • This reply was modified 9 years, 2 months ago by moymadethis.
    Moderator bcworkz

    (@bcworkz)

    I’m tempted to leave you alone just to see what else you can learn on your own.

    Just kidding! But seriously, kudos for working things out on your own. You can add any number of additional arguments to the array passed to new WP_Query(). In particular a ‘post_type’ argument if that is what you want. The query could be further qualified by category, post meta, author, date, all sorts of things. As specified in the class reference I initially linked to.

    You can make as many queries as needed on your front page template, along with loop and template parts to output the query results. These can be used like modules to assemble all the various content desired into a complete front page. Getting all the output to look cohesive is the job of CSS. Not only can the loop code have different elements and classes, but the main template code can contain the various “modules” in their own elements and classes so CSS can target the various parts individually or collectively to style them as desired.

    You’ve learned how to construct the basic building blocks. Alter the query arguments to get different content and use CSS to make each block look good. Assemble all the blocks on the front page template to create an awesome front page!

    Thread Starter moymadethis

    (@moymadethis)

    Noooo! This is why I’ve always had back-end dev’s around to do this haha!

    Can I use wp_reset_query(); to reset the WordPress query after looping through the custom query so it reverts back to the default query for the current page? I friend told me to use that but I couldn’t get it to work. Is that due to how my loop.php is set up?

    There has to be an easier/better way than just duplicating the code from loop.php onto the homepage, right? Though I am tempted to do that just to get it done haha!

    Moderator bcworkz

    (@bcworkz)

    Yes, we should always call wp_reset_query() after making a custom query. It shouldn’t make any difference on a single post or page, including a front page, because the main query is only for the one page. There are no more pages in the main query to output. As long as the other custom queries also completed their loops, we essentially have the same completed state whether the queries were reset or not. Still, it’s the right thing to do.

    What are you seeing or not seeing that leads you to believe it’s not working?

    I’m not sure all of what’s on your loop.php. The way you’ve included it with get_template_part() inside a loop, it should not have any actual loop code — the while have_posts():the_post() part. It should only have code for the loop internals. For example, in the twentysixteen default theme, the files in the template-parts folder are only loop internals, there is no actual loop code, only what is output for each post. These templates generally start with an overall containing <article> tag, within which there’s a header tag for the title. There’s a content div followed by a <footer> tag that contains post meta like date, permalink, author, categories, etc. Nothing else.

    If your loop.php does have actual loop code, that’s a problem because you have nested loops operating off a single query. One of the loops will not properly complete.

    Since the loop internals contain much of the tags and classes used to style each post, it only makes sense to reuse the template part for other queries if you want the posts to appear the same or at least fairly similar. You can still cause posts to appear differently despite using the same template part by containing all of the query output in a unique container, which is used as part of the CSS selectors so that the rules only apply to posts of that query.

    If the posts from one query are to appear significantly different than those of another query, it would make sense to create a different template part that outputs different HTML that’s appropriate for the posts queried. You’ve encountered a classic coding quandary regarding repetitive code. Whether it’s better to simply copy the same thing over and over, making minor changes as needed in each version, or to formalize it into a reusable object that accommodates the minor changes through passed arguments.

    Each situation is different, you’ll need to factor in all effort involved for each approach, as well as any coding aesthetic you may wish to adhere to. Neither way is necessarily wrong, but one will take less effort. Some are willing to expend more effort to produce something more elegant, efficient, and easier to read. Others only care about what’s faster.

    Moderator bcworkz

    (@bcworkz)

    I may have misspoke. In your case, to reset the query, use wp_reset_postdata(). It’s similar to wp_reset_query() but has different applications. I tend to get the two mixed up and can never remember which to use when. wp_reset_query() is used in conjunction with query_posts(), which no one should be using anyway.

    Thread Starter moymadethis

    (@moymadethis)

    Using the code I pasted:

    
    <?php
        $latest_blog_posts = new WP_Query( array( 'posts_per_page' => 3 ) );
        if ( $latest_blog_posts->have_posts() ) : while ( $latest_blog_posts->have_posts() ) : $latest_blog_posts->the_post();
    
            get_template_part('loop');
    
        endwhile; endif;
    ?>
    

    It does display 3 posts on front-page.php but all 3 posts are called “Home”, have the same date and all link to the Homepage. I guess this is because it’s a query, within a query. Is there a way to adjust my loop.php so this works using the code above or something similar?

    The only way I managed to get the 3 latest posts to display on the homepage was to copy and paste the code from loop.php onto front-page.php. That worked …but I guess it’s not ideal to maintaining two lots of code in different locations that essentially do the same thing/are the same thing?

    Unless this is the only way it can be achieved?

    Moderator bcworkz

    (@bcworkz)

    There are many ways to utilize external resources like separate code pages. Of course, how the resource is pulled in needs to be done correctly and the resource code has to be appropriate for the situation. I touched on the use of redundant code in the last round of posts.

    I don’t know what’s on loop.php, but it apparently is inappropriate for this application if you are getting the wrong titles and links. What you could do is initially just code the first few things on the main template, even though it’s largely redundant. Once that is working properly, examine the code to see exactly what is identical and what things change from one version to the other. Decide how to accommodate the changing elements while reusing the redundant code by reference instead of copying.

    One way to reuse code is to define a function that contains all the redundant code and accommodates the variations through passed parameters. Then instead of copying the code and altering a few things, call the function, passing those few things as arguments.

    As you’ve seen, add_template_part() is another way. The problem here is you cannot pass parameters except as global values. WP template parts make extensive use of globals, in particular $post to manage variations on each template part. Template parts are analogous to using PHP include statements to pull in other code pages.

    Thread Starter moymadethis

    (@moymadethis)

    Ok, this is the solution I’ve ended up using. It seems to work but I’d appreciate any pointing out flaws if they see any…

    I amended my loop.php so the wrapping if/else statement was removed. This left loop.php looking like this:

    
    <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    
        <!-- post thumbnail -->
        <?php if ( has_post_thumbnail()) : // Check if thumbnail exists ?>
            <a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>" class="h-entry__image-link">
                <?php the_post_thumbnail(array(120,120)); // Declare pixel size you need inside the array ?>
            </a>
        <?php endif; ?>
        <!-- /post thumbnail -->
    
        <!-- post title -->
        <h2 class="p-name">
            <a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a>
        </h2>
        <!-- /post title -->
    
        <!-- post details -->
        <time datetime="<?php the_time('Y-m-j'); ?>" class="dt-published"><?php the_time('jS F Y'); ?></time>
        <!-- /post details -->
    
        <?php html5wp_summary('html5wp_index'); // Build your custom callback length in functions.php ?>
    
        <p><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>" class="arrow-link">Read the full article</a></p>
    
        <?php edit_post_link(); ?>
    
    </article>
    

    The part this was removed was this:

    
    <?php if (have_posts()): while (have_posts()) : the_post(); ?>
    
       [ARTICLE CODE WAS IN HERE]
    
    <?php endwhile; ?>
    
    <?php else: ?>
    
        <!-- article -->
        <article>
            <h2><?php _e( 'Sorry, nothing to display.', 'html5blank' ); ?></h2>
        </article>
        <!-- /article -->
    
    <?php endif; ?>
    

    This allowed me to use the following code on the homepage to pull in the latest 3 posts:

    
    <div class="h-feed featured-blog">
    	<?php
    	    $args = array(
    		    'posts_per_page'    => 3,
    		    'post_type'     => 'post',  //choose post type here
    		    'order' => 'DESC',
    		);
    		// query
    		$the_query = new WP_Query( $args );
    		
    		
    		if( $the_query->have_posts() ):
    		    while( $the_query->have_posts() ) : $the_query->the_post();
    		        get_template_part('loop');
    		    endwhile; 
    		else :
    		
    		endif;
    	?>
    </div>
    

    This gets the posts working on the homepage (front-page.php) great. I had to wrap the code in the parent div markup. This mightn’t be ideal on other sites but it actually works quite well for me here as I need to be able to add different classes on the blog/home page.

    The big issue with this was that only 1 post was displayed on the blog page as the code loading it looked like this:

    
    <?php get_template_part('loop'); ?>
    

    I amended this by wrapping the if/else statement around the get_template_part so it now looks like this:

    
    <?php if (have_posts()): while (have_posts()) : the_post(); ?>
    
    <?php get_template_part('loop'); ?>
    
    <?php endwhile; ?>
    
    <?php else: ?>
    
    	<!-- article -->
    	<article>
    		<h2><?php _e( 'Sorry, nothing to display.', 'html5blank' ); ?></h2>
    	</article>
    	
    	<!-- /article -->
    	
    <?php endif; ?>
    
    <?php get_template_part('pagination'); ?>
    

    That all seems to work. I was even able to use the same code for my Custom Post Type changing 'post_type' => 'post' to 'post_type' => 'custom-post-name' to pull those posts onto the homepage.

    I’ve not checked if the pagination still works and what happens when 10+ posts are on the page but can anyone see any problems with what I’ve done?

    Thanks again for all your help and time giving me information on this. I still don’t fully understand but at least we’re getting there haha!

    Moderator bcworkz

    (@bcworkz)

    Looks good AFAICT!

    I’m not sure if pagination is supposed to work in the first place as this is the home page. It depends on what you are expecting and what query the pagination code thinks it’s supposed to be working with. To reset everything back to the main query, don’t forget to call wp_reset_postdata() after each custom query loop completes.

    The pagination may need to be custom coded. I can help you with that if that is what’s needed, but you’ll need to accurately describe what criteria constitutes a group of pages, including how it’s ordered.

    Thread Starter moymadethis

    (@moymadethis)

    Great!

    No the pagination wouldn’t go on the homepage, just on the Post and Custom Post index pages. Thankfully I added 10+ Posts to both and the pagination automatically appeared when I included <?php get_template_part('pagination'); ?> on both pages!

    To reset everything, do you mean put wp_reset_postdata() before the closing PHP tag? So…

    
    <!-- article -->
    <article id="post-<?php the_ID(); ?>" <?php post_class('h-entry'); ?>>
    
    	<!-- post thumbnail -->
    	<?php if ( has_post_thumbnail()) : // Check if thumbnail exists ?>
    		<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>" class="h-entry__image-link">
    			<?php the_post_thumbnail(array(120,120),array('class' => 'your-class-name')); // Declare pixel size you need inside the array ?>
    		</a>
    	<?php endif; ?>
    	<!-- /post thumbnail -->
    
    	<!-- post title -->
    	<h2 class="p-name">
    		<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a>
    	</h2>
    	<!-- /post title -->
    
    	<!-- post details -->
    	<time datetime="<?php the_time('Y-m-j'); ?>" class="dt-published"><?php the_time('jS F Y'); ?></time>
    	<!-- /post details -->
    
    	<?php html5wp_summary('html5wp_index'); // Build your custom callback length in functions.php ?>
    	
    	<p><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>" class="arrow-link">Read the full article</a></p>
    
    	<?php edit_post_link(); ?>
    	
    	 <!--  Restore original Post Data -->
    	wp_reset_postdata();
    
    </article>
    

    Or do you mean on the page the loop is pulled into like…

    
    <div class="h-feed featured-projects">
    	<?php
    	    $args = array(
    		    'posts_per_page'    => 3,
    		    'post_type'     => 'html5-blank',  //choose post type here
    		    'order' => 'DESC',
    		);
    		// query
    		$the_query = new WP_Query( $args );
    		
    		
    		if( $the_query->have_posts() ):
    		    while( $the_query->have_posts() ) : $the_query->the_post();
    		        get_template_part('loop-html5-blank');
    		    endwhile; 
    		else :
    		
    		endif;
    		
    		<!--  Restore original Post Data -->
    		wp_reset_postdata();
    
    	?>
    </div>
    

    Thanks for all the help, made real progress. All I need to do now is find out how I can add a generic class to the UL elements in the sidebar so I can style them. Worried targeting .widget > ul might style lists in other widgets that aren’t categories/sub-pages/archives etc.

    Moderator bcworkz

    (@bcworkz)

    Anytime a new WP_Query is created, after the associated loop is run is the right time to reset the data, so your second example would be perfect. IF the first example were a proper location, it would need to be wrapped in <?php ?> tags, otherwise the text “wp_reset_postdata();” would appear on your page as content 🙂

    Yes, .widget > ul is pretty generic and could be applied to other widget output. It’s always nice to have some unique class or ID so an element can be targeted specifically. The unique class doesn’t need to be assigned to the ul element, though that simplifies things. Any unique class or ID that’s an ancestor of the ul group, but is still within the widget can be used to target only the ul group of this widget.

    All widgets should be wrapped in an aside container that has a unique ID, plus a class for the type of widget. The ID should be composed of the widget type plus an instance number. For site specific custom CSS, this ID can be used once the sidebar content is finalized. If the sidebar is later edited and another instance inserted, the custom CSS will not target the proper element.

    Some types of widgets are only used once, or one would want multiple instances to all be styled the same. In either case, the widget type class can be used to isolate the widget’s ul group from other types of widgets with ul groups.

    Depending on what style you are hoping to change, targeting ul may not work. For example, if you want to change a link whose lineage is aside > ul > li > a and the ‘a’ element is assigned a default color, targeting ‘ul’ to change color will not work because the ‘a’ style is more specific. You need to actually target the ‘a’ element with any ancestor attributes that seem usable. If the aside element looks like this:
    <aside id="my_projects-3" class="widget widget_my_projects">

    Target the links in the specific instance with #my_projects-3 a { color: blue; }
    Or target links in all widgets of the type with .widget_my_projects a { color: blue; }

    Of course, if you are writing your own widget, you can add classes to any elements in the widget() method. If you are styling a provided widget, you should avoid editing the widget code. But do check the code for any filters or actions that might be useful. If not, selectors using aside attributes as I described should work.

    Thread Starter moymadethis

    (@moymadethis)

    Great, I managed to add wp_reset_postdata(); like in the (2nd) example I gave above.

    However, I found it a bit difficult on pages where the code appears like this:

    
    <?php if (have_posts()): while (have_posts()) : the_post(); ?>
    
    <?php get_template_part('loop'); ?>
    
    <?php endwhile; ?>
    <?php else: ?>
    	<!-- article -->
    	<article>
    		<h2><?php _e( 'Sorry, nothing to display.', 'html5blank' ); ?></h2>
    	</article>
    	<!-- /article -->
    <?php endif; ?>
    
    <?php get_template_part('pagination'); ?>
    

    Does that mean I need to include the code like <?php wp_reset_postdata(); ?> but just after <?php get_template_part('loop'); ?>? Or is there a better place to put it?

    I noticed my parent theme had the following code in it’s functions.php:

    
    if (function_exists('register_sidebar'))
    {
        // Define Sidebar Widget Area 1
        register_sidebar(array(
            'name' => __('Widget Area 1', 'html5blank'),
            'description' => __('Description for this widget-area...', 'html5blank'),
            'id' => 'widget-area-1',
            'before_widget' => '<div id="%1$s" class="%2$s">',
            'after_widget' => '</div>',
            'before_title' => '<h3>',
            'after_title' => '</h3>'
        ));
    
        // Define Sidebar Widget Area 2
        register_sidebar(array(
            'name' => __('Widget Area 2', 'html5blank'),
            'description' => __('Description for this widget-area...', 'html5blank'),
            'id' => 'widget-area-2',
            'before_widget' => '<div id="%1$s" class="%2$s">',
            'after_widget' => '</div>',
            'before_title' => '<h3>',
            'after_title' => '</h3>'
        ));
    }
    

    I thought about amending the before_widget bit to read:

    
    'before_widget' => '<div id="%1$s" class="%2$s side-nav">',
    

    Which seemed to add the class ok, I just wanted to check that will just target the navigation/category lists before proceeding?

    Thanks again! 🙂

Viewing 15 replies - 1 through 15 (of 31 total)

The topic ‘Loading posts (and custom posts) on homepage’ is closed to new replies.