Support » Developing with WordPress » get_next_post options

  • berry metal

    (@erikalleman)


    When

    $in_same_term = true

    when using the get_next_post and get_previous_post functions, and the current post has several parent categories and several child catgeories:

    – will the function pick the next/previous post only from the current posts parent categories or will it also consider child categories?

    – if the post has several categories, let’s say: first, second and third category (both parent and child categories), will it choose a post from all 3 categories, or only from the first?

    And if the current post has categories A and B, then will an other post that has the categories A and B have priority in the next/prev choice, even if its publish date falls further away than let’s say an other post, that has categories A and C?

    And is there any difference in the choices of the functions in comparison, when using get_next_post & get_previous_post, get_adjacent_post and get_{$adjacent}_post_where ?

Viewing 15 replies - 31 through 45 (of 63 total)
  • Thread Starter berry metal

    (@erikalleman)

    The reason I wrote the first query because I didn’t know how to check for the current post date, but I think that the first query is not checking correctly for the first date as well. That is what I could find, only, as an example.

    Thread Starter berry metal

    (@erikalleman)

    Thanks for removing the moderation.
    What do you mean by plugin reviews as a means of getting support?
    I don’t remember anything like that. How could one do that?

    • This reply was modified 1 month, 3 weeks ago by berry metal.
    Moderator bcworkz

    (@bcworkz)

    In wp-typography reviews last month, you said

    Plugin (or some plugin settings) causes insertion of extra quotation marks in shortcode html (fontawesome icon shortcode) , and the icons will not be displayed.

    I would agree it’s a borderline case, but it could have been phrased better to be a good review. It sounds more like a “How can this be fixed” support request than a review. Reviews should help others decide if they should try the plugin or go elsewhere. This sounds like a unique problem to your site. Anyway, it’s in the past, let’s move on.

    To convert the query to AND logic, the IN () clause needs to be replaced with a sub-query that gets all object IDs that have all of the term IDs in common. TBH, I’m not that good with SQL and aren’t entirely sure how to do that correctly. To avoid a blind leading the blind situation, we ought to get the next post with get_posts() or WP_Query class.

    I don’t know the reason for the type cast of meta data, meta data is saved as char anyway. The meta part is added by your filter hook, it’s not part of the default query. You can still include meta criteria in get_posts() in addition to category criteria if necessary. To get category AND logic, you can either use 'category__and or 'tax_query', the result is the same.

    To get the current post’s date, it’s in both the global $post object and available through get_post_datetime().

    Thread Starter berry metal

    (@erikalleman)

    I didn’t know what to do with get_post_datetime() and I have used category_and instead of tax_query, so here it is, I made a puzzle of code, could it possibly work?

    function in_same_term_next_post ($nextpost, $terms, $post_object, $args) {
    
    $post_object = get_queried_object();
    $terms = wp_get_post_terms( $post_object->ID, 'category', array( 'fields' => 'ids' ) ); 
    
    $args = array(
        'operator' => 'AND',
        'post_type' => 'post',
        'cat' => $terms[0],
        'posts_per_page' => 1,
        'order' => 'ASC',
        'category__and' => array( $terms ),
        'no_found_rows' => true,   // Get 1 post and bail. Make our query more effiecient
        'date_query' => array(
            'operator'  => 'AND',
            array(
                'after' => $post_object->post_date,  // Get the post after the current post, use current post post_date
                'inclusive' => false, // Don't include the current post in the query
            )
        ) 
    );
    
    $nextpost = new WP_Query( $args );
    
    }
    
    echo '<li><a href="'.get_permalink( $nextpost->posts ).'">'.get_the_title( $nextpost->posts ).'</a></li>';

    Are there any ingredients missing?
    The syntax I am not sure is correct.
    Why $terms[0] instead of just $terms?
    Because we want all terms.

    Could you help me with an example code?

    Thanks!

    Thread Starter berry metal

    (@erikalleman)

    Yes, perhaps bugs don’t belong to reviews, I’ll write some functionality pros/cons next time, instead.
    I’ll keep the rules. 🙂
    I review so rarely, once in 5 years, that I was not aware of the rules.

    @erikalleman, wp-Typography developer here. Sorry to drop into this thread, but I sort of got mentioned 😉 If you open a support thread for the described issue, I’m sure we’ll be able to sort it out. It could be a bug in one of the plugins, or simply an incompatibility (there are more than 50.000 active plugins in the WP.org repository, so it’s not possible to test all combinations).

    Thread Starter berry metal

    (@erikalleman)

    Okay. I needed the plugin for hyphenation, if I’ll use it again I’ll write to support.

    Moderator bcworkz

    (@bcworkz)

    Heh, hardly anyone reads the forum guidelines it seems 🙂 But thanks for going back and reviewing. Being put on a moderation watch is a frequent follow-up when members are notified that they have strayed from the guidelines. In virtually all cases, we don’t think any more poorly of members when this happens. It’s just a way to ensure compliance and to see if further admonishment might be necessary. We do start to think rather poorly of frequent repeat offenders 😉 In extreme cases where they don’t seem to ever care about guidelines, we have had to ban a few accounts.

    The parameter list isn’t used since you’re getting necessary data from the queried object. Either remove the list or reconfigure your code to make use of passed data. If you want to keep some parameters, but make them optional, you need to supply default values, something like function example( $parm = null, $args = array()){ //do something }. Some parameters just don’t make sense to be optional. Without a default, they are always required.

    Remove the entire 'cat' => $terms[0], argument, it conflicts with “category__and”. I’m unsure what effect “no_found_rows” has on queries. It removes the SQL_CALC_FOUND_ROWS in the SQL, but I don’t know SQL well enough to know what effect it has.

    The echo line is outside of the function declaration. That makes $nextpost out of scope. If you want the function to actually output the link, move the echo line into the function declaration. Otherwise have your function return $nextpost (actually $nextpost[0], since WP_Query always returns an array, even if an array of one). If the function is to return a value instead of echoing, then you’d need something like $next = in_same_term_next_post();

    get_post_datetime() returns a DateTimeImmutable object. To get the date it represents, use its format() method.

    $date_obj = get_post_datetime( $post_object );
    '$arg = ['after' => $date_obj->format('d-M-Y H:i:s'),];
    Thread Starter berry metal

    (@erikalleman)

    Not even the $args need to be declared at the function parameters? As far as I know, those are variables. So all parameters are variables, but not all variables are parameters?

    If the function is to return a value instead of echoing, then you’d need something like $next = in_same_term_next_post();

    Echoing is a must since I need to display the next link with the shortcode, because we had to abandon the idea of a filterable solution.

    Do you think the code is worth testing now, or are there still possible errors?

    add_shortcode( 'in-same-term-next-post', function in_same_term_next_post {
    
    $post_object = get_queried_object();
    $terms = wp_get_post_terms( $post_object->ID, 'category', array( 'fields' => 'ids' ) ); 
    $date_obj = get_post_datetime( $post_object );
    $arg = ['after' => $date_obj->format('d-M-Y H:i:s'),];
    
    $args = array(
    
        'operator' => 'AND',
        'post_type' => 'post',
        'posts_per_page' => 1,
        'order' => 'ASC',
        'category__and' => array( $terms ),
        'date_query' => array(
            'operator'  => 'AND',
            array(
                'after' => $post_object->post_date,  // Get the post after the current post, use current post post_date
                'inclusive' => false, // Don't include the current post in the query
            )
        ) 
    );
    
    $nextpost = new WP_Query( $args );
    
    echo '<li><a href="'.get_permalink( $nextpost->posts ).'">'.get_the_title( $nextpost->posts ).'</a></li>';
    
    } );

    And how do I get the original styles of my next/prev button that I already worked out?

    I intend this shortcode only for my “in same term” links, because I have normal next/prev links as well only with the date criteria, and I already done the styling for those, so I would like to use the same styling for the “in same terms” links, as well.

    I know that I could just insert my own classes with php, but based on the template codes that I posted previously, can you see any easier way in the template to adopt the styles from there?

    Sometimes I have seen $args declared as a parameter variable at the right side of the function name, in such declarations, is it enough to declare the plural or the singular, but not both $arg and $args?

    What the 'after' exactly is?
    And if the date is inside the post object, why is a separate $date_obj necessary?

    Thanks!

    • This reply was modified 1 month, 2 weeks ago by berry metal.
    • This reply was modified 1 month, 2 weeks ago by berry metal.
    • This reply was modified 1 month, 2 weeks ago by berry metal.
    • This reply was modified 1 month, 2 weeks ago by berry metal.
    Thread Starter berry metal

    (@erikalleman)

    I have the AND operator declared in 2 places in the code, but not at the array of terms.

    How do I declare the AND operator for the array of terms? That is where I would need it.

    • This reply was modified 1 month, 2 weeks ago by berry metal.
    Moderator bcworkz

    (@bcworkz)

    So all parameters are variables, but not all variables are parameters?

    Not exactly, but sort of. Basically just coder jargon, you may as well get used to it 🙂 Parameters are the data passed to functions that are assigned to variables specified in the function declaration.

    echo my_function( 'foo' ); // Passing a parameter to my_function()
    function my_function( $content ) { // $content could be called a parameter or variable here, depending on context
       $content .= 'bar'; // just a variable here
       return $content;
    }
    //outputs: foobar

    Sure, the link must be output at some point. You could echo the function return on the template, or have the function echo from within. Same end result. WP has some variants of functions that do one or the other, example: the_content() vs. get_the_content(). Other WP functions optionally do one or the other from the same function, based on a parameter value. I cannot recall an example ATM, but they exist.

    However, this is important: Shortcode handler functions must never output anything. All desired output must be collected into a single variable that is returned. WP then echoes the return at the right time. Is a shortcode the right approach here? They are normally only used within post content. You can use them on templates by calling do_shortcode(), but for your own custom template code it’s better to directly call the function than to go through a shortcode.

    $terms should already be an array, so just do 'category__and' => $terms,

    Sure, go ahead and test. It looks reasonable except for the $terms in an array. You’ll develop your own workflow that works for you, but I suggest very frequent testing as you develop. Testing every new line sometimes. I never seem to be able to code much at once without something going wrong. It’s easier to debug, the less that has been added since the last test.

    Whenever I write code in a sizable block, it very rarely goes as expected. There are always things wrong. If your code works on first go, pat yourself on the back for a job well done.

    To get existing styles applied, your links need the same HTML structure as the original links. Same classes, same IDs, same div containers, whatever is applicable for the relevant styles. Don’t worry too much about the existing template code, look at the HTML output. The template code has several possible variants that probably don’t apply and would confuse the issue. The same HTML output is what you want to achieve, except the linked post is different.

    $args in function declarations are generally plural since the intent is to collect a variable number of arguments. But it’s just a label really, call it whatever makes sense to you.

    ‘after’ is the argument to use when we want posts after the specified date. It gets translated into SQL that is in part similar to WHERE wp_posts.post_date > '2020-11-10 12:11:10' if the date string is the date of the current post. ‘before’ is similar except the > becomes <.

    $date_obj is not necessary, it’s just another way of doing things. The datetime object conveys some other properties and features that are useful in some situations. In this case $post_object->post_time works just as well.

    The AND logic is implicit in 'category__and'. Found posts must have all terms assigned whose IDs are in the $terms array. Contrast with date_query, tax_query, and meta_query where you do specify AND or OR. AND is the default, so you don’t actually have to declare it, you only need to declare if you want OR logic. Still, it’s useful to specify AND anyway for better readability.

    Thread Starter berry metal

    (@erikalleman)

    Here is the code with the HTML:

    But, since my HTML contains both links, next and previous, I would like to maintain this structure of the theme, so now the code need to be modified to output both next and previous links.
    How do I do that?

    In my text editor the correct highlighting went off at some parts of the code, so probably there are errors in it.

    Should I use esc_url or esc_html to output the links?

    add_shortcode( 'in-same-term-prev-next-post', function in_same_term_prev_next_post {
    
    $post_object = get_queried_object();
    $terms = wp_get_post_terms( $post_object->ID, 'category', array( 'fields' => 'ids' ) );
    $date_obj = get_post_datetime( $post_object );
    $arg = ['after' => $date_obj->format('d-M-Y H:i:s'),];
    
    $args = array(
    
        'operator' => 'AND',
        'post_type' => 'post',
        'posts_per_page' => 1,
        'order' => 'ASC',
        'category__and' => $terms,
        'date_query' => array(
            'operator'  => 'AND',
            array(
                'after' => $post_object->post_date,  // Get the post after the current post, use current post post_date
                'inclusive' => false, // Don't include the current post in the query
            )
        ) 
    );
    
    $nextpost = new WP_Query( $args );
    
    /*
    echo '<li><a href="'.get_permalink( $nextpost->posts ).'">'.get_the_title( $nextpost->posts ).'</a></li>';
    
    */
    
    $output .= ' <div class="plugin-post-next-prev textright postnavigation" style="font-size:1.4em;">
    
    ::before
    
      <div class="plugin-col prefix-inline-block prefix-mr-0">
        <a href="https://previouspost.link" class="theme-button graphical blue prefix-text-center prefix-max-w-100">
            <span class="ticon ticon-chevron-left prefix-mr-10">
                ::before
            </span>
    
                 esc_url( .get_permalink( $nextpost->posts ).'">'.get_the_title( $nextpost->posts ). );
    
        </a>
      </div>
    
      <div class="plugin-col prefix-inline-block prefix-ml-0">
        <a href="https://nextpost.link" class="theme-button graphical blue prefix-text-center prefix-max-w-100">
    
                 esc_url( .get_permalink( $nextpost->posts ).'">'.get_the_title( $nextpost->posts ). );
    
            <span class="ticon ticon-chevron-right prefix-ml-10">
                ::before
            </span>
    
        </a>
      </div>
    
    </div> ';
    
    return $output;
    
    } );

    Could you help me out correcting this code?
    I am not sure what the dots mean and the spaces at the links html…
    I wrote this code by adopting it from other shortcode code from my functions.php, that outputs html and links.

    • This reply was modified 1 month, 2 weeks ago by berry metal.
    Thread Starter berry metal

    (@erikalleman)

    The HTML is the exact code from the Dev Tools as you recommended, so it includes the 3 ::before elements as well, the first is a text label before the next/prev wrapper, that indicates that this is an “in same term” navigation, and the other two are arrows that indicate the direction of the next/prev.

    The second arrow should be an ::after instead of before, because it’s after the link, but probably it’s absolute positioned (I don’t remember exactly), so then it functions as an ::after.

    Thread Starter berry metal

    (@erikalleman)

    I just changed the class theme prefixes, because the theme developer asked me to do so when I share theme code.

    Thread Starter berry metal

    (@erikalleman)

    Ah I found out that dots are for concatenation. What about the space before and after the dot?

Viewing 15 replies - 31 through 45 (of 63 total)
  • You must be logged in to reply to this topic.