Main column – the loop

This is the most important section of our WordPress code. It's called the loop, and it's an essential part of your new theme. The loop's job is to display your posts in reverse chronological order, choosing only those posts that are appropriate. You need to put all of your other post tags inside the loop. The basic loop text, which has to surround your post information, is displayed using the following code:

<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
  <?php get_template_part('content', get_post_format()); ?>
<?php endwhile; else: ?>
  <?php get_template_part('content', 'none'); ?>
<?php endif; ?>

The get_template_part() function call that's right in the middle, fetches another file that contains the rest of the loop; but for now, let's just focus on the main section here.

There are two basic parts of the loop, as follows:

The first part is handled by a standard PHP while loop that goes through every post and, for each element, calls the appropriate content-[TYPE].php file. The second part is similar, as it calls the content-none.php file if there are no posts that can be displayed. The use of these various content-[TYPE].php files is currently the standard for handling the different types of content that WordPress displays. It's a lot more effective and clear than working with the individual if or switch clauses.

So, in order to get started with this, let's create a basic content.php file that will serve the role of a placeholder for the default type of content. In this file, let's place the following code, which handles the loop:

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

<header class="entry-header">
  <?php the_title(sprintf('<h1 class="entry-title">
  <a href="%s" rel="bookmark">', esc_url(get_permalink())), '</a></h1>');
  ?>

  <?php if('post' == get_post_type()) : ?>
  <div class="entry-meta">
    <?php daily_cooking_custom_posted_on(); ?>
  </div>
  <?php endif; ?>
</header>

<div class="entry-content">
  <?php
  the_content(sprintf(__('Continue reading %s <span class="meta-nav">&rarr; 
  </span>', 'daily-cooking-custom'), the_title('<span class="screen-reader-
  text">"', '"</span>', false)));

  wp_link_pages(array('before' => '<div class="page-links">' . __('Pages:',  
  'daily-cooking-custom'), 'after'  => '</div>'));
  ?>
</div>

<footer class="entry-footer">
  <?php daily_cooking_custom_entry_footer(); ?>
</footer>

</article><! -  #post-##  - >

If you take a closer look, you'll notice that it's very similar to the static HTML version I shared earlier in this chapter. The only difference is that, instead of the dummy text, there are calls to specific WordPress functions and custom-made functions that we'll discuss shortly.

Let's take it from the top; the file starts with these two lines:

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
  <header class="entry-header">

This is just some standard HTML and basic WordPress function calls to display proper element IDs and CSS classes. For instance, the the_ID() function displays the ID of the post. Next, we have the following line:

<?php the_title(sprintf('<h1 class="entry-title"><a href="%s" rel="bookmark">', esc_url(get_permalink())), '</a></h1>'); ?>

This displays the link and the title of the current content element (which is usually a post), instead of using the dummy text. The the_title() function takes three parameters (which are all optional). Right here, we're using just two. The first one defines the text to place before the title (in this case, we're making a sprintf() function call), and the second one defines the text to place after the title. The following is a piece of code that displays various types of meta information about the current content element:

<?php if('post' == get_post_type()) : ?>
<div class="entry-meta">
  <?php daily_cooking_custom_posted_on(); ?>
</div>
<?php endif; ?>

If what we're dealing with is a standard post, a custom function is called to display the details. This way of handling thingsthrough an additional functionmakes everything much clearer in comparison to placing the code right there. Here's what the function looks like (we can place it in our main functions.php file, or inside a new file in a separate sub-directory called inc, indicating that it holds additional functions; in our case, this function definition can be found in inc\template-tags.php):

function daily_cooking_custom_posted_on() {
  $time_string = '<time class="entry-date published updated" 
  datetime="%1$s">%2$s</time>';
  if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) ) {
    $time_string = '<time class="entry-date published" 
    datetime="%1$s">%2$s</time><time class="updated" 
    datetime="%3$s">%4$s</time>';
  }

  $time_string = sprintf( $time_string,
    esc_attr( get_the_date( 'c' ) ),
    esc_html( get_the_date() ),
    esc_attr( get_the_modified_date( 'c' ) ),
    esc_html( get_the_modified_date() )
  );

  $posted_on = sprintf(
    _x( 'Posted on %s', 'post date', 'daily-cooking-custom' ),
    '<a href="' . esc_url( get_permalink() ) . '" rel="bookmark">'
    . $time_string . '</a>'
  );

  $byline = sprintf(
    _x( 'by %s', 'post author', 'daily-cooking-custom' ),
    '<span class="author vcard"><a class="url fn n" href="' .
    esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) )
    ) . '">' . esc_html( get_the_author() ) . '</a></span>'
  );

  echo '<span class="posted-on">' . $posted_on . '</span><span
  class="byline"> ' . $byline . '</span>';
}

As you can see, this is quite a long function, but the thing to remember is that it's just meant to display the date of when the post was published and the byline of the author. Also, there are language functions (_e() and _x()) used here to fetch translated data from the database. You can learn more about these functions at https://codex.wordpress.org/Function_Reference/_e and https://codex.wordpress.org/Function_Reference/_x.

Going back to our content.php file, we have the following:

<div class="entry-content">
  <?php
  the_content(sprintf(
    __('Continue reading %s <span class="meta-nav">&rarr;</span>', 
     'daily-cooking-custom'),
    the_title('<span class="screen-reader-text">"', '"</span>', false)
  ));

  wp_link_pages(array(
    'before' => '<div class="page-links">' . __('Pages:', 'daily-
    cooking-custom'),
    'after'  => '</div>',
  ));
  ?>
</div>

The first part (the_content()) takes care of displaying the contents of the current post, along with a Continue reading link. This is actually the most important part of the whole file. Next, the second part (wp_link_pages()), is meant to display page links for paginated posts (WordPress allows you to divide your content into individual subpages; this can be useful when dealing with an overly long piece of text). Finally, we have the code for the footer section of the entry, as follows:

<footer class="entry-footer">
  <?php daily_cooking_custom_entry_footer(); ?>
</footer>

There's another call to a custom-made function there. Here's what the function looks like:

function daily_cooking_custom_entry_footer() {
  // Hide category and tag text for pages.
  if ( 'post' == get_post_type() ) {
    $categories_list = get_the_category_list( __( ', ', 
     'daily-cooking-custom' ) );
    if ( $categories_list && daily_cooking_custom_categorized_blog() ) {
      printf( '<span class="cat-links">' . __( 'Posted in %1$s', 
       'daily-cooking-custom' ) . '</span>', $categories_list );
    }

    $tags_list = get_the_tag_list( '', __( ', ', 'daily-cooking-custom' 
      ) );
    if ( $tags_list ) {
      printf( '<span class="tags-links">' . __( 'Tagged %1$s', 
        'daily-cooking-custom' ) . '</span>', $tags_list );
    }
  }

  if ( ! is_single() && ! post_password_required() && 
  (comments_open() || get_comments_number() ) ) {
    echo '<span class="comments-link">';
    comments_popup_link(__('Leave a comment', 'daily-cooking-custom'),
     __('1 Comment', 'daily-cooking-custom'), __('% Comments', 
    'daily-cooking-custom'));
    echo '</span>';
  }

  edit_post_link( __( 'Edit', 'daily-cooking-custom' ), 
  '<span class="edit-link">', '</span>' );
}

All this code handles the post details, such as the categories, tags, and the comment links (which other visitors can click to submit their opinions about the post). One interesting thing I'd like to point out here is the call to the comments_popup_link() function, as follows:

comments_popup_link(__('Leave a comment', 'daily-cooking-custom'), __('1 Comment', 'daily-cooking-custom'), __('% Comments', 'daily-cooking-custom'));

Here, you can see that there are three arguments passed, separated by commas:

This is it regarding a basic understanding of the loop. Of course, its structure allows you to do many more things and include many custom features. However, for now, we are good with what we have here. Once you save your index.php and reload your website, you will see your new theme in action.

This version of the index.php file is available in the code bundle for this chapter, inside a sub-directory called phase 2. Our theme files will go through a couple of phases before we have the final version.

Later in the chapter, I will show you how to create a custom page template, which will take advantage of the loop and use it for a slightly different purpose.