How to get current page menu item ancestor name wordpress - php

I would like to know how to retrieve as variable the name of the current page.
For exemple, My menu is like :
Item 1
Item 2 => sub-item 1
Item 1 & 2 are custom links. sub-item1 is my page.
When I'm on this page, I want to retrieve "Item 2" name (to build my custom breadcumbs)
Thanks

BREADCRUMBS:
Here is a breadcrumbs function that work with the hierarchy of your menu. Add this to your theme's 'functions.php'.
function my_menu_breadcrumb($theme_location, $separator = ' > ') {
$locations = get_nav_menu_locations();
if ( isset( $locations[ $theme_location ] ) ) {
$menu = wp_get_nav_menu_object( $locations[ $theme_location ] );
$menu_items = wp_get_nav_menu_items($menu->term_id);
_wp_menu_item_classes_by_context( $menu_items );
$breadcrumbs = array();
foreach ( $menu_items as $menu_item ) {
if ($menu_item->current) {
$breadcrumbs[] = "<span title=\"{$menu_item->title}\">{$menu_item->title}</span>";
}
else if ($menu_item->current_item_ancestor) {
$breadcrumbs[] = "{$menu_item->title}";
}
}
echo implode($separator, $breadcrumbs);
}
}
You can then call as <?php my_menu_breadcrumb('header-menu'); ?> where 'header-menu' is the menu location name. In the loop, $menu_item->title will return page title and $menu_item->url it's URL.
PARENT MENU TITLE:
Here is the function to get parent menu item title(s) of current page - add this to your theme's 'functions.php'.
function my_menu_parent($theme_location) {
$locations = get_nav_menu_locations();
if ( isset( $locations[ $theme_location ] ) ) {
$menu = wp_get_nav_menu_object( $locations[ $theme_location ] );
$menu_items = wp_get_nav_menu_items($menu->term_id);
_wp_menu_item_classes_by_context( $menu_items );
$breadcrumbs = array();
foreach ( $menu_items as $menu_item ) {
if ($menu_item->current_item_ancestor) {
$breadcrumbs[] = $menu_item->title;
}
}
return $breadcrumbs;
}
}
You can then call as below where 'header-menu' is the menu location name.
$parentitems = my_menu_parent( 'header-menu' );
foreach ( $parentitems as $parentitem ) {
echo $parentitem."<br>";
}

You can user this
$pagename = get_query_var('pagename');
if ( !$pagename && $id > 0 ) {
// If a static page is set as the front page, $pagename will not be set. Retrieve it from the queried object
$post = $wp_query->get_queried_object();
$pagename = $post->post_name;
}

There are plenty of tutorials and code snippets online describing how to show the active page’s children (or if on one of those children, the active page’s siblings) as a sub-menu in WordPress. Usually something like this:
<?php
$ref_post = empty($post->post_parent) ? $post->ID : $post->post_parent;
$children = wp_list_pages('title_li=&child_of='.$ref_post.'&echo=0');
if ($children) {
echo "<ul>$children</ul>";
}
?>
for ref:-https://www.minddevelopmentanddesign.com/blog/showing-current-pages-parents-sub-menu-items-custom-nav-menu-wordpress/

Related

get parent element title using wp_get_nav_menu_items

I need the parent element's title as a variable and also the submenu of it.
Currently I have:
function navigation_footer() {
$menu_name = 'footer_nav';
if (($locations = get_nav_menu_locations()) && isset($locations[$menu_name])) {
$menu = wp_get_nav_menu_object($locations[$menu_name]);
$menu_items = wp_get_nav_menu_items($menu->term_id);
foreach ((array) $menu_items as $key => $menu_item) {
$title = $menu_item->title;
$url = $menu_item->url;
$type = get_post_meta( $item->menu_item_parent, '_menu_item_type', true );
$title_parent = get_post( $object_id )->post_title;
$menu_list .= "\t\t\t\t". '<div class="fl-links"><h2>'. $title_parent .'</h2>' ."\n";
$menu_list .= "\t\t\t\t\t". '<p>'. $title .'</p></div>' ."\n";
}
}
echo $menu_list;
}
The variable type gets me the title of a post which was kinda workaround.
Still, it's in a foreach so I'm getting a mess instead of what I actually want.
As I'm a fairly beginner in PHP I am stuck.
Each element in WP is going to be an individual link. The parent is only being used as a placeholder for the title followed by the links.
[Current output](https://i.stack.imgur.com/xsGRS.png)
[My desired output](https://i.stack.imgur.com/SP14p.png)
[WP Menu Parent/Child](https://i.stack.imgur.com/Z5d8K.png)

WordPress/PHP get list of all links in primary navigation

I am trying to create a list of all links in primary navigation on my WordPress site. I am trying to output the link as URL: in a script tag using a foreach loop.
I am stuck trying to list of of the navitems links using $navItem->url in my foreach loop. It doesn't return anything / false.
Instead of $locations[$menuLocations] I have tried simply just write primary menu name as well: $locations['primary'] but no luck so far.
function get_nav_menu_items_by_location( $location, $args = [] ) {
$html = '<script type="application/ld+json" alt="hejtest">';
// Get all locations
$menuLocations = get_nav_menu_locations();
// Get object id by location
$object = wp_get_nav_menu_object( $locations[$menuLocations] );
// Get menu items by menu name
$menu_items = wp_get_nav_menu_items($object);
foreach ( $menu_items as $navItem ) {
$html .= '"url":"' . $navItem->url . '"';
}
$html .= "</script>";
echo $html;
}
add_action('wp_head', 'get_nav_menu_items_by_location');
Well... I did a refactor of your code and it's works ;)
Try with this way:
function get_nav_items() {
$menu_slug_to_retrieve = 'main'; // This can be main, primary, what ever...
$locations = get_nav_menu_locations();
$menu = wp_get_nav_menu_object( $locations[ $menu_slug_to_retrieve ] );
$menu_items = wp_get_nav_menu_items( $menu->term_id );
$menu_items_json = array(); // Prepare the array to convert to json
// Loop it
if ( $menu_items ) {
foreach ( $menu_items as $item ) {
$menu_items_json[] = array( 'url' => $item->url );
}
$html = sprintf(
'<script type="application/ld+json" id="custom-json">%s</script>',
json_encode( $menu_items_json )
);
echo $html;
}
}
add_action( 'wp_head', 'get_nav_items' );
Regards!

WordPress child, grandchild, great grandchild categories must use parent category template

I have created a template named category-south-africa.php. I would like all child, grandchild, great grandchild categories to automatically use this template. For example, all these categories must use the category-south-africa.php template:
/category/south-africa/
/category/south-africa/stellenbosch/
/category/south-africa/stellenbosch/wine-farm/
/category/south-africa/stellenbosch/wine-farm/wine-varietal/
Does anyone perhaps have a php function solution?
You can create you own template for this. You can check the category_template filter and do something like this.
add_filter('category_template', 'add_top_term_template');
function add_top_term_template($template) {
$term = get_queried_object();
$parent = $term->parent;
if($parent === 0) {
return $template;
}
$topLevel = null;
while($parent !== 0) {
$topLevel = get_term($parent);
$parent = $topLevel->parent;
}
$templates = ["term-top-level-{$topLevel->slug}.php"];
return locate_template($templates);
}
You can find more info about the filter here: https://codex.wordpress.org/Plugin_API/Filter_Reference/category_template
get_ancestors() that returns an array containing the parents of any given category.
use like get_ancestors( child_category_id, 'category' );
Check the value is in the array or not. if yes then define template name.
You can use this function to check if the current category is a child category and set the template to the same you have for the parent category. Put this in the functions.php of your theme.
function childcategory_template( $template ) {
$cat = get_queried_object();
if( 0 < $cat->category_parent )
$template = locate_template( 'category-south-africa.php');
return $template;
}
add_filter( 'category_template', 'childcategory_template' );
Edit after comment: You can also check the name (slug) and set the $template variable taking the name (slug) of the parent into account.
function childcategory_template( $template ) {
$cat = get_queried_object();
if( 0 < $cat->category_parent )
$parent_id = $cat->category_parent;
if ( get_category( $parent_id )->slug == "south-africa" ) {
$template = locate_template( 'category-south-africa.php');
} else if ( get_category( $parent_id )->slug == "north-africa" ) {
$template = locate_template( 'category-north-africa.php');
}
return $template;
}
add_filter( 'category_template', 'childcategory_template' );

howto iterate menu items in wordpress?

I read wordpress code documents about how to iterate menu items, and then I wrote this code in index.php:
<?php
$menu_name = 'top_menu';
$array_menu = wp_get_nav_menu_items($menu_name);
foreach ((array)$array_menu as $mol) ;
{
echo $mol;
}
?>
But it doesn't work. And is returning nothing. Casting to array didn't help so.
I need to echo items menu title one by one. without any html list tags.
$navItem is an object, so you can not just echo it, try to echo its properties like this:
foreach ($array_menu as $navItem ) {
echo '<li>'.$navItem->title.'</li>';
}
This might help:
<?php
function get_menu_items_by_registered_slug($menu_slug) {
$menu_items = array();
if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menu_slug ] ) ) {
$menu = get_term( $locations[ $menu_slug ] );
$menu_items = wp_get_nav_menu_items($menu->term_id);
}
return $menu_items;
}
$show_menus = [];
$menus = get_menu_items_by_registered_slug('primary');
foreach( $menus as $menu ) {
$show_menus[] = $menu->title;
}
echo '<pre>';
print_r($show_menus);
?>

2 Layouts for a WooCommerce shop

I have to categories named "Collectie" and "Shop", what I want is different layouts for the children of both categories.
I already tried this with the template_include function like this:
function lab5_template_include( $template ) {
if ( category_has_children('collectie')) {
$template = get_stylesheet_directory() . '/woocommerce/archive-product-collectie.php';
}elseif ( is_product_category('shop')) {
$template = get_stylesheet_directory() . '/woocommerce/archive-product-shop.php';
}
return $template;
}
How do I do that?
EDIT
I solved it with the solution from https://wordpress.org/support/topic/different-page-layouts-for-category-vs-subcategory
i added the next lines to taxonomy-product_cat.php
// We need to get the top-level category so we know which template to load.
$get_cat = $wp_query->query['product_cat'];
// Split
$all_the_cats = explode('/', $get_cat);
// How many categories are there?
$cat_count = count($all_the_cats);
//
// All the cats say meow!
//
// Define the parent
$parent_cat = $all_the_cats[0];
// Collectie
if ( $parent_cat == 'collectie' ) woocommerce_get_template( 'archive-product-collectie.php' );
// Shop
elseif ( $parent_cat == 'shop' ) woocommerce_get_template( 'archive-product.php' );
I think you'd be better off running a while loop to determine the parent level category name. Then you can match it against the different parent categories you want to display differently.
edit lab5_template_include() should use is_product_category() instead of is_product_taxonomy() which returns true on product category and tag archives.
function lab5_template_include( $template ) {
if( is_product_category()){
$slug = get_query_var('product_cat');
$cat = get_term_by( 'slug', $slug, 'product_cat' );
$catParent = so_top_product_category_slug($cat);
// locate the new templates
if ( 'collectie' == $catParent ) {
$new_template = locate_template( array( 'woocommerce/archive-product-collectie.php' ) );
} elseif ( 'shop' == $catParent ) ) {
$new_template = locate_template( array( 'woocommerce/archive-product-shop.php' ) );
}
// set the new template if found
if ( '' != $new_template ) {
$template = $new_template ;
}
}
return $template;
}
add_filter('template_include', 'lab5_template_include', 20 );
edit bug fixes and improved efficiency of so_top_product_category_slug(). Now tested and working.
// get the top-level parent product category from a term object or term slug
function so_top_product_category_slug($cat) {
if( is_object( $cat ) ){
$catid = $cat->term_id;
} else {
$cat = get_term_by( 'slug', $cat, 'product_cat' );
$catid = $cat->term_id;
}
$parentId = $cat->parent;
$parentSlug = $cat->slug;
while ($parentId > 0) {
$cat = get_term_by( 'id', $parentId, 'product_cat' );
$parentId = $cat->parent; // assign parent ID (if exists) to $catid
$parentSlug = $cat->slug;
}
return $parentSlug;
}

Categories