ytrewq
ytrewq

Reputation: 69

Display an index next to a post — WP & Twig/Timber

I'm new to both WP and Twig/Timber. I'm working on a website where I need to display a number next to a WP post as such:

  1. First post
  2. Second post
  3. Third post

…And so on

I couldn't find any information on how to do it. Can I achieve this with Twig/Timber? Also, I don't know much about it, but if it's recommended to use ACF for that, I would be open to it.

Thank you

Edit: I would like to display post number(s) both on a page which contains all the blog posts and on each post page.

Edit 2: I'm hoping there is a robust solution which would account for deleted posts

Upvotes: 0

Views: 839

Answers (2)

Phil Veloso
Phil Veloso

Reputation: 1126

You could use a Twig filter to query a custom post number index which is saved in a transient: the order is currently set to the menu order and transient is cached for 1 minute.

Twig

{{ post.id|get_post_number }}

php

/**
 * Adds functionality to Twig.
 * 
 * @param \Twig\Environment $twig The Twig environment.
 * @return \Twig\Environment
 */
add_filter( 'timber/twig', 'add_to_twig' );
function add_to_twig( $twig ) {

    // Adding functions as filters.
    $twig->addFilter( new Timber\Twig_Filter( 'get_post_number', 'get_post_number_by_id' ) );

    return $twig;
}

/**
 * Get post number from ID, based on menu order.
 *
 * @param [type] $id
 * @return void
 */
function get_post_number_by_id( $id ) {

    // Check we have a string
    $target_id =  strval( $id );

    // Save quesry and index in transient
    $post_number_index = Timber\Helper::transient(
        'get_post_number_by_id',
        function () {

            // Update parameters to match desired search order
            $args = array(
                'orderby'    => 'menu_order',
                'posts_per_page' => -1,
                'post_status'    => 'publish',
            );

            // Query
            $posts = get_posts( $args );
            if ( !empty( $posts ) ) {
                
                // Store list
                $data = [];
                
                // Set post numer count
                $count = 0;

                // build index.
                foreach( $posts as $post ) {
                    $data[ $post->ID ] = array(
                        'post_id' => $post->ID,
                        'post_number' => ++$count,
                    );
                }

                return !empty( $data ) ? $data : false;
            }
            return false;
        },
        MINUTE_IN_SECONDS
    );

    // Retrun post number
    if ( !empty ( $post_number_index ) && array_key_exists( $target_id, $post_number_index ) ) {
        return $post_number_index[ $target_id ]['post_number'];
    }

    return false;

}

Upvotes: 1

Jared
Jared

Reputation: 1734

This is something that exists in Twig's loop variable that should make it super-easy:

https://twig.symfony.com/doc/3.x/tags/for.html#the-loop-variable

Upvotes: 1

Related Questions