How to use redirect
Created: Last updated:
Redirecting is basically a simple procedure within HTML or rather HTTP. Forcing a redirect, refresh and reload of a page from within a script like PHP is also pretty simple and the same is true for the Zend Framework. There is a slight little problem: "You need to know how!"
If you need some fundamentals on how a redirect works (and I think you should) then you may want to read first How does a redirect work and then come back here.
This page dives directly into how to redirect in PHP plus the Zend Framework.
Fundamentals for redirecting
First some fundamentals to make sure we are talking about the same thing, i.e. we have an understanding what a redirect is.
A normal response
Lets look at the web server how a "normal" transactions works.
A user-agent (browser) sends a request for a document with the URI as domain/path/documentname. The server in return sends a response. Keep these two things in mind, they always work together: request→response. When we redirect we send a response telling the requester to send a different request! That is the whole secret of redirecting in a nutshell, but we are not there yet.
The response contains a status code which is 200 OK if everything is normal. If there are problems or special situations like our redirects the response has a different number. Watch out: The status codes are part of the HTTP specification; not HTML!
Other server responses
Before we dive into redirects lets look at two other common types of response by a web server. These are status code 404 and 500 which are not redirects but nevertheless do not return the expected web page.
Although we sometimes see the code in the browser, a user agent itself should and does not care about it. A user agent simply displays the HTML document page submitted by the server along with the status code. You could send any page with an error code and a user would not know.
Page not found: If the server cannot locate the requested path or document its response is 404. Together with the response a web page is returned, which is either the default page specified with the server for this type of error or a specially designed page and configured into the server.
Internal Server Error: If the web server has to send the request to a script engine like PHP (CGI) and does not get back a proper response (or in time) it will return a 500 error. Like before a web page is returned as well.
There are other types of error plus we can add real redirect options into the web server. For an Apache web server this is usually within the .htaccess file as a redirect or a rewrite [R]. We will not look at the server configuration in more detail because this is about PHP and Zend but here is the link to the mod_rewrite documentation for Apache 2.2.
Why or when do we need a redirect? Like we have seen before if a document is not found our web server should respond with a 404 status code.
If the user just typed some silly request this may be okay but it is not very smart (or polite) when we know we have moved or renamed the document. In all these cases we should catch the request and redirect to the new location or new document name.
A reason to reload or refresh
You have a page and for some reason you like to refresh or reload the page for the user. Most prominent is the POST/GET pattern. A user submits a form with a POST request and there is this little problem when a user hits the refresh (F5) button. The browser would resubmit the form and data which is not only annoying for your user but may also introduce some problem with your application. To avoid all this you respond with a redirect. This not only actively refreshes or reloads the page for the user it forces the browser in a GET request state, i.e. if the user hits F5 the page just reloads or refreshes but no form data is resubmitted.
Before we talk about PHP and Zend Framework redirect here is something else you may have seen in other places. Especially when a page has been moved, i.e. can be found with another URL, aka link.
In such cases a common method is having a page with a note about the move and a link to the new location so the user can update any bookmark or link on a web page. Within the HTML document we can place a "refresh" meta tag. The refresh tag will cause a reload for the page after a defined period to a specified new location.
Note: This is not a real redirect and a thing handled by browsers once the whole page has been loaded. It is also not a part of HTTP and actually not a standard defined in HTML either. PHP is not much involved either because you'll just need it to probably echo some HTML code. In terms of informing the user this might be a good and valid option but it has some limitations as explained in this document at W3C.
If you don't want to use the meta refresh tag you have to send a status code and a new location forcing HTTP to reload the page, i.e. send a new request based on this information. Because HTTP is part of the network protocol suite (IP stack) a browser is not aware of this redirect to some degree.
Well, that is actually not true because a browsers under hood handles HTTP. Lets just say between a user and a browser the user is not aware of this redirect.
Back to working on the redirect we also need a way to communicate with HTTP and that's were we need PHP.
Redirect with PHP
So, how do we work with HTTP in PHP? Working with HTTP means the header information. Because we only have to make changes to the header it is very simple. We can set header information with the aptly named header() function in PHP.
The only tricky thing is to add the information before you have any sort of output, i.e. echo, print or any other form of data. Note that a file include containing spaces outside your <?php ?> marks might be enough to throw the function off and trigger an error.
Once you have set all information with the header function you can or actually have to terminate your script by calling exit() or die(). Whatever else you send or do will have no effect after you have set the redirect header information.
The information in the header, as the response to the requester, causes HTTP to request the new document. Again, a browser (I mean the user) is usually not aware what just happened. They get note of the new URI when they see the updated address field, though. Other than that this process is very transparent.
Can I see the header information
It depends what you are looking for.
You can however query your own page and act as a client, if you must. You can call your own link with get_headers() which will give a client's point of view, sort of. You can use this in a test application but you should not use this in the same procedure sending your page.
On the client-side: In theory, a browser is able to query HTTP for the header information but there are two problems. First you cannot see the reload only the new page and second I have looked at all major browser but have found none giving you header information by default. Only with some developer extensions you can get and see the response header.
Google's Chrome browser has a Web Developer extension by chrispederick.com. Firefox has this web developer add-on and guess what; also by chrispederick.com. In both tools you go to Information and all the way at the end or bottom you will see View Response Headers. As far as I know these are about the only two browsers and location where you can find out what the response status code is.
If you have your web site in Google's Webmaster Tools you can use "Fetch as Googlebot" in Diagnostics. Once you get the success link you can click that and you will see the whole page including header information.
The last extreme solution to figure out the status code is a network sniffer or get your own web page with telnet.
Redirect with the Zend Framework
First of all, it really raises the question if you want to use the Framework's methods because they are not going to do anything more than what we have above. Although, since we have the methods and like to stay consistent in some way we should use it.
Before we start also a special remark about redirects in the Zend Framework. We are talking here about HTTP redirects. Zend Framework also uses internal redirects, i.e. you can redirect to modules or other controllers and actions. This is not about internal redirects!
First thing to know about redirect in Zend Framework is that it is a Action Helper. If you are not familiar with Action Helpers think of it as a plugin. Action Helpers are plugins for action methods inside a controller though and because of this it means we have to work inside a controller.
If you use a MVC pattern and want to redirect from within a model class—and work properly—you can (should) not do this directly from the model. You should either return an appropriate response from your model or provide an access to a property in your model indicating that a redirect is necessary. Your controller then initiates the redirect.
There is a redirect() method inside the controller class but I am not very fond of it. Because I already extend Zend_Controller for other thing I included a getter method for the Action helper "Redirector" plus I can set the redirect status code as an argument. Most of the time you need and do the same things with a redirect so it might be worth to add a special method in your own controller.
On we go, first we get the helper which is named Redirector. Here is how you fetch the redirector:
- // $this is your zend controller class
- $redirector = $this->_helper->getHelper('Redirector');
Now that you have the object you can work with it, like calling the methods to add the data for the redirect. As you see the methods can be chained, i.e. they return $this. For readability I would not chain everything but this is up to you.
- $newPath = 'http://www.newdomain.com/newpath/newdocument.html';
And we are basically done but what is happening here?
First we set the status code. Important fact here, the code has to be an integer and not a string (I learned it the hard way). Of course, the code has to be one of the valid HTTP status codes and is not a code only known to or defined somewhere in Zend Framework.
Second, set an absolute URI to make sure it is a valid path and not inadvertently a relative path breaking the new request.
Last, the redirector by default and the final call to method gotoUrl() will terminate the framework, i.e. it will call the exit() function. The call to exit as a default can be postponed for whatever reason by calling setExit(false) earlier. Once you are ready to finally leave you can call redirectAndExit() which will finally terminate the framework and trigger the redirect.
Redirects and error codes
Do not use the redirects for the error codes for two reasons. First you want to return a document telling what went wrong. Second the Redirector is supposed to terminate with exit and therefore is not returning this document. Whatever you would write is thrown away, lost.
You can set an error status code with Zend Framework like this:
- $error_404 = 'HTTP/1.1 404 Not Found';
Note again that all this goes inside your controller.