Roots Discourse

Trying to learn Controller from examples (Sticky post)

Hi guys, I’m jumping on the Sage train after some years of not doing anything related with developing and I feel like I know nothing about modern tools.

I’ve read so far Blade docs, soberwp/controller docs and numerous posts here related to Controller itself but it’s not helping me a lot. Docs are too general and even when I understand examples there, I cannot make something by myself.

Maybe you will help me, as I tend to learn more by dissecting real life examples.

So. I want to make sticky post (featured) as separate item to be able to place it on top of my page (blog). The best way would be to first hide it from archive and then use it outside of main loop.

I’ve found this, And I have honestly no idea how to make it in “Controller way”:

 <?php if (is_home()) {
            $sticky = get_option( 'sticky_posts' ); // Get all sticky posts

            $args = array(
                  'posts_per_page' => 1,
                  'post__in'  => $sticky,
                  'ignore_sticky_posts' => 1
            );
            $query = new WP_Query( $args );

            if( $query->have_posts() ) {
                  while( $query->have_posts() ) {
                        $query->the_post();
                  ?>
                        <div class="trend-post">
                        <div class="thumb"><?php the_post_thumbnail(); ?></div>
                        <div class="title"><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></div></div>
                  <?php
                  }
                  wp_reset_query();
            }
        }
?>

What would be “proper modern Sage way” to achieve it? My attempts are always nice blank pages.

Instead of closing your PHP tag to print out some HTML, return an array containing the data you want to be used, and then create a blade that uses that data.

@alwaysblank I’ve edited code in my question as there were some leftovers from copy/paste.

This code is working fine. But I’m asking how to “translate” it for the Controller. Or maybe there is another way how to modify loop to get same result? Sorry for my not understanding general statements. Please treat me as utter idiot :wink:

Edit:
For now I’m using something like this:

index.blade.php

@while (have_posts()) @php the_post() @endphp
@include(‘partials.sticky-’.get_post_type())
@endwhile

partials/sticky.blade.php

@if (is_sticky())

@endif

Do running two loops isn’t too heavy for this task?

Edit 2:

Ok, I’ve it in one loop:

@if (is_sticky())

@else

@endif

But still I don’t understand how this could be achieved inside Controller, or is it not necessary?

So if I’m understanding correctly, you want to completely separate your normal posts from your sticky posts, and you want to keep the “sticky query” in a controller.

Here’s how you could do that, using the examples from the WordPress codex:

app/Controllers/App.php (or other appropriate controller):

...

// This is untested but it should be close to working
public function stickies() {

  // Initialize the return array
  $return = array();

  // Get the sticky posts
  $sticky = get_option( 'sticky_posts' );

  // Set up arguments for sticky posts
  $args = array(
    'posts_per_page' => -1,
    'post__in'  => $sticky,
    'ignore_sticky_posts' => 1
  );

  // Get all sticky posts as an array
  $return = get_posts( $args );
  
  // Always return
  return $return;
}

...

And then in your template…

@foreach($stickies as $sticky)
  @include('partials.sticky', $sticky)
@endforeach

Finally, in sticky.blade.php

<article class="sticky-post">
  <h2>{!! get_the_title($id) !!}</h2>
</article>

Or something like that. I’m doing this from a phone and I can’t test it :slight_smile:

2 Likes

@MWDelaney kudos for typing this on a phone!

There is missing @ before include and ’ ’ around partials.sticky but it’s working great! Thank you for this solution.

Now, can you tell me how performance wise this is different from the method I’ve come up to in my Edit 2?

It’s for sure more flexible as I don’t need to run whole loop in other place then home, right?

Edit:

There is something wrong. I’ve glued 3 posts. No. 6, 7, 8. My method is displaying them correctly but yours is sticking only last one 3 times. I’ve changed array args as below:

  $args = array(
        'posts_per_page' => 3,
        'post__in'  => $sticky,
        'ignore_sticky_posts' => 0
      );

Try with 'ignore_sticky_posts' => 1. Confusingly this is probably the setting you want.

No difference sadly, I’ve tried it before after reading from Codex.

What if you try with static method?

public static function stickies() {

    // Initialize the return array
    $return = [];

    // Get the sticky posts
    $sticky = get_option( 'sticky_posts' );

    // Set up arguments for sticky posts
    $args = [
        'posts_per_page' => 3,
        'post__in'  => $sticky,
    ];

    // Get all sticky posts as an array
    $return = get_posts( $args );

    // Always return
    return $return;
}
@foreach(App::stickies() as $sticky)
    <h3>{{ $sticky->post_title }}</h3>
@endforeach

Static shouldn’t make a difference because the query and context don’t change. The most recent three sticky posts are always the same.

@l_dudzic this point in troubleshooting I would just var_dump() the data being passed to the template(s) and see what’s going on.

1 Like

Ok, there is something confusing going on here.

I’ve placed var_dump($sticky) before @endforeach and the result is correct but {!! get_title() !!} or {{ post_class() }} are still the same, which is last sticky post. Here is example:

   Post number 8 // < this is last sticky post title assigned to what is below {!! get_title() !!}

    object(WP_Post)#5374 (24) { 
    ["ID"]=> int(23) 
    ["post_author"]=> string(1) "1" 
    ["post_date"]=> string(19) "2019-04-15 16:01:46" 
    ["post_date_gmt"]=> string(19) "2019-04-15 14:01:46" 
    ["post_content"]=> string(2568) "

    // ... content here

    " ["post_title"]=> string(12) "Post number 6" 
    ["post_excerpt"]=> string(0) "" 
    ["post_status"]=> string(7) "publish" 
    ["comment_status"]=> string(4) "open" 
    ["ping_status"]=> string(4) "open" 
    ["post_password"]=> string(0) "" 
    ["post_name"]=> string(12) "post-number-6" 
    ["to_ping"]=> string(0) "" ["pinged"]=> string(0) "" 
    ["post_modified"]=> string(19) "2019-04-15 23:26:03" 
    ["post_modified_gmt"]=> string(19) "2019-04-15 21:26:03" 
    ["post_content_filtered"]=> string(0) "" 
    ["post_parent"]=> int(0) 
    ["guid"]=> string(32) "//localhost:3000/wordpress/?p=23" 
    ["menu_order"]=> int(0) 
    ["post_type"]=> string(4) "post" 
    ["post_mime_type"]=> string(0) "" 
    ["comment_count"]=> string(1) "0" 
    ["filter"]=> string(3) "raw" } ;

Edit:

Solved.
I need to add $sticky in every bracket:

{{ post_class($sticky) 
{!! get_the_title($sticky) !!}
{{ get_the_excerpt($sticky) }}

And it’s not necessary to add it in @foreach for some reason:

  @foreach($stickies as $sticky)
    @include('partials.sticky')
  @endforeach

This topic was automatically closed after 42 days. New replies are no longer allowed.