php - WP_QUERY, ARRAYS, Duplicate post if has multiple categories
I have a shortcode with wp_query loop which outputs a list of categories as navigation and list of posts. The original code is much more complex so I tried to remove unnecessary lines for better understanding.
function filter_shortcode($atts, $content = null) {
global $post;
$attributes = shortcode_atts(
array(
'type' => '',
'num' => -1
), $atts);
$args = array(
'post_type' => $attributes["type"],
'posts_per_page' => $attributes["num"]
);
$post_query = new WP_Query($args);
$master_array = array();
if ($post_query->have_posts() ) {
while ($post_query->have_posts()) {
$post_query->the_post();
$nav_arr = wp_get_post_terms( get_the_ID(), 'solutions_category' );
// Problem here
foreach($nav_arr as $nav_value ) {
$nav = $nav_value->name;
}
$box_tooltip = '<div>Lorem Ipsum</div>';
$info_box_title = '<h5 style="margin-bottom: 0;">' . strtoupper($post->post_title) . '</h5>';
if (!($master_array[$nav])) {
$master_array[$nav] = array();
array_push(
$master_array[$nav],
[
'icon_title' => $info_box_title,
'tooltip' => $box_tooltip,
]
);
} else {
array_push(
$master_array[$nav],
[
'icon_title' => $info_box_title,
'tooltip' => $box_tooltip,
]
);
}
} // End of while have_posts
wp_reset_postdata();
/* Foreach master array */
foreach ((array)$master_array as $master_key => $master_value) {
/* Navigation */
$navigation .= '<div>'. $master_key .'</div>';
foreach($master_value as $query_key => $query_value) {
$output_inner = '';
foreach ($query_value as $object_key => $object_value) {
$output_inner .= $object_value;
}
/* Content */
$output_outer .= '<div class="'. $master_key .'">'. $output_inner .'</div>';
} // end foreach mastervalue
} // end foreach master
} // end if have posts
return '
<div style="margin-bottom: 30px;">'. $navigation .'</div>
<div>'. $output_outer .'</div>
';
}
add_shortcode('cpt_filter', 'filter_shortcode');
Output:
The problem is that if post has more than one category the function will output only one occurrence of post. For example "GOOGLE WORKSPACE" has two categories - "Collaboration" and "Communication" but it outputs only once.
How I can output "GOOGLE WORKSPACE" as many times as the number of categories it has, and also to have it's own category class specified?
var_dump($nav_arr) on "GOOGLE WORKSPACE" post iteration: array(2) { [0]=> object(WP_Term)#3992 (10) { ["term_id"]=> int(825) ["name"]=> string(13) "Collaboration" ["slug"]=> string(13) "collaboration" ["term_group"]=> int(0) ["term_taxonomy_id"]=> int(825) ["taxonomy"]=> string(18) "solutions_category" ["description"]=> string(0) "" ["parent"]=> int(0) ["count"]=> int(8) ["filter"]=> string(3) "raw" } [1]=> object(WP_Term)#3986 (10) { ["term_id"]=> int(824) ["name"]=> string(13) "Communication" ["slug"]=> string(13) "communication" ["term_group"]=> int(0) ["term_taxonomy_id"]=> int(824) ["taxonomy"]=> string(18) "solutions_category" ["description"]=> string(0) "" ["parent"]=> int(0) ["count"]=> int(8) ["filter"]=> string(3) "raw" } }
Tried to check if $nav_arr
has more than one value if (sizeof($nav_arr) > 1) { .... }
and create separate array, but stuck.
Answer
Solution:
The problem appears to be that in the following foreach statement:
foreach($nav_arr as $nav_value ) {
$nav = $nav_value->name;
}
You are iterating through the array once, and setting the value of $nav to "Collaboration" and then when you are looping through it the second time, (because there are two items in $nav_arr), you are just rewriting $nav to the new value of "Communication", ending up with only one $nav.
$nav should be saved as an array of values, instead of a string of a single value, like this:
foreach($nav_arr as $nav_value){
$nav[] = $nav_value;
}
Without seeing the full code, I am having a hard time understanding what all is going on.... but I think you can then replace all of:
if (!($master_array[$nav])) {
$master_array[$nav] = array();
array_push(
$master_array[$nav],
[
'icon_title' => $info_box_title,
'tooltip' => $box_tooltip,
]
);
} else {
array_push(
$master_array[$nav],
[
'icon_title' => $info_box_title,
'tooltip' => $box_tooltip,
]
);
}
}
with the following:
foreach($nav as $navitem){
$master_array[$nav] = array(
'icon_title' => $info_box_title,
'tool_tip' => $box_tooltip
),
}
Source