I am trying to get_posts() from a category that has a subcategory within. To show an example please look at the image just below.
So, as you can see. The parent and the children have posts inside. I want to preview the content within the children only once not twice. The following image shows what I mean. You can see that some items are retrieved twice.
I have created a shortcode, but I don't know how to make the first part of it get only the posts in the parent category (from desserts first), then show the posts in the subcategories (Baked cookie dough and Pancakes) if exist.
add_shortcode('TEDS_MENU', 'fetch_teds_menu_items');
function fetch_teds_menu_items($atts)
{
$atts = shortcode_atts(array(
'category_name' => ''
), $atts);
$category = get_term_by('name', $atts['category_name'], 'category');
if (!$category) {
return '';
}
$args = array(
'category__in' => [$category->term_id],
'post_type' => 'menu',
'numberposts' => -1,
'post_status' => 'publish'
);
$subcategories = get_categories(
array(
'parent' => $category->term_id
)
);
$output = '<section id="' . $category->slug . '">';
$menu_items = get_posts($args);
foreach ($menu_items as $menu_item) {
setup_postdata($menu_item);
$output .= '<div class="teds-menu-item-wrapper">';
$output .= '<h3 class="teds-menu-item__title">' . $menu_item->post_title . '</h3>';
$output .= '<div class="teds-menu-item">';
$output .= '<div class="teds-menu-item-description">';
$output .= '<p class="teds-menu-item-description__text">' . $menu_item->post_content . '</p>';
$output .= '</div>';
$output .= '<ul class="teds-menu-prices-list">';
if (get_post_meta($menu_item->ID, 'regular_size_price')[0] || get_post_meta($menu_item->ID, 'large_size_price')[0]) {
$output .= '<li class="menu-prices-list--item">R ' . get_post_meta($menu_item->ID, 'regular_size_price')[0] . ' EGP</li>';
$output .= '<li class="menu-prices-list--item">L ' . get_post_meta($menu_item->ID, 'large_size_price')[0] . ' EGP</li>';
}
if (get_post_meta($menu_item->ID, 'price')[0]) {
$output .= '<li class="teds-menu-prices-list--item">' . get_post_meta($menu_item->ID, 'price')[0] . ' EGP</li>';
}
$output .= '</ul>';
$output .= '</div>';
$output .= '</div>';
}
if ($subcategories) {
$output .= '<section class="teds-menu-subcategory">';
foreach ($subcategories as $subcategory) {
$output .= '<div class="teds-menu-subcategory__content">';
$output .= '<h2 class="teds-subcategory-title">' . $subcategory->name . '</h2>';
$subcategory_items = get_posts(array(
'category' => $subcategory->cat_ID,
'post_type' => 'menu',
'numberposts' => -1,
'post_status' => 'publish'
));
foreach ($subcategory_items as $subcategory_item) {
$output .= '<div class="teds-subcategory-item">';
$output .= '<div class="teds-subcategory-item__content">';
$output .= '<h3 class="teds-subcategory-item__title">' . $subcategory_item->post_title . '</h3>';
if ($subcategory_item->post_content) {
$output .= '<p class="class="menu-prices-list--item teds-subcategory-item__desc">' . $subcategory_item->post_content . '</p>';
}
$output .= '</div>';
if (get_post_meta($subcategory_item->ID, 'price')[0]) {
$output .= '<ul class="teds-menu-prices-list">';
$output .= '<li class="teds-menu-prices-list--item">' . get_post_meta($subcategory_item->ID, 'price')[0] . ' EGP</li>';
$output .= '</ul>';
}
$output .= '</div>';
}
$output .= '</div>';
wp_reset_postdata();
}
wp_reset_postdata();
$output .= '</section>';
}
$output .= "</section>";
wp_reset_postdata();
return $output;
}
UPDATE: Following @Sally CJ's answer solves the issue of some posts being displayed twice. But in some other categories, posts have disappeared. For example, the following categories include posts but they are not displayed any more:
I am trying to get_posts() from a category that has a subcategory within. To show an example please look at the image just below.
So, as you can see. The parent and the children have posts inside. I want to preview the content within the children only once not twice. The following image shows what I mean. You can see that some items are retrieved twice.
I have created a shortcode, but I don't know how to make the first part of it get only the posts in the parent category (from desserts first), then show the posts in the subcategories (Baked cookie dough and Pancakes) if exist.
add_shortcode('TEDS_MENU', 'fetch_teds_menu_items');
function fetch_teds_menu_items($atts)
{
$atts = shortcode_atts(array(
'category_name' => ''
), $atts);
$category = get_term_by('name', $atts['category_name'], 'category');
if (!$category) {
return '';
}
$args = array(
'category__in' => [$category->term_id],
'post_type' => 'menu',
'numberposts' => -1,
'post_status' => 'publish'
);
$subcategories = get_categories(
array(
'parent' => $category->term_id
)
);
$output = '<section id="' . $category->slug . '">';
$menu_items = get_posts($args);
foreach ($menu_items as $menu_item) {
setup_postdata($menu_item);
$output .= '<div class="teds-menu-item-wrapper">';
$output .= '<h3 class="teds-menu-item__title">' . $menu_item->post_title . '</h3>';
$output .= '<div class="teds-menu-item">';
$output .= '<div class="teds-menu-item-description">';
$output .= '<p class="teds-menu-item-description__text">' . $menu_item->post_content . '</p>';
$output .= '</div>';
$output .= '<ul class="teds-menu-prices-list">';
if (get_post_meta($menu_item->ID, 'regular_size_price')[0] || get_post_meta($menu_item->ID, 'large_size_price')[0]) {
$output .= '<li class="menu-prices-list--item">R ' . get_post_meta($menu_item->ID, 'regular_size_price')[0] . ' EGP</li>';
$output .= '<li class="menu-prices-list--item">L ' . get_post_meta($menu_item->ID, 'large_size_price')[0] . ' EGP</li>';
}
if (get_post_meta($menu_item->ID, 'price')[0]) {
$output .= '<li class="teds-menu-prices-list--item">' . get_post_meta($menu_item->ID, 'price')[0] . ' EGP</li>';
}
$output .= '</ul>';
$output .= '</div>';
$output .= '</div>';
}
if ($subcategories) {
$output .= '<section class="teds-menu-subcategory">';
foreach ($subcategories as $subcategory) {
$output .= '<div class="teds-menu-subcategory__content">';
$output .= '<h2 class="teds-subcategory-title">' . $subcategory->name . '</h2>';
$subcategory_items = get_posts(array(
'category' => $subcategory->cat_ID,
'post_type' => 'menu',
'numberposts' => -1,
'post_status' => 'publish'
));
foreach ($subcategory_items as $subcategory_item) {
$output .= '<div class="teds-subcategory-item">';
$output .= '<div class="teds-subcategory-item__content">';
$output .= '<h3 class="teds-subcategory-item__title">' . $subcategory_item->post_title . '</h3>';
if ($subcategory_item->post_content) {
$output .= '<p class="class="menu-prices-list--item teds-subcategory-item__desc">' . $subcategory_item->post_content . '</p>';
}
$output .= '</div>';
if (get_post_meta($subcategory_item->ID, 'price')[0]) {
$output .= '<ul class="teds-menu-prices-list">';
$output .= '<li class="teds-menu-prices-list--item">' . get_post_meta($subcategory_item->ID, 'price')[0] . ' EGP</li>';
$output .= '</ul>';
}
$output .= '</div>';
}
$output .= '</div>';
wp_reset_postdata();
}
wp_reset_postdata();
$output .= '</section>';
}
$output .= "</section>";
wp_reset_postdata();
return $output;
}
Share Improve this question edited Jul 13, 2019 at 14:20 Tes3awy asked Jul 12, 2019 at 22:54 Tes3awyTes3awy 1058 bronze badgesUPDATE: Following @Sally CJ's answer solves the issue of some posts being displayed twice. But in some other categories, posts have disappeared. For example, the following categories include posts but they are not displayed any more:
1 Answer
Reset to default 1If you don't want to include posts in child categories, use the category__in
parameter:
$args = array(
'category__in' => [ get_cat_ID( $category_name ) ], // use category__in
//'category_name' => $category_name, // and not this.
'post_type' => 'menu',
'numberposts' => -1,
'post_status' => 'publish'
);
And although the above would give you what you wanted, the following might help you..
function fetch_teds_menu_items($atts)
{
$atts = shortcode_atts(array(
'category_name' => ''
), $atts);
if ( ! $category = get_term_by( 'name', $atts['category_name'], 'category' ) ) {
return '';
}
$args = array(
'category__in' => [ $category->term_id ],
'post_type' => 'menu',
'numberposts' => -1,
'post_status' => 'publish'
);
$meta_data = get_term_meta($category->term_id, 'category_featured_image', TRUE);
// $category_image = wp_get_attachment_url($meta_data);
$subcategories = get_categories(
array(
'parent' => $category->term_id
)
);
$output = '<section id="' . $category->slug . '">';
...
return $output;
}
I.e. I use get_term_by()
to get the full category object by its name (not slug, but can be slug).
PS: The category
parameter also include child categories — 'category' => $subcategory->cat_ID,
.