Support

Account

Home Forums General Issues Deeply nested post types

Solved

Deeply nested post types

  • I have a few custom post types: States, Counties, Towns and Locations.

    Each of these post types needs their own archive and single templates, save possibly for States.

    In my mind these post types are representing objects that relate together in a chain, from most specific to least specific: Location -> Town -> County -> State.

    My original thought was to create a relationship field for each post type that would relate it to its parent type. So, for Location I made a field so you can select which Town it belongs to. For Town, there’s a field so you can select which County it belongs to, and for County there’s a field so you can select which State it belongs to. You get the idea.

    That seems inefficient. And on top of that, if I’m in my single-location.php template, how would I grab information from it’s great-grandparent (State)?

    I’m not sure what solution I’m really looking for. But I know that I don’t want to have to select a Location’s county and state every time, when it could potentially be inferred from it’s own parent Town… does that make sense?

    What’s the best way to look at WP Relationships “objectively”?

    Thanks in advance!

  • Well, actually, getting information from a great-grandparent wouldn’t be that difficult.

    
    // somewhere in the loop on the single location page
    $town = get_field('town');
    $county = get_field('county', $town->ID);
    $state = get_field('state', $county->ID);
    

    You can also display all the towns on the single state page. You’d need to do a query of all of the county posts with a meta_query for the state, then a query of all the town posts with a meta query for the county and then finally a query of all location posts with a meta query for the county.

    I personally think you’re going about this in the right way. The only other choice would be to select the towns when editing the county, and etc. This would make management and querying more complex. What you’re doing will take a few steps to walk through the hierarchy but it can all be done with fairly simple queries.

    The only thing that I would say is that you look into using some type of object caching, possibly with the WP transients in order to keep the queries from slowing down your site.

  • Thanks!

    That makes a bit of sense. As I was reading I was already asking how much this will impact performance. Admittedly, the reason I’m doing this is because the previous solution we used was to place all towns/counties/locations on a couple google maps as pins using a plugin. There are thousands of records, so the site all but stopped working because of the load.

    I actually haven’t done much with caching on any WP projects, as they’ve never been this large. Would it be wise to get my queries working on a few sample records, and then shift to caching? Or should I be incorporating that right away?

    Thanks for the help!

  • I would get it working with a few, the problem with caching is that once you activate it you need to clear the cache to see any changes, and when you forget it becomes frustrating until you remember and slap yourself for forgetting (yes, I’ve done it). They are best used after development is done. You may want to look into full site caching, something like WP Super Cache. There are also several other full site caching plugin in the WP Repo

    This is a self promotional plug: https://wordpress.org/plugins/blunt-cache/
    It’s a fragment and object cache. There are also some other caching plugins similar to mine in the reply. The main difference with mine is that it uses filters and actions.

  • Having an interesting problem while trying to display the results.

    I made a gist of my code: https://gist.github.com/swthate/abc35769addcce27c03d

    I’m following the basic loop with postdata example from http://www.advancedcustomfields.com/resources/relationship/

    It is correctly echoing the title of the related town, but for the county it’s echoing the title of the “Hello World!” example post. Is that because $posts = get_field('town') and $town = get_field('town') are so similar? I have no idea. And, interestingly, it echoes the title of the town for the state.

    So, this is what the output looks like:

    Town: Burgerstadt
    County: Hello world!
    State: Burgerstadt

    When it should look like:

    Town: Burgerstadt
    County: Nuechtegall
    State: Minnesota

    And yes, those, save for Minnesota, are filler nonsense names 😉

  • I turned debugging on, and found these messages:

    
    Trying to get property of non-object ... on line 27
    Trying to get property of non-object ... on line 28
    

    These lines correspond to lines 16 and 17 in my gist.

  • Not sure if you’re still looking for help on this. I’m actually a bit confused about the line

    $posts = get_field( 'town' );

    at the beginning of your code.

    
    // single location template
    get_header();
    
    while (have_posts()) {
        the_post();
        $town   = get_field( 'town' );
        $county = get_field( 'county', $town->ID );
        $state  = get_field( 'state', $county->ID );
        ?>
            <p>
                Location: <?php the_title(); ?><br />
                Town: <?php echo $town->post_title; ?><br />
                County: <?php echo $county->post_title; ?><br />
                State:  <?php echo $state->post_title; ?><br />
            </p>
        <?php 
    }
    
    get_footer();
    
  • I thought it was needed, after reading the Relationship documentation. I’m still working on my fluency in PHP, so I don’t always catch when something looks nonsensical 😉

    The code you pasted looks really good, but sadly when I use it I get the same “Trying to get property of non-object” error for every call to Town, County and State.

    I have my relationship fields set to Post Object, so I’m not sure how they can’t be objects…

  • Are you using a Post Object field or a Relationship field?

    Also, what are you returning, Object or ID?

    The answer to one or both of these questions will help explain what’s causing the error.

  • I’m using a Relationship field and returning an Object (inside ACF it calls it a Post Object, which is kind of confusing).

  • a relationship field returns an array of objects, that’s why there is an error. Since a location can only be in one town, one town per city, etc, you might be better off using a Post Object field, which will only allow one.

    With a post object field the code I posted will work.

    For a relationship field you’d need to loop through each array, or if you have these limited to only allow one item you could use something like

    
    Location: <?php the_title(); ?><br />
    Town: <?php echo $town[0]->post_title; ?><br />
    County: <?php echo $county[0]->post_title; ?><br />
    State:  <?php echo $state[0]->post_title; ?><br />
    
  • Ah-ha, that makes sense. Thank you.

  • How would I go about reversing the “relationship” and listing all the Locations in a Town, or all the Counties in a State? Looking through the documentation, I can’t really tell if I need a second field or not. I don’t want one, I feel like there should be a way to harness the connections already made between posts, but I can’t find out how to use it.

  • That would most definitely be easier if you use a Post Object field rather than a relationship.

    With a post object you’d need to do a query, for example on the state page, to get all the counties

    
    // assuming this is on the single state template
    // $post->ID represents the id for the state post
    // this only works with a Post Object field
    $args = array(
      'post_type' => 'county',
      'posts_per_page' => -1,
      'meta_query' => array(
        'key' => 'state',
        'value' => $post-ID,
      ),
    )
    $query = new WP_Query($args);
    

    see WP_Query http://codex.wordpress.org/Class_Reference/WP_Query

    for using a relationship field Eliot has a tutorial here http://www.advancedcustomfields.com/resources/querying-relationship-fields/

  • Thanks for all the help so far. I appreciate it a lot.

    I finally got back to this project and tried your suggestion. I closed the main loop and started this one, but <?php the_title(); ?> is returning the state’s title… not the title of the counties. I might be wrong, but my assumption is that I should be able to use the_title() because this secondary loop is going through the county post type.

    Here’s my code:

    
    <?php
    $args = array(
      'post_type' => 'county',
      'posts_per_page' => -1,
      'meta_query' => array(
        'key' => 'state',
        'value' => $post->ID,
      ),
    );
    $query = new WP_Query($args);
    
    if(have_posts()) : ?>
    <ul>
    <?php while(have_posts()) : the_post(); ?>
      <li><?php the_title(); ?></li>
    <?php endwhile; ?>
    </ul>
    <?php endif; ?>
    

    Thanks again!

  • 
    <?php
    $args = array(
      'post_type' => 'county',
      'posts_per_page' => -1,
      'meta_query' => array(
        'key' => 'state',
        'value' => $post->ID,
      ),
    );
    $query = new WP_Query($args);
    
    // you need to refer to the new query object you created above
    if($query->have_posts()) : ?>
    <ul>
    <?php while($query->have_posts()) : $query->the_post(); ?>
      <li><?php the_title(); ?></li>
    <?php endwhile; ?>
    </ul>
    <?php endif; ?>
    
  • I thought of that as well, a while after I posted that last question. Still doesn’t work…

    Here’s a gist of all the code for the page, maybe there’s something above this section that is interfering?

    https://gist.github.com/swthate/cabf1ffe9ca329e0a834

  • To be honest, I’m not seeing anything.

    The only suggestions I can make are to remove this line that appears above the new query

    <?php wp_reset_query(); ?>

    It shouldn’t interfere, but it’s not needed there, that needs to be after the <?php endif; ?> of your nested query.

    The other suggestions is to name the new query something else, it could be the $query is a problem, but there’s no reason I know of that it should be.

    
    <?php
          $args = array(
            'post_type' => 'county',
            'posts_per_page' => -1,
            'meta_query' => array(
              'key' => 'state',
              'value' => $post->ID,
            ),
          );
          $county_query = new WP_Query($args);
          // you need to refer to the new query object you created above
          if($county_query->have_posts()) : ?>
          <ul>
          <?php while($county_query->have_posts()) : $county_query->the_post(); ?>
            <li><?php the_title(); ?></li>
          <?php endwhile; ?>
          </ul>
          <?php endif; ?>
    
  • Yeah, I’ve tried both of those suggestions previously as well. Still no luck.

    The client has requested to go in a much simpler direction dealing only with Towns with nothing else. In a way I’m glad, but I would have loved to figured this out in any case!

Viewing 19 posts - 1 through 19 (of 19 total)

The topic ‘Deeply nested post types’ is closed to new replies.