University of Oregon

PHP redirects if the headers have already been sent.

I ran in to a situation with some inherited code today.
The developer wanted to redirect users to a course listing page if they landed on a date/time listing that couldn’t be found.
See this code below; they check for an empty $dateTime var and create a log message before attempting to redirect the user.

if (empty($dateTime)) {
  $logger->err('DateTime with the id of '.$_REQUEST['dt_id'].' cannot be located.');
  Header( 'Location: course_list.php'); // Go back to the course list
  exit;
}

Unfortunately the headers had already been sent to the browser and the Header function call was ignored and the user only saw a partially loaded web page with no body content.

In the past I had implemented a fall-back with a meta and js redirect but I thought that could be improved upon.
Stack Overflow had some nice responses to a previous question and one of them included Redirect function that checked if the headers were already sent: headers_sent().
I liked that. So I added my fall back to that function.

Next I swapped that Header function call with the Redirect function call:

if (empty($dateTime)) {
  $logger->err('DateTime with the id of '.$_REQUEST['dt_id'].' cannot be located.');
  Redirect('course_list.php'); // Go back to the course list
}

Problem solved.

Here’s the function (note: it’s wrapped in a function_exists() call to make sure I don’t declare this twice at any point):

<?php
if(!function_exists('Redirect')){
  function Redirect($url, $code = 302) //from http://stackoverflow.com/questions/768431/how-to-make-a-redirect-in-php
  {
    #echo 'redirecting';
    if (strncmp('cli', PHP_SAPI, 3) !== 0)
    {
      #echo 'cli';
      if (headers_sent() !== true)
      {
        if (strlen(session_id()) > 0) // if using sessions
        {
            session_regenerate_id(true); // avoids session fixation attacks
            session_write_close(); // avoids having sessions lock other requests
        }
        if (strncmp('cgi', PHP_SAPI, 3) === 0)
        {
            header(sprintf('Status: %03u', $code), true, $code);
        }
      header('Location: ' . $url, true, (preg_match('~^30[1237]$~', $code) > 0) ? $code : 302);
      } else { //headers have already been sent. Use Meta refresh with js location.href fallback
      ?>
        <em>This page has moved.</em><br />
        If you are not redirected automatically please follow this link: <a href=\"<?php echo $url; ?>"><?php echo $url; ?></a>.
        <meta http-equiv="Refresh" content="1;
        URL=<?php echo $url; ?>">
        <script language=javascript>
        setTimeout("location.href='<?php echo $url; ?>'",1);
        </script>
        <?php
      }//end if headers_sent

      exit();
    }
  }
}
#usage:
#Redirect('course_list.php');
?>

Drupal 6 adding styles from a themed view variable output

Here’s an overview of what I did to add a style to the doc head from within a themed view for a specific variables output. I’ll likely post more on that scenario later.
I don’t intend to raise a discussion about whether or not we should be adding one-off styles in a view vs. appending a master stylesheet, but the facts remain that I did it, it came in pretty handy for testing and it requires some configuration worthy of saving for later (so I don’t have to try and figure it out again!). The best part was being able to keep the custom styles in the same page where I was working on theming the view.
To make things a little more complicated I only wanted to append one rule to the head of the page and not adding a style to each row (which could be done with jquery).
So here’s what I did: (more…)