I'm having a small problem with a variable in one of my PHP scripts. The variable is $isSubMenu. It gets set using a function that runs recursively called createNavigationMenu. However, even though I have set it, the interpreter keeps telling me that the variable is undefined. I really don't know what's going on because I've checked several times and I'm sure that it IS defined.

Does this have anything to do with the fact that the function is being called recursively?

Any input would be greatly appreciated.

Thanks for your help in advance.

Dodzi

P.S. How do you turn on language specific formatting now that they've changed the tags?

<?php
private function convertToListItem( $heading, $path = "", $isHeading = false, $isSubMenu )
{
    //safety check
    if( is_null($heading) )
    {
        return;
    }

    //initializations
    $listItem = $heading;
    $itemClass = $isHeading ? "nav_heading" : "nav_list_item";

    //format heading
    $listItem = $this->underscoresToSpaces( basename( $listItem, ".php" ) );

    if( !empty($path) )
    {
        //add hyperlink
        $subMenuClass = $isSubMenu ? "nav_sub_menu" : "";
        $path = $this->getRelativePath( $this->currentFilePath, $path );
        $listItem = "<a href='$path' class='$subMenuClass'>$listItem</a>";
        //first new item only
        $isSubMenu = false;
    }

    $listItem = "<li class='$itemClass'>$listItem";

    if( !$isHeading )
    {
        $listItem .= "</li>";
    }

    return $listItem;
}

private function createNavigationMenu( $menuTree, $isSubMenu = false )
{
    $treeSize = count( $menuTree );
    $menuAsString = "";

    for( $i = 0; $i < $treeSize; $i++ ) 
    {
        $heading = key( $menuTree );
        $path = current( $menuTree );

        //menu heading
        if ( strpos( $heading, SITE_NAVIGATION_SUB_MENU_SUFFIX ) === false )
        {
            $menuAsString = sprintf(
                "%s%s",
                $menuAsString,
                $this->convertToListItem( $heading, null, true, $isSubMenu )
            );
        }
        //is new sub menu
        if( is_array( $path ) )
        {
            $menuAsString .= $this->createNavigationMenu( $path, true );
        }
        else //create menu
        {
            $menuAsString = sprintf(
                "%s%s",
                $menuAsString,
                $this->createListForHeading( $path )
            );
        }

        $menuAsString .= "</li>" . PHP_EOL;

        next( $menuTree );
    }

    //wrap in nav tags
    $menuAsString = sprintf(
        "<ul>%s</ul>" . PHP_EOL,
        $menuAsString
    );

    return $menuAsString;
}

Recommended Answers

All 17 Replies

the interpreter keeps telling me that the variable is undefined

What line is it referring to ?

pritaeas,

Thanks for the reply. It was referring to a different line in the code, but I have just fixed that error.

I am still; however, having trouble with the variable disappearing on me...

It disappears on line 12 of the code that I've posted. I've echoed the variable throughout the entire code and it actually seems to disappear after the first recursive call.

Any ideas as to what could be causing this?

What do you mean by disappear? $isHeading should always be true, it is never given a new value.

When I run my script $isSubMenu has already been set as false by defalt; however, anytime I echo the variable it's empty....

Do not use echo $isSubMenu; but use echo $isSubMenu ? 'true' : 'false'; instead.

When I run my script $isSubMenu has already been set as false by defalt; however, anytime I echo the variable it's empty....

I don't understand your problem but I'll try to help anyway. You didn't define the variable, you are using it from the beginning without any declaration. I think you should write, before the function, something like

$isSubMenu=false;
//rest of the code.

You didn't define the variable

It is defined as a function parameter. The value on the first call is false (by default).

On line 37 of the code that I posted, $isSubMenu is set to false by default. On line 59 of the posted code I call the function on line 37 and set it to true. It's a recursive call. On line 53 I call the function on line 2 and pass it the variable $isSubMenu. $isSubMenu should now be set to true. $isSubMenu is then used on line 20 to set a property. If $isSubMenu is true the property should be "nav_sub_menu". If $isSubMenu is false, the property should be set to a blank string.

The property is always set to a blank string meaning that $isSubMenu must be false; however, when I go to echo / print / log $isSubMenu on any line (strictly for debugging purposes) it is neither true nor false, but empty / undefined.

I have been trying to debug this for a while now, but I'm having trouble understanding where or why it gets set to empty. I have narrowed it down to line 16. Once it enters the if statement, even it was true on the previous line, it gets reset to false JUST after it enters the if statement.

Where are you calling your function createNavigationMenu in the first instance and what paremters are you sending through as $isSubMenu will only be set to false if you are not passing through a setting for the function parameter as this may be where your problem is coming from?

I'm calling in in the constructor of a class as follows.

public function __construct()
{
    $this->menuAsString = $this->createNavigationMenu( $this->scanDirectoryForFolders(), false );
}

The logic is the first item on the first line of of a menu won't be a submenu, so that is set to false. All other calls to createNavigationMenu are done by createNavigationMenu itself.

I'm reading through my code right now to see if it's not a completely different problem that's causing this. Will be back with what I find.

Back. I rewrote the code so that it's a little bit easier to follow and I think I know where the problem is, but I don't know why.... I'll post the new code.

The problem is the variable $isSubMenu is always false, even though it's being set to true when called.

private function convertToListItem( $heading, $path = "", $isHeading = false, $isSubMenu )
{
    //safety check
    if( is_null($heading) )
    {
        return;
    }

    //initializations
    $listItem = $heading;
    $itemClass = ( $isHeading ? "nav_heading" : "nav_list_item" );
    $subMenuClass = ( $isSubMenu ? "nav_sub_menu" : "here" );

    if ( $isSubMenu )
    {
        $subMenuClass = "nav_sub_menu";
    }

    //format heading
    $listItem = $this->underscoresToSpaces( basename( $listItem, ".php" ) );

    if( empty($path) == false )
    {
        //add hyperlink
        $path = $this->getRelativePath( $this->currentFilePath, $path );
        $listItem = "<a href='$path' class='$subMenuClass'>$listItem</a>";
    }

    $listItem = "<li class='$itemClass'>$listItem";

    if( !$isHeading )
    {
        $listItem .= "</li>";
    }

    return $listItem;
}

private function createNavigationMenu( $menuTree, $isSubMenu = false )
{
    //initializations
    $menuAsString = "";

    foreach( $menuTree as $heading => $path ) 
    {
        //menu heading
        if ( strpos( $heading, SITE_NAVIGATION_SUB_MENU_SUFFIX ) === false )
        {
            $menuAsString .= $this->convertToListItem( $heading, null, true, $isSubMenu );
            //this lets you see the menu trees if you want them
            //$menuAsString .= $this->convertToListItem( $heading, $path );

        }
        //is new sub menu
        if( is_array( $path ) )
        {
            $menuAsString .= $this->createNavigationMenu( $path, true );
        }
        else //create menu
        {
            $menuAsString .= $this->createListForHeading( $path ); 
        }

        $menuAsString .= "</li>" . PHP_EOL;
    }

    //wrap in nav tags
    $menuAsString = "<ul>$menuAsString</ul>" . PHP_EOL; 

    return $menuAsString;
}

I believe that what's happening here is one of those once in a while, how does this happen bugs. That's why I posted it here.

I'll write down a few examples to prove it.

1) Verifying the value of the variable.
I put the following code between lines 11 and 12 of most recent code posted.

if ( $isSubMenu )
{
    echo "<p>WTF?!?!</p>";
}

The letters "WTF" get printed to the screen meaning the variable is true in the function convertToListItem(). However, the subsequent line with the true/false evaluation still returns false. If it was true the line before why did it change to false?

2) Forcing a true value.
I added the following code to the test above.

if ( $isSubMenu )
{
    echo "<p>WTF?!?!</p>";
    $isSubMenu = true;
}

The letters "WTF" get printed to the screen proving that the last test still works, and I have set the value of $isSubMenu to true again by force. The following line still always evaluates to false.......

3) Using a new variable for evaluation.
This is another permutation of the two tests above.

if ( $isSubMenu )
{
    echo "<p>WTF?!?!</p>";
    $randomBool = true;
}

The letters "WTF" print to the screen, but following line still evaluates to false.

I've kind of run out of ways to debug this because I've been able to prove that the value coming into the function is true, but when it's use to set a dfferent value it always evaluates to false.

Any suggestions for different ways or things I can do to debug this would be greatly appreciated.

I am really not sure why it is not working for you, but as you are passing a value to the funtion from your constructor and also when re-calling the function from within itself, have you tried removing the default false from the function parametetrs (as you will always be getting a value so not necessarily required but I know is good practice) and seeing if things work as they should:

private function createNavigationMenu( $menuTree, $isSubMenu )

Thanks. I'll give that a try and see what happens.

What version of PHP are you using? If you are on an old version, your variable could be passed by value, instead of by reference.

Looks pretty insane, only thing i can think of:

private function convertToListItem( $heading, $path = "", $isHeading = false, $isSubMenu )

I may not be thinking of php but i thought optional parameters always had to be last in the function declaration and use var_dump(); to see whats actually in them

private function convertToListItem( $heading, $isSubMenu, $path = "", $isHeading = false){
var_dump($heading);
var_dump($isSubMenu);
var_dump($path);
var_dump($isHeading);

Hey guys,

I want to thank you for your help. I FINALLY found what the problem was.... Once I say it we're all going to be like OH YEAH....

On a completely different script, that happened to call this one I was using a heredoc...

My original code looked like this.

$addExtraHtml = <<<HTML
    stuff stuff and stuff
<<<HTML;
    $navMenu = new NavigationMenu();

I should have written.

$addExtraHtml = <<<HTML
    stuff stuff and stuff
<<<HTML;

    $navMenu = new NavigationMenu();

That one line of white space made ALL the difference.

Thanks so much for you help though.

Sincerely,

Dodzi

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.