0

I have a simple template rendering system that includes a header, template and footer PHP file. The header has a single PHP function call to render a navigation bar. The template has a function call that sets a header('location ...'); and the footer is just basic HTML.

When I view the page, I get a 'headers already sent' error, specifying the line in the header that makes the call to echo out the navigation bar. If I modify the code to remove the child elements in the navigation, I don't get the 'headers already sent' error. The child elements are nothing more than array items. If I replace them with dummy text, then the page redirects correctly.

I imagine it's something very simple, but it has me stumped!

header.php (the int passed in specifies the depth to scan)

<ul class="nav navbar-nav"><?php echo getNavigation(1); ?></ul>

template.php

// Run from start
default:
        $_SESSION['updateStart'] = microtime(true);
        $_SESSION['updateErrors'] = array();
        $_SESSION['updateLog'] = array();
        header('location: /update-products?action=getDataFeeds');
        exit();
break;

getNavigation function:

function getNavigation($depth) {
    global $path, $misc;

    $items = $misc->getNavigation(1,(int)$depth,true);
    $nav = "";

    if($items) {
        foreach($items as $item) {
            $class = ($item['ob_alias']==("/".$path[0])?' class="active"':'');
            $nav .= '<li'.$class.'>';

            if(isset($item['children'])) {
                $nav .= '<a href="#" class="dropdown-toggle" data-toggle="dropdown">'.$item['ob_label'].' <span class="caret"></span></a>';
                $nav .= '<ul class="dropdown-menu" role="menu">';
                foreach($item['children'] as $child) {
                    $class = ((isset($path[1]) && $child['ob_alias']==("/".$path[1]))?' class="active"':'');
                    $nav .= '<li'.$class.'><a href="'.$child['ob_alias'].'">'.$child['ob_label'].'</a></li>';
                }
                $nav .= '</ul>';
            } else {
                $nav .= '<a href="'.$item['ob_alias'].'">'.$item['ob_label'].'</a>';
            }
            $nav .= '</li>';
        }
    }       
    return $nav;
}

I've tried to walk through my code and all that I can seem to do to toggle the error Vs. having the page run as expected is to replace this line in my getNavigation() call:

$nav .= '<li'.$class.'><a href="'.$child['ob_alias'].'">'.$child['ob_label'].'</a></li>';

with

$nav .= '<li>Some dummy text</li>';

Then it's fine. I can't see why including the two array item strings would break the 'headers'.

Any help, or pointers for things to test would be most welcome.

Alexander Holsgrove
  • 1,795
  • 3
  • 25
  • 54

1 Answers1

1

Seeing the order you are loading all of this may help but based on what you have, I would suspect you are rendering something (like the nav) before setting the headers in template.php. You may want to reference this answer as well as post more specific code that show in what order the template files are being loaded.

Functions that send/modify HTTP headers must be invoked before any output is made. 

Otherwise the call fails.

Output can be:

Unintentional:

   Whitespace before <?php or after ?>
   UTF-8 Byte Order Mark
   Previous error messages or notices

Intentional:

   print, echo and other functions producing output (like var_dump)
   Raw <html> areas before <?php code.
Community
  • 1
  • 1
Ross Edman
  • 798
  • 5
  • 14
  • Thanks for your answer - I did have a search around first and found that post. I have a render function that does an 'include' for the the header, file, then does a file_get_contents & echo on the template, and finally another include on the footer. It's strange because I on;y have to comment out the child nav elements for it to work. I'd understand if any output from the header caused the error - but it's only those $child items. – Alexander Holsgrove Oct 20 '14 at 08:39