WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The code below shows the active sub menu of the Main Menu. It's nearly perfect, however, I need it to show ALL subitems of these sub items, and their children. AKA unlimited depth. Thanks in advance!

To further clarify here is an example:

WP - Main Menu

  1. Home
  2. About
  3. News (Active Menu Item)
    • Press
    • Social
      • Facebook
      • Twitter
    • Speeches
  4. Contact

With the code currently, if I'm on News, Press, Social, Facebook, or Twitter Page, it shows the side menu:

  1. Press
  2. Social
  3. Speeches

That is what I want, except that on all of those pages, "Social"'s two children (Facebook and Twitter should appear under social as well.

class Selective_Walker extends Walker_Nav_Menu
        function walk( $elements, $max_depth) {

            $args = array_slice(func_get_args(), 2);
            $output = '';

            if ($max_depth < -1) //invalid parameter
                return $output;

            if (empty($elements)) //nothing to walk
                return $output;

            $id_field = $this->db_fields['id'];
            $parent_field = $this->db_fields['parent'];

            // flat display
            if ( -1 == $max_depth ) {
                $empty_array = array();
                foreach ( $elements as $e )
                    $this->display_element( $e, $empty_array, 1, 0, $args, $output );
                return $output;

             * need to display in hierarchical order
             * separate elements into two buckets: top level and children elements
             * children_elements is two dimensional array, eg.
             * children_elements[10][] contains all sub-elements whose parent is 10.
            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( 0 == $e->$parent_field )
                    $top_level_elements[] = $e;
                    $children_elements[ $e->$parent_field ][] = $e;

             * when none of the elements is top level
             * assume the first one must be root of the sub elements
            if ( empty($top_level_elements) ) {

                $first = array_slice( $elements, 0, 1 );
                $root = $first[0];

                $top_level_elements = array();
                $children_elements  = array();
                foreach ( $elements as $e) {
                    if ( $root->$parent_field == $e->$parent_field )
                        $top_level_elements[] = $e;
                        $children_elements[ $e->$parent_field ][] = $e;

            $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );  //added by continent7
            foreach ( $top_level_elements as $e ){  //changed by continent7
                // descend only on current tree
                $descend_test = array_intersect( $current_element_markers, $e->classes );
                if ( !empty( $descend_test ) ) 
                    $this->display_element( $e, $children_elements, 0, 0, $args, $output );

             * if we are displaying all levels, and remaining children_elements is not empty,
             * then we got orphans, which should be displayed regardless
             /* removed by continent7
            if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
                $empty_array = array();
                foreach ( $children_elements as $orphans )
                    foreach( $orphans as $op )
                        $this->display_element( $op, $empty_array, 1, 0, $args, $output );

/*added by alpguneysel  */
                $pos = strpos($output, '<a');
            $pos2 = strpos($output, 'a>');
            $topper= substr($output, 0, $pos).substr($output, $pos2+2);
            $pos3 = strpos($topper, '>');
            $lasst=substr($topper, $pos3+1);
            $submenu= substr($lasst, 0, -6);

        return $submenu;
share|improve this question
xLRDxREVENGEx, I noticed you edited my code above to a version which now produces a 500 error. Can you be sure to post any attempts as an answer so people will have the original working version to go off of, when trying to allow sub items to show? – cchiera May 24 '11 at 17:12
xLRDxREVENGEx, To note, the 500 error came from your line: if ($max_depth db_fields['id']; – cchiera May 24 '11 at 17:25
actually the weird error was a function of the code being wrapped in <pre> tags. To post blocks of code here, just indent everything four or more spaces, or use the code button in the editor. Other wise everything in between < and > gets treated as a tag and stripped out. – goldenapples May 24 '11 at 17:34
@goldeenapples, The original version I posted provides no errors and works however it does not show the sub sub menu items. xLRDs code provided produced a 500 error. Your revised produces the same results as my initial copy where it works but does not show the sub sub items (which this post is for). Or do you solve it and I'm grabbing a wrong revision? Thanks! – cchiera May 24 '11 at 18:42
up vote 0 down vote accepted

After no solution from the community :-/ and days of reviewing it over and over I determined I simply had to change a 2 to a 0 for unlimited depth, and now it works perfectly!

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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