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');
?>

Redirect an entire Drupal site – .htaccess

I’ve migrated several Drupal sites to new servers lately and since some of those sites were in development they didn’t have a proper cName. So I’ve been using a .htaccess redirect to channel all traffic from the old site to the new ones.
Here’s an example of the new .htaccess file I placed in the /hr_diac directory on my old server:
##Redirect everything that pointed to /hr_diac to http://access-guide.hrstg.uoregon.edu/$1

RewriteEngine on
RewriteCond %{REQUEST_URI} /hr_diac [nc]
RewriteRule ^(.*)$ http://access-guide.hrstg.uoregon.edu/$1 [r=301,nc]

To clarify; I completely replaced the drupal .htaccess file with this file.
It’s pretty simple but it works.

Handle sites/default/files redirect in Drupal 6 with Custom Errors module

When I’ve migrated sites into Aegir recently, I find that the users have many links in the content hard-coded to files in the default directory.
While it is possible to use the Scanner search & replace module to ferret those out. It’s not always thorough enough. For example, it doesn’t search and replace menu link urls, or content in blocks, views, headers, footers or custom fields. You can specify custom fields and locations to search but that’s another bag of worms that fraught with issues.
So I wanted to find a simple way to catch any hard coded links that I missed.
Enter the Custom Error module.

I’ve been using it to provide a populated search form on the 404 ‘Not found’ page as well as a site map but I also have a few custom redirects in there so adding an option for sites/default/files was simple.

Here’s the code: (more…)