• Hi,

    I’m having an issue with custom taxonomies in that I need the entry for one custom taxonomy to be linked to the same entry in others.

    I am building a film review site and have set up taxonomies for Actors, Writers and Directors but of course, some people do both. At the moment, the taxonomies are all separate, so if someone clicks eg. Ben Affleck under the actor category, they will see a list of content where he is tagged as an actor.

    I’d like when a user on the front-end clicks on Ben Affleck in any category, they would see a list of everything he’s done as an actor, a writer and a director. Is it possible to link individual taxonomies across different sections like this? Or any way to have it appear that way on the front-end?

    Any help is much appreciated.

Viewing 15 replies - 31 through 45 (of 52 total)
  • Moderator bcworkz

    (@bcworkz)

    Actually, the query is missing the erroneous ‘wp_posts.post_author = 1 AND’, so the query looks pretty good to me, it ought to work.

    I see the latest template has an add_action call to pre_get_posts adding the archive function. Isn’t “archive” our function we’ve been working on? Isn’t the function declaration in functions.php? Is the same add_action to pre_get_posts on functions.php as well? Or no? Well, it needs to be on functions.php and not on the template file.

    I hope that helps, because I’m running out of explanations why this isn’t working. The query looks perfect. The only other thing I can think of is to double check that all the slugs used are absolutely correct. No singular where there should be plural and vice versa. No underscores instead of hyphens, no transposed letters, etc.

    Thread Starter a_mulg

    (@a_mulg)

    So the good news is…it works! It’s now pulling in posts from every taxonomy, regardless of the URL (eg. actors/, writers/, directors/) so that’s working exactly like it should.

    However, this wasn’t immediately obvious as for some reason it’s only displaying the first available post, so I had to do a lot of unpublishing/publishing to see what displays and what doesn’t.

    Is that something I would fix via the archive function or via the <?php if ( have_posts() ) : ?> part of my template? (Apologies if that isn’t related to this topic exactly!)

    Thread Starter a_mulg

    (@a_mulg)

    Also, a quick follow-up question: given that I don’t want to use this exact query for archives that don’t relate to a person, how do I go about applying my function to eg. archive_person.php and not archive.php?

    Moderator bcworkz

    (@bcworkz)

    Phew! Good news indeed!

    Oh, I’m sure it’s related, the number of posts returned is part of the same query. It should be the posts per page that is set in the Reading Settings in the admin area. The default is 10 and that is the limit asked for in the last SQL you posted, so I’m not sure why you only get one ??

    It shouldn’t be the template code as long has it has the usual while have posts : the post after if have posts (ignoring proper syntax). It should be something we can fix in the archive function, but I’m not sure it’ll help since the query asked for 10 and got 1.

    In any case, it would not hurt to try. Modify like so:

           if ( ! isset( $person )) return;
    
              $query->set( 'posts_per_page', -1 ); // <<=== JUST ADDING THIS
              $taxquery = array(

    Just add the middle line as indicated. By setting the count to -1, we are saying “give us everything that qualifies”. The resulting SQL should then have the LIMIT 0, 10 dropped from the end. Once this mess is all resolved, you can change the -1 to any value you prefer.

    I fear this will not help. While the SQL is very close to the final state prior to executing the query, there remains a few opportunities for other code to interfere, both before and after the query. We can investigate these and eventually zero in on where the interference is and take measures to stop it. It could take awhile since the turnaround time with this forum format is so slow. But I need time to formulate the next step, so switching to chat will not really help.

    Anyway, see what you can determine with this added bit of code and we’ll see.

    Thread Starter a_mulg

    (@a_mulg)

    Aha, I checked my template and the if have posts was missing the while have posts part. I’ve fixed that and it seems to be working perfectly now! Thanks for all your help and patience!

    Just wondering now if it’s possible to apply this to a page other than archive.php so I can have a more generic archive.php page as well?

    Moderator bcworkz

    (@bcworkz)

    Awesome! I’m sooo glad it was an easy fix, I was pretty much at a loss if that wasn’t it.

    Yes, we can get these kind of queries to use a template other than archive.php. If you have no other custom taxonomies that require a normal archive style template, i.e. all custom taxonomies are able to use this taxonomy template, then just rename it as taxonomy.php and WP will find it. As long as it’s in the theme folders.

    I’m curious though, what is different about this template that makes it unsuitable for other queries? Does it still have that pre_get_posts add_action() call for the archive() function? That doesn’t really belong there, it ought to go on functions.php. (No need for <?php ?> tags there) I’m surprised it even works at that location. I clearly don’t fully understand everything.

    I’m unaware of any reason a normal archive template would not work for this. Perhaps you’d like the page to appear somewhat differently than regular archives. Or you just want it for the future possibility of something different and they are currently identical. Whatever the reason, it’s fine, you are allowed to have extra templates ??

    But if you do have other custom taxonomies that should not use this template, you will need to make three copies of the same thing, one for each possible taxonomy. Name them taxonomy-actors.php, taxonomy-writers.php, and taxonomy-directors.php.

    Thread Starter a_mulg

    (@a_mulg)

    No, I removed the pre_get_posts add_action() action in the archive.php file. I’m just concerned that I’m also using standard WP tags for things like genres, festivals, award shows and other more generic terms.

    For example, when I visit eg. /tag/action/, it’s using archive.php and returning no posts, even though there are numerous posts with that tag. Is that because the function we created is looking for the custom taxonomies only? Or is it a case of just adding the generic tags to the function?

    Moderator bcworkz

    (@bcworkz)

    Ah, I see. That’s not a template issue. There needs to be something in a pre_get_post function like ours to pass such queries through unchanged. The if ( ! isset( $person )) return; should have taken care of that. A normal archive template simply outputs whatever the query returns, it does not concern itself with what the request was. Just like a printer merely prints whatever was sent to it.

    Please re-enable the “posts_request” filter that outputs the resulting SQL query. This time make a normal tag request and post the resulting SQL. That should tell us what’s preventing the proper results from appearing. I have a feeling it’s something unrelated to the archive function, as that if ! isset line should be infallible and pass on any query that is not for one of those 3 taxonomies the function is meant to capture.

    Thread Starter a_mulg

    (@a_mulg)

    Ok, this is what I get when I try to view /tag/action. There are definitely multiple posts with that tag so should be plenty to show.

    SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1 AND (
    wp_term_relationships.term_taxonomy_id IN (50)
     ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 10

    I double checked the tag_ID and it is definitely 50 as shown in the SQL.

    • This reply was modified 7 years, 10 months ago by a_mulg.
    Moderator bcworkz

    (@bcworkz)

    The query is for only ‘post’ post types! I know you mentioned other things that were tagged, these would be custom post types, yes? Other than that the query looks OK. Are there any regular posts at all with this tag that should have been returned, or do custom post types fully explain why there is nothing?

    It seems like WP should add custom post types into tag queries anytime tags are associated with those post types when registered, but it doesn’t seem to work that way. We can correct for this in the same archive function, but I need to know which kind of requests should be so modified and which not. I know the writer, actor, director taxonomies are different. Should the post types be added only for tag requests, or are there others? Other possible requests to consider are categories, searches, authors, dates, feeds, and other custom taxonomies.

    Also please provide a complete list of all post type slugs that should be included in tag requests, as well as in other possible scenarios. Is the archive() function version in this post still the correct version?

    Thread Starter a_mulg

    (@a_mulg)

    Ah right. I have added that tag to a standard post which now shows, so the loop is working correctly. I am slightly confused though! This is the archive function I currently have…

    function archive($query) {
    
        if ( ! is_archive() && $query->is_main_query() )
          return;
    
            // echo '<pre>', print_r( $query->query_vars, true ), '</pre>';
            
            $tentative = $query->get('actors');
              if ('' != $tentative ) {
                  $person = $tentative;
                  unset( $query->query_vars['actors']);
              }        
            $tentative = $query->get('writers');
              if ('' != $tentative ) {
                  $person = $tentative;
                  unset( $query->query_vars['writers']);
              }        
            $tentative = $query->get('directors');
              if ('' != $tentative ) {
                  $person = $tentative;
                  unset( $query->query_vars['directors']);
              }
            if ( ! isset( $person )) return;
    
            //$query->set( 'posts_per_page', -1 );
    
              $taxquery = array(
                'relation' => 'OR',
                  array(
                     'taxonomy' => 'actors',
                     'field'    => 'slug',
                     'terms'    =>  $person,
                  ),
                  array(
                     'taxonomy' => 'writers',
                     'field'    => 'slug',
                     'terms'    =>  $person,
                  ),
                  array(
                     'taxonomy' => 'directors',
                     'field'    => 'slug',
                     'terms'    =>  $person,
                  ),
              );
    
          $query->set( 'tax_query', $taxquery );
            
        }
    
    add_action('pre_get_posts','archive');
    
    add_filter('posts_request', function( $sql ) { return str_replace('wp_posts.post_author = 1 AND ', '', $sql ); }, 100 );

    I think what I’m not quite understanding is how that function manages to return custom post types for the actors, writers and directors taxonomies but not the standard tag?

    The way I currently have it set up, the actors, writers and directors taxonomies are available across all post types, as well as the standard WP tag taxonomy. The post types I use are reviews, feature, trailer and posts. (Those are their slugs).

    I also use the categories awards and festivals across all post types, so I can group all posts about awards or festivals and access them via one menu item on the front end. So those categories would ideally need to show all different post types, as would search and author requests.

    I hope this is enough information – thanks again for your help and continued patience!

    Moderator bcworkz

    (@bcworkz)

    You are not alone in not understanding why custom taxonomies pull in their related custom posts, but standard tags with the same relations do not. I don’t know if it’s an overlooked flaw (i.e. bug) or intentionally ignored based on the assumption that if someone can code custom posts, they can code the query adjustment as well. ˉ\_(ツ)_/ˉ I’ve never thought about it much, I’ve just made it work where necessary.

    I could pull in custom posts for author queries, but author queries for user ID == 1 will always fail because I am removing the related author clause that was in our person term queries by adding that last line of your most recently posted snippet. We haven’t resolved why that happens, my fix is a band-aid solution that does not address the root cause. I think it works because all posts so far are authored by user 1 (I’m assuming). I have a suspicion that if a post by another author had one of the ben-affleck terms assigned, and one clicked on that term to get all of Ben’s related posts, then that erroneous clause will have this other author’s ID. My band-aid fix will not work with IDs other than 1, thus the query will again fail as before ??

    If that’s the case, we can modify the band-aid fix to work with all user IDs by using preg_replace() (regexp matching) instead of str_replace(). In that case, all author queries will not work. If you think author queries will be important, I think I can come up with a different band-aid that only applies to our current person term queries, but I fear this erroneous clause will then creep into other queries where it does not belong. Unless the root cause can be eliminated, I think we need to accept that author queries are broken and not use them. This means removing any links anywhere the author’s name appears on posts.

    Incorporating these extra post types in all appropriate queries will require some restructuring of what we already have, so give me some time to work up a good solution. Since I’ll be unable to test what I come up with, be ready for another round of debugging. C’est la vie.

    You made no mention of the ‘page’ post type. They normally have no taxonomies related to them, but they are included in searches, but not any other archive type queries. Even if you currently have no pages, I’m inclined to include them in search queries but in no other archive type queries just for consistency with normal WP behavior. Sound OK? Or do you prefer something else?

    Thread Starter a_mulg

    (@a_mulg)

    I’ve discovered something that might make the author situation a lot easier! Since we changed the archive page and it started working correctly, I left the function as it was. However, I just tried removing the author line and everything still works as intended without it! So it looks like we can scrap that line?

    For what it’s worth, at the moment when I visit the author’s name on the front end, it returns the archive page and only displays posts, not any of the custom taxonomies. I’m sure that is expected behavior but thought it might be worth mentioning!

    So as it stands, my custom taxonomies (actors, writers, directors) display all posts from custom post types, but not ‘posts’. Tag and author return only the ‘posts’ type and none of the custom post types. I also tried the search and it uses the search.php template, which returns both my custom post types and ‘posts’.

    I think you’re right about the page post type though, which doesn’t seem to appear in any search results. While I’ll only be using it for generic content (about us etc), it may be useful if that displays in the search. But yeah, they won’t be needed in any other query.

    Moderator bcworkz

    (@bcworkz)

    Huh, that’s curious about authors. Yeah, if queries work with out it then definitely scrap it! Well, comment it out for now until the dust settles ?? Be sure the queries are truly working and you’re not seeing cached browser results.

    Thanks for the additional information, that’s helpful. I’ve still not had some time to work up a solution. I’ll try to get to it today (Monday). Thanks for your patience. I know this has been a long process. It’ll be worth it in the end ??

    Moderator bcworkz

    (@bcworkz)

    OK, here it is. It didn’t take too much adjustment. I did rename the function because “archive” alone is a little too common for comfort. I fear a name collision could easily happen in the future. flmrev is a contraction of “film reviews”. You can change it if you want, as long as it’s not to something common. If you do, remember to change the add_action() line at the bottom too.

    function flmrev_archive( $query ) {
    
        /* do not handle admin or secondary queries - 
             determine by is_admin property, there is no similar method! */
        if ( $query->is_admin || ! $query->is_main_query()) return;
    
        // handle non-archive queries
        if ( ! $query->is_archive()) {
          if ( $query->is_search()) 
              $query->set('post_type', array('reviews', 'feature', 'trailer', 'post', 'page',));
          if ( $query->is_feed()) 
              $query->set('post_type', array('reviews', 'feature', 'trailer', 'post',));
          return;
        }
    
        // handle all archive type queries - includes taxonomies
        // echo '<pre>', print_r( $query->query_vars, true ), '</pre>';
    
        $query->set('post_type', array('reviews', 'feature', 'trailer', 'post'));
        $tentative = $query->get('actors');
          if ('' != $tentative ) {
              $person = $tentative;
              unset( $query->query_vars['actors']);
          }
        $tentative = $query->get('writers');
          if ('' != $tentative ) {
              $person = $tentative;
              unset( $query->query_vars['writers']);
          }
        $tentative = $query->get('directors');
          if ('' != $tentative ) {
              $person = $tentative;
              unset( $query->query_vars['directors']);
          }
        if ( ! isset( $person )) return;  
    
        // handle only actors, writers, or directors taxonomy queries
        $taxquery = array(
            'relation' => 'OR',
             array(
                 'taxonomy' => 'actors',
                 'field'    => 'slug',
                 'terms'    =>  $person,
             ),
             array(
                 'taxonomy' => 'writers',
                 'field'    => 'slug',
                 'terms'    =>  $person,
             ),
             array(
                 'taxonomy' => 'directors',
                 'field'    => 'slug',
                 'terms'    =>  $person,
             ),
        );
        $query->set('tax_query', $taxquery );
    }
    
    add_action('pre_get_posts', 'flmrev_archive');

    If this does not work as you expect, let me know and I’ll figure out a solution. If there’s a problem, it is likely because I misunderstood something. Just in case it’s a problem with the query itself, describe what link you followed, what’s wrong with the results, and post the resulting SQL query string from the posts_request hook.

Viewing 15 replies - 31 through 45 (of 52 total)
  • The topic ‘Linking custom taxonomies’ is closed to new replies.