0

So I'm working on a medical site that has a custom post type "doctors". Within this post type are custom taxonomies for "locations" and "procedures". I've created a custom taxonomy-locations.php file to control how my locations pages look, on this page is some general information like contact info, maps, related doctors. I also need to include a list of all procedures offered at each location. Since procedures are attached to each doctor, not to each location, I created a function containing a loop to run through all doctors tagged at the current location and output a comma separated list of all tagged procedures term ids. See below:

// Get the doctors procedures
function location_doctors_procedure_loop() {

$tax_slug = get_query_var( 'locations' );

$args = array(
    'posts_per_page'    =>  -1,
    'order'             =>  'DESC',
    'post_type'         =>  'our_team',
    'locations'         =>  $tax_slug
); 

// The Query
$the_query = new WP_Query( $args );

// The Loop
if ( $the_query->have_posts() ) {

    while ( $the_query->have_posts() ) {

    $the_query->the_post();

        $terms = get_the_terms( $post, 'procedures' );

        if ( !empty($terms) ) {
            foreach( $terms as $term ) {
                echo $term->term_id . ','; 
            }

        }

    }

    wp_reset_postdata();

} 
}

I then created a function that loops through all active procedure taxonomies and lists them hierarchically as parent, child, grandparent. See below:

// Get the procedures
function tax_location_procedures() {

$doctor_procedures = location_doctors_procedure_loop();

$terms = get_terms( array(
    'taxonomy'      =>  'procedures',
    'hide_empty'    =>  true,
    'include'       =>  array( $doctor_procedures ),
) );

echo '<h2 class="doctor-bio-procedure-condition-header">Procedures</h2>';

if ( !empty($terms) ) {
    echo '<div class="doctor-bio-procedures">';
    foreach( $terms as $term ) {
        if( $term->parent == 0 ) {
        ?>
            <p class="doctor-bio-procedure-condition-sub-header"><?php echo $term->name; ?></p>
        <?php 
            echo '<ul>';
            foreach( $terms as $childterm ) {
                if($childterm->parent == $term->term_id) {
                    echo '<li>' . $childterm->name . '</li>';
                    echo '<ul>';
                    foreach( $terms as $grandchildterm ) {
                        if($grandchildterm->parent == $childterm->term_id) {
                            echo '<li>' . $grandchildterm->name . '</li>';
                        }
                    }
                    echo '</ul>';
                }
            }
            echo '</ul>';
        }
    }
    echo '</div>';

} 
}

What I'm trying to do is use my first function "location_doctors_procedure_loop()" to populated the 'include' arguments array in "function tax_location_procedures()". The problem I'm having is that while "location_doctors_procedure_loop()" does echo out a comma separated list of the correct term IDs (e.g 231,229,) it does nothing for my 'include" argument because its echoing as a string rather than integers, so it's reading as

'include'    => array('231,229,')

rather than

'include'    => array(231,229,)

I'm stuck on this and have already spent the better part of a day trying to get this to work properly. Any help you guys can provide would be greatly appreciated.

2
  • 1
    'include' => explode(',', trim($doctor_procedures)), ? Mar 14, 2018 at 14:18
  • 4
    There's also the handy wp_parse_id_list() core function.
    – birgire
    Mar 14, 2018 at 14:20

4 Answers 4

4

You should be able to change these lines

if ( !empty($terms) ) {
    foreach( $terms as $term ) {
        echo $term->term_id . ','; 
    }

}

to this:

if ( !empty($terms) ) {
    // create an empty array
    $procedures_to_include = array();
    foreach( $terms as $term ) {
        // now instead of echoing, add each term to the array
        $procedures_to_include[] = $term->term_id;
    }

}

Basically instead of echoing manually, you're creating the array to begin with, and in your get_terms call you can just use $procedures_to_include directly:

$terms = get_terms( array(
    'taxonomy'      =>  'procedures',
    'hide_empty'    =>  true,
    'include'       =>  $procedures_to_include
) );
2
  • 1
    The location_doctors_procedure_loop() then also need to return $procedures_to_include. This seems to be the correct way of achieving this, why create a comma separated string if you really want an array =) Mar 14, 2018 at 14:19
  • You guys are great. This was also perfect Mar 14, 2018 at 14:54
1

So there's a few things you need to do in location_doctors_procedure_loop() for this to work:

  1. Have the function return values, rather than echo them. If you need to assign the output of the function to a variable, or use it as an argument, it needs to be returned. echo outputs the values to the screen, which you don't want.
  2. To do this you'll need to build up an array of values within the loop. Do this by creating an empty array at the beginning, then adding procedures to it in the loop before ultimately returning the array.
  3. Probably not required, but it might be a good idea to strip out duplicates from the array.

But you can go further. All you're doing with these IDs is retrieving the terms. Why not just pass the full terms all the way through, thus avoiding the need to call get_terms() at all. You can avoid duplicates by using the term ID as the key of the array.

Here's a version of your function with this all applied:

function location_doctors_procedure_loop() {
    /**
     * Create the array to return at the end.
     */
    $procedures = array();

    /**
     * Get all doctors for the current location.
     * We're not using template tags, so a custom WP_Query is unnecessary.
     */
    $doctors = get_posts( array(
        'posts_per_page' => -1,
        'order'          => 'DESC',
        'post_type'      => 'our_team',
        'locations'      => get_query_var( 'locations' )
    ) );

    /**
     * Loop through each doctor and add its procedures' to the array.
     * If a term is added a second time, it will just replace the original 
     * because the key is the ID.
     */
    foreach ( $doctors as $doctor ) {
        $terms = get_the_terms( $doctor, 'procedures' );

        if ( ! empty( $terms ) ) {
            foreach( $terms as $term ) {
                $procedures[$term->term_id] = $term;
            }
        }
    }

    /**
     * Return the array.
     */
    return $procedures;
}

Now in your tax_location_procedures() function you can just pass this directly to $terms:

$terms = location_doctors_procedure_loop();
2
  • No problem. I hope my explanation of the approach makes sense. Mar 14, 2018 at 14:54
  • Perfect sense. Thats such a clean solution, thank you so much Mar 14, 2018 at 15:03
0

Turn your comma seperated string into an array like this :

$inclusionArray = explode(',', $doctor_procedures);

Then use that array.

'include'    => $inclusionArray
3
  • $doctor_procedures is not going to contain the values as a string because the location_doctors_procedure_loop() function is using echo. Mar 14, 2018 at 14:21
  • @JacobPeattie According to the question, that is exactly what it is doing : "'include' => array('231,229,')"
    – Stender
    Mar 14, 2018 at 14:25
  • It's not working though, hence the question, and one of the reasons its not working is because the function is echoing when it should return. This answer will solve the issue of the function is returning a string, but it's not returning anything. Mar 14, 2018 at 14:29
0

You need to convert values into an integer array because you are getting string in this

$doctor_procedures = location_doctors_procedure_loop();

variable. You can convert it by using following option :

$doctor_procedures_int_val = array_map('intval', explode(',',  $doctor_procedures));

after this you need to pass this new array variable in "include" index.

so currently you are getting

'include'    => array('231,229,')

by using array_map('intval', explode(',', '231,229,')) this you will get array(231,229,)

So need to update your function with this :

$doctor_procedures = location_doctors_procedure_loop();
$doctor_procedures_int_val = array_map('intval', explode(',',  $doctor_procedures));
$terms = get_terms( array(
                  'taxonomy'      =>  'procedures',
                  'hide_empty'    =>  true,
                  'include'       =>  array( $doctor_procedures_int_val ),
                 ) );

Or you can make changes in your first function as well. Instead of doing echo the ids, you can put them in an array. then you do not need to do the above steps.

Let me know, if you need any more clarification.

1
  • location_doctors_procedure_loop() is echoing out the term ids, not returning them. So this won't resolve the issue because $doctor_procedures isn't actually going to contain the string. Since location_doctors_procedure_loop() needs to be modified anyway it's simpler to have that function return the desired values rather than trying to convert them. Mar 14, 2018 at 14:44

Your Answer

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

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