Support

Account

Home Forums Front-end Issues Position 9 posts in grid based on Options page & Have timed posts work

Solving

Position 9 posts in grid based on Options page & Have timed posts work

  • Hi there,

    We are running a news blog. At the top of the page, there is a featured section. This section contains 9 positions.

    I would like to control this section from one page, so an ACF option page comes to mind.

    So I have a loop that looks at the option page, and if the 9 positions have a published post ID, then they get displayed.

    
    $top1 = get_field('kiemelt1', 'option');
    $top2 = get_field('kiemelt2', 'option');
    $top3 = get_field('kiemelt3', 'option');
    $top4 = get_field('kiemelt4', 'option');
    $top5 = get_field('kiemelt5', 'option');
    $top6 = get_field('kiemelt6', 'option');
    $top7 = get_field('kiemelt7', 'option');
    $top8 = get_field('kiemelt8', 'option');
    $top9 = get_field('kiemelt9', 'option');
    
    $top1pozicio = get_posts(array(
        'posts_per_page' => 1,
        'post_type' => array('cikkek', 'mti'),
        'orderby' => 'date',
        'order' => 'DESC',
        'post__in' => $top1
    ));
    
    if ($top1pozicio): ?>
    
    <?php foreach ($top1pozicio as $post):
    
        setup_postdata($post);
    
        ?>
    <article class="item-main col-12">
        <div class="item-inner-main">
            <div class="image-blocks-main">
                <a href="<?php the_permalink(get_the_id());?>"><?php echo get_the_post_thumbnail(get_the_id(), 'medium-hd', array( 'class' => 'main_topone_featured_image')); ?></a>
            </div>
            <div class="text-holder-main">
                <h2 class="entry-title-main kiemelt1"><a href="<?php the_permalink(get_the_id());?>"><?php echo get_the_title(get_the_id()); ?></a>
                </h2>
            </div>
        </div>
    </article>
    
    <?php endforeach;
    wp_reset_postdata();
    endif;
    $top2pozicio = get_posts(array(
        'posts_per_page' => 1,
        'post_type' => 'cikkek',
        'orderby' => 'date',
        'order' => 'DESC',
        'post__in' => $top2
    ));
    
    if ($top2pozicio): ?>
    
    <?php foreach ($top2pozicio as $i => $post):
    setup_postdata($post);?>
    
    <!-- TOP2 -->
    <article class="item-main-half col-6 ">
        <div class="item-inner-main">
            <div class="image-blocks-main top2row">
                <a href="<?php the_permalink(get_the_id());?>"><?php echo get_the_post_thumbnail(get_the_id(), 'owl-size'); ?></a>
            </div>
            <div class="text-holder-main">
                <h2 class="entry-title-main"><a href="<?php the_permalink(get_the_id());?>"><?php echo get_the_title(get_the_id()); ?></a>
                </h2>
            </div>
        </div>
    </article>
    
    <?php endforeach;
    wp_reset_postdata(); 
    endif;

    So this goes on until position 9, no point in posting the entire code.

    However, there are two issues.

    1. I can’t schedule articles, because if I overwrite one of the positions with a scheduled article, the position remains empty until the new scheduled article is set to publish.

    2. All of these positions are separate loops, so they can’t roll over and replace… empty positions (for example posts that are scheduled but not yet published) so that the layout does not break.

    The goal would be something like this:

    Have the 9 positions always filled up based on the most recent posts, but overridable by the options page. Example: I have 9 articles based on the date displaying in the positions, but the news comes in that an asteroid is heading towards earth, and I deem it so that this news deserves position 3.

    The result ->

    Position 9 falls out of the loop (since it’s the oldest). Position 3 is moved to position 4 (it does not get deleted only moves +1 position in the loop, this is the most challenging part that I can’t figure out), and my great asteroid article takes up position 3.

    Is this possible?

    Can this be made to work somehow? Any pointers appreciated!

  • There is something that I don’t understand from you description.

    Will $top1 = get_field('kiemelt1', 'option'); not return a value if the post should not be shown because of something else?

    Also, what does the above return, just the post ID?

  • Well, currently it does not.

    The options page consists of 9 number input fields.
    Each field contains an ID. ​
    If I change an input ID, the last value disappears (if I could save the last value, that would be a start, but such an option is not available as far as I know).

    It only returns the post ID.

  • Sorry, still not sure I follow. I would set these fields up as post object fields to allow selecting a post rather than entering an ID manually.

    So, thinking about what you have this is the way I would do something similar.

    The options page has 9 post object fields that will appear and override specific positions. Each could be empty.

    I would get the values from these fields and I would query all the posts to get 9 posts in descending date order excluding any posts selected in the post object fields.

    I would then create a loop to show 9 posts using a counter to tell me what post from the query is next something like the following.

    Please note that this is just a rough idea and a lot of it would need to be filled in.

    
    $next_post = 0;
    for ($i=0; $i<9; $i++) {
      if (/* test for top post at this position */) {
        $post = {post at this position};
      } else {
        $post = $queried_posts[$next_post]
        $next_post++;
      }
      // show the selected post
    }
    

    What this would do is show the posts that are selected filled in with other recent posts up to the 9 needed and avoid showing any post twice.

    I can help flesh this out more if need be. I have actually created something like this before for a client. They wanted to events and to have a slider that showed the first X number of upcoming posts but they also wanted to be able to override any position in the slider with a “featured” event that may be further into the future.

  • ** EDIT: I just saw that you answered so I’ll read through that. Disregard this answer for now!

    Also, I’m not sure I fully answered your question. Right now the loop is really basic. It takes in cikkek posts and is limited to a certain number of posts based on the layout.

    A picture might help a bit: https://imgur.com/npKU5SL

    The section I’m referring to is “kiemelt hirek”.

    So the top 3 positions are:

    1st loop: Take 1 cikkek post with acf options id from kiemelt 1
    2nd loop: Take 1 cikkek post with acf options id from kiemelt 2
    3nd loop: Take 1 cikkek post with acf options id from kiemelt 3

    I understand that I need to combine the loops somehow, but I’m unsure as to how I can achieve that. I would somehow need to assign

    $top1 = get_field(‘kiemelt1’, ‘option’); a value and order by that value.

    That would fix the looping issue for one, but not the others.

  • Wow that is exactly what I need.

    I will try to implement your answer tomorrow as it’s midnight here.
    If you have your code around by any chance, that would be highly appreciated.

    Thanks a lot!

  • Following along the lines of what I described above

    
    $top = array(); // holds values from options page fields
    $top_ids = array(); // will hold id values for query
    for ($i=1; $i<10; $i++) {
      // assumes fields are post object fields that returns Post Object
      $value =  get_field('kiemelt'.$i, 'option');
      if (!empty($value)) {
        // populate top array for this position
        $top[$i] = $value;
        $top_ids[] = $value->ID;
      }
    }
    
    // query to get most recent 9 posts excluding top posts
    $args = array(
      'post_type' => array('cikkek', 'mti'),
      'posts_per_page' => 9,
      'orderby' => 'date',
      'order' => 'DESC'
    );
    if (!empty($top_ids)) {
      $args['post__not_in'] = $top_ids;
    }
    $posts = get_posts($args);
    
    $next_post = 0;
    for ($i=1; $i<10; $i++) {
      $post = false;
      if (!empty($top[$i])) {
        $post = $top[$i];
      } elseif (!empty($posts[$next_post])) {
        // this elseif statement also takes into account
        // that query may not return 9 posts
        $post = $posts[$next_post];
        $next_post++;
      }
      if (!empty($post)) {
        setup_postdata($post);
        // show post
      }
    }
    wp_reset_postdata();
    
Viewing 7 posts - 1 through 7 (of 7 total)

You must be logged in to reply to this topic.