0

I have a Custom Post Type ("Rental"). I am using the code from this article I found to display Rental custom posts on a page, with the Categories of a custom Taxonomy ("Region") as headings between the posts that belong to that Category. For example, it outputs this structure:

  • Region Category #1
    • Post #1
    • Post #3
    • Post #4
  • Region Category #2
    • Post #2
    • Post #5
    • Post #6

I am now trying to add subheadings of Categories from a second Custom Taxonomy ("Property"), but only once in the loop. I'm not sure where to start (do I need another foreach loop, or can I add to the existing one?), any help or direction would be much appreciated.

For example, I'm looking to get this output structure:

  • Region Category #1
    • Property Category #1
      • Post #1
    • Property Category #2
      • Post #3
      • Post #4
  • Region #2
    • Property Category #3
      • Post #2
      • Post #5
    • Property Category #4
      • Post #6

This is the code I have so far:

  <?php
    // get all the categories from the database
    $cats = get_categories('taxonomy=region');
    // loop through the categries
    foreach ($cats as $cat) {
        // setup the cateogory ID
        $cat_id= $cat->term_id;
        // Make a header for the cateogry
        echo "<h1>".$cat->name."</h1>";  
        // create a custom wordpress query
        $args = array(
            'tax_query' => array(
              array(
                'taxonomy' => 'region',
                'field' => 'slug',
                'terms' => ".$cat->name."
              )
            )
        );
        $query = query_posts( $args );
        // start the wordpress loop!
        if (have_posts()) : while (have_posts()) : the_post(); ?>
            <?php // create our link now that the post is setup ?>
            <p><a href="<?php the_permalink();?>"><?php the_title(); ?></a></p>

        <?php endwhile; endif; // done our wordpress loop. Will start again for each category ?>
        <?php wp_reset_query(); ?>
  <?php } // done the foreach statement ?>
3
  • 1
    I'm off to bed now. First of all, don't use query_posts, ever. Secondly, I have done a similar post in last week that can be useful inm a solution to this problem with some modification. Commented Feb 1, 2015 at 20:07
  • Check this out - a very similar question with an accepted answer posted by @PieterGoosen and a couple of alternitive methods. Have a bash and post your results, happy to help if you are still struggling.
    – David Gard
    Commented Feb 2, 2015 at 9:39
  • Thank you for your comments. As I mentioned on Privateer's answer, this is out of my depth at this time (I'm not able to makes sense of the code at the link you provided) so I will look at hiring a more experienced developer than myself for this project and when I have time try to level up my skills.
    – codeview
    Commented Feb 2, 2015 at 21:35

1 Answer 1

0

You really should try to avoid using query_posts if at all possible.

See When to Use WP Query vs Query Posts vs Get Posts

Here is a pass through a loop using WP_Query:

$args = array(
    'tax_query' => array(
        array(
            'taxonomy' => 'region',
            'field' => 'id',
            'terms' => $region_id
        )
    )
);
$properties = new WP_Query( $args );
if ( ! $properties->have_posts() ) {
    # This should not happen, but just in case
    echo "<p>No properties in this region!</p>";
} else {
    while( $properties->have_posts() ) {
        $property = $properties->next_post();
        $property_id = $property->ID;
        $property_url = get_permalink( $property->ID );
        $property_title = get_the_title( $property->ID );
    }
    # If you need to do the loop over later
    # $properties->rewind_posts();
}

Also, I'd recommend using get_terms to grab your regions:

$regions = get_terms( 'region' );
if ( is_wp_error( $regions ) ) {
    die( $regions );
}

That being said, you have a few different options on how to do this. I'd recommend mapping out the flow of how you are going to do it then write your code.

  • Grab all regions having properties in them

  • Loop through each region drawing your header and grabbing all properties in the region

  • Loop through each property in the region

While doing this loop, you can use get_the_terms( $property-ID, 'property_type' ) to gather all of the property types for each property.

You might then create an array of property types and create some kind of relation between the property types and the properties.

For example:

# Before the loop:
$property_types = array();

# .. looping through the properties ..
if ( $properties->have_posts() ) {
   while ( $properties->have_posts() ) {
      $property = $properties->next_post();
      # Grab all property type terms for this property
      $types = get_the_terms( $property->ID, 'property_type' );
      # Cycle through and build out our property_types array started previously
      foreach ( $types as $type ) {
         # we add them by slug so we can use a key sort later
         if ( !array_key_exists( $type->slug, $property_types ) ) {
            # The slug is not a key in our array, add it and attach the type under a data key
            $property_types["{$type->slug}"]['data'] = $type;
         }
         # Add the property under the properties key for the current type
         # - this will cause properties to possibly show up multiple times
         # - if that is not wanted, do a key check before adding the property
         $property_types["{$type->slug}"]['properties']["{$property->ID}"] = $property;
      }
      # ... anything else in the loop
   }
}

# Sort the property types in this region
ksort( $property_types );

# Cycle through the property types array we built and 
# draw them all out
foreach ( $property_types as $info ) {
   $type_data = $info['data'];
   $properties = $info['properties'];
   $type_url = get_permalink($type_data->term_id);
   $type_name = $type_data->name;
   echo '<h2><a href="' . $type_url . '">' . $type_name . '</a></h2>';
   foreach ( $properties as $property ) {
      $property_url = get_permalink( $property->ID );
      $property_name = get_the_title( $property->ID );
      echo '<p><a href="' . $property_url . '">' . $property_name . '</a></p>';
   }
}

There are many ways to do this, but the above should work reasonably decently.

4
  • Thank you for your answer. Unfortunately, as a PHP novice, I do not follow much of it. I tried your example code but receive a parse error for the {$type_url}'s first { (7 lines from the bottom). Because this is so far out of my skill level at this time, I will look at hiring an experienced developer. I will mark your answer as accepted since you were kind enough to elaborate and I'm sure someone will find it useful and tweakable for their needs.
    – codeview
    Commented Feb 2, 2015 at 21:31
  • Sorry about that. I fixed it. I'm used to doing things a different way and forgot to escape the quotes.
    – Privateer
    Commented Feb 2, 2015 at 23:56
  • I get a "Fatal error: Call to a member function have_posts() on a non-object" on the if ( $properties->have_posts() ) { line
    – codeview
    Commented Feb 3, 2015 at 5:03
  • Did you include the code before that (the wp_query call?) The last section of code is just to show what to do once you have your properties selected. It isn't designed to be a complete solution, simply to show how you can go about doing it in a fairly detailed manner.
    – Privateer
    Commented Feb 3, 2015 at 17:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.