Roots Discourse

Custom Page Template for blog posts

I’ve searched everywhere and can’t find an answer to what I am trying to do. I need the posts page to have a featured post at the top then below it two columns with the next two blog posts then under that the rest of the posts in three columns. I’ve tried doing a new wp_query but it only shows all the posts in descending order and won’t pull them in any other order.

This is the first time I’ve used Sage and am still trying to figure out where everything is. I’ve gone through the Wordpress codex and tried multiple loops and it doesn’t seem to make a difference. I am not using the post page under the Settings -> Reading just the Static Front page. I have a custom page template for the posts.

This loop is adapted from one I used recently. You should be able to just drop it into whatever template you’re using to display your blog posts and it’ll work. It may need a little tweaking based on your needs.

<?php global $wp_the_query; 
	while (have_posts() && $wp_the_query->current_post < 0): the_post(); ?>
		<div class="featured-post">
			<?php the_title(); // ...and whatever else you want to do ?>
		</div>
	<?php endwhile; ?>

	<div class="two-columns">
		<?php while (have_posts() && $wp_the_query->current_post < 2): the_post(); ?>
			<div class="secondary-post">
				<?php the_title(); // ...and whatever else you want to do ?>
			</div>
		<?php endwhile; ?>
	</div>

	<div class="three-columns">
		<?php while (have_posts() && $wp_the_query->current_post >= 2): the_post(); ?>
			<div class="tertiary-post">
				<?php the_title(); // ...and whatever else you want to do ?>
			</div>
		<?php endwhile; ?>
	</div>

Instead of modifying the WordPress Loop, this query just looks at what iteration of that loop you’re on, and then uses the correct section accordingly.

The queries like this are the key:

while (have_posts() && $wp_the_query->current_post < 0)

The integer there (0 in this case) is, basically, the number of posts (minus 1, because when a computer counts the first item is 0) from the beginning of the loop that you want to show here. This particular while loop will “loop” through only a single post–the first one.

while (have_posts() && $wp_the_query->current_post < 2)

This while loop with move through the next two posts. The first while has already “done” the first post, so it’s not available to this loop: It’ll start on post #2.

while (have_posts() && $wp_the_query->current_post >= 2)

And this will move through the remainder.

Ultimately, you should end up with something like this:

<div class="featured-post">
	Title of the Featured Post
</div>

<div class="two-columns">
	<div class="secondary-post">Another Post, A</div>
	<div class="secondary-post">Another Post, B</div>
</div>

<div class="three-columns">
	<div class="tertiary-post">Remainder Post 1</div>
	<div class="tertiary-post">Remainder Post 2</div>
	<div class="tertiary-post">Remainder Post 3</div>
	<div class="tertiary-post">Remainder Post 4</div>
	<div class="tertiary-post">Remainder Post 5</div>
	<div class="tertiary-post">Remainder Post 6</div>
	<div class="tertiary-post">Remainder Post 7</div>
</div>

…Which you can then style into columns however you want.

2 Likes

What exactly is $wp_the_query?

https://www.google.com/search?q=wp_the_query&ie=utf-8&oe=utf-8

Oh, I though something else.

I’m trying to loop posts and I’m using App Controller, however, I can’t seem to make this work.

App Controller has this:

class App extends Composer

{

    /**

     * List of views served by this composer.

     *

     * @var array

     */

    protected static $views = [

        '*',

    ];

    /**

     * Data to be passed to view before rendering.

     *

     * @return array

     */

    public function with()

    {

        return [

            'siteName' => $this->siteName(),

        ];

    }

    public function blog_posts(){

        $query_args = [

            'post_type' => 'post',

            'posts_per_page' => 10,

        ];

    

        return get_posts($query_args);

    }

etc…

And then on page.blade.php I’m trying to use that as:

 @foreach ($blog_posts as $key=>$post)
      @if ($key < 4)
        <div class="grid__item medium--one-half large--three-twelfths">
          <div class="blog-item">
            @if($post->image)
              <a href="{{ $post->url }}">
                <div class="blog-item__image" style="background-image: url({{ $post->image }})" title="{{ $post->title }}"></div>
              </a>
            @else
              <a href="{{ $post->url }}">
                <div class="blog-item__image" style="background-color: #eee" title="{{ $post->title }}"></div>
              </a>
            @endif
            <p class="blog-item__meta">
              {{ $post->date }} /
              @foreach ($post->categories as $category)
                <a href="<?php echo esc_url( get_category_link( $category->term_id ) ); ?>">
                  {{ $category->name.' ' }}
                </a>
              @endforeach
            </p>
            <h4 class="blog-item__title"><a href="{{ $post->url }}">{{ $post->title }}</a></h4>
            <div class="blog-item__excerpt">
              @php echo $post->excerpt @endphp <a class="blog-item__excerpt-link" href="{{ $post->url }}">Read More...</a>
            </div>
          </div>
        </div>
      @endif
    @endforeach

But it doesn’t seem it works. not sure what to do.

Your with() method doesn’t return the result of blog_posts() so that data isn’t available in your view. Have you read our article on composers? https://roots.io/working-with-composers-in-sage-10/

1 Like

Right, that worked.

Now, last question about this, I’m trying to incoporate the above code, into what you actually wrote:

<?php global $wp_the_query; 
	while (have_posts() && $wp_the_query->current_post < 0): the_post(); ?>
		<div class="featured-post">
			<?php the_title(); ?>
		</div>
	<?php endwhile; ?>

And I can’t figure this out.

This returns Home, the page title I’d assume. I did try to use custom variabe, I tried to pass it like $blogPosts->have_posts() etc… and nothing seems to work.

What have you tried so far?

How is it not working?

Why do you think it isn’t working?

So your code works on single.blade.php page.

However, when I’m on page.blade.php, it displays the title of the page. Which makes sense because outside the loop, the_title() gets the page title.

I also increased the number from 1 to 2, and only one title is showing as well.

Which means the loop isn’t working.

This doesn’t seem to work, its how a normal WP loop should be right:

<?php if( $blogPosts->have_posts()) :
             while ($blogPosts->have_posts() && $wp_the_query->current_post < 1) : $blogPosts->the_post(); ?>

		<div class="featured-post">
			<?php the_title(); ?>
		</div>
        
	<?php endwhile; ?>
    <?php endif; ?>

Not sure, now I ran out of ideas, as what I was trying before doesn’t make sense. The loop seems not to work on page.blade.php, though it works on single.blade.php.

Why does it do this?

Does it actually work or does it fail in a way that looks like working?[quote=“AurelianSpodarec, post:10, topic:10137”]
I also increased the number from 1 to 2, and only one title is showing as well.
[/quote]

If this happens then there isn’t a loop happening.

You should probably review the nature of the Loop and how it works.

1 Like

So it didn’t actually work, it looked as if it worked. I’ve dobule chekced it by increasing the limit on the single page, and the_title() shows the page title, not what should be withing the loop.

And while I did check the docs before you’ve sent them to me, for some reason, you did rubber duck on me, and it works.

public function args(){

        $query_args = [

            'post_type' => 'post',

            'posts_per_page' => 10,

        ];

    

        $query = new \WP_Query($query_args);

        return $query;

    }
	<?php  while ($args->have_posts() && $args->current_post < 0) : $args->the_post(); ?>

		<div class="featured-post">
			<?php the_title(); ?>
		</div>

	<?php endwhile; ?>

    <div class="two-columns">
		<?php while ($args->have_posts() && $args->current_post < 2): $args->the_post(); ?>
			<div class="secondary-post">
				<?php the_title(); ?>
			</div>
		<?php endwhile; ?>
	</div>

I’ll blame it on me not using this for a while and the fact its late night :smiley:

But all serious, really appreciate your help!

1 Like