Thursday, May 21, 2009

XMLHttp POST Requests in php ajax

Now that you've seen how XMLHttp can simplify GET requests, it's time to take a look at POST requests. First, you need to make the same changes to SaveCustomer.php as you did for GetCustomerInfo.php, which means you need to remove extraneous HTML and JavaScript, add the content type information, and output the text:

This now represents the entirety of SaveCustomer.php. Note that the header() function is called to set the content type, and echo is used to output $sStatus. In the main page, the simple form that was set up to allow entry of new customer info is the following:

Enter customer information to be saved:

Customer Name:
Address:
City:
State:
Zip Code:
Phone:
E-mail:

You'll note that the onsubmit event handler has now changed to call the function sendRequest() (although the event handler still returns false to prevent actual form submission). This method first assembles the data for the POST request and then creates the XMLHttp object to send it. The data must be sent in the format as a query string:
name1=value1&name2=value2&name3=value3
Both the name and value of each parameter must be URL-encoded in order to avoid data loss during transmission. JavaScript provides a built-in function called encodeURIComponent() that can be used to perform this encoding. To create this string, you'll need to iterate over the form fields, extracting and encoding the name and value. The getRequestBody() function handles this:
function getRequestBody(oForm) { var aParams = new Array(); for (var i=0 ; i < sparam =" encodeURIComponent(oForm.elements[i].name);">
This function assumes that you will supply a reference to the form as an argument. An array (aParams) is created to store each individual name-value pair. Then, the elements of the form are iterated over, building up a string and storing it in sParam, which is then added to the array. Doing this prevents multiple string concatenation, which can lead to slower code execution in some browsers. The last step is to call join() on the array, passing in the ampersand character. This effectively combines all the name-value pairs with ampersands, creating a single string in the correct format.
The sendRequest() function calls getRequestBody() and sets up the request:
function sendRequest() { var oForm = document.forms[0]; var sBody = getRequestBody(oForm); var oXmlHttp = zXmlHttp.createRequest(); oXmlHttp.open("post", oForm.action, true); oXmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); oXmlHttp.onreadystatechange = function () { if (oXmlHttp.readyState == 4) { if (oXmlHttp.status == 200) { saveResult(oXmlHttp.responseText); } else { saveResult("An error occurred: "+ oXmlHttp.statusText); } } }; oXmlHttp.send(sBody); }
As with previous examples, the first step in this function is to get a reference to the form and store it in a variable (oForm). Then, the request body is generated and stored in sBody. Next comes the creation and setup of the XMLHttp object. Note that the first argument of open() is now post instead of get, and the second is set to oForm.action (once again, so this script can be used on multiple pages). You'll also notice that a request header is being set. When a form is posted from the browser to a server, it sets the content type of the request as application/x-www-form-urlencoded. Most server-side languages look for this encoding in order to parse the incoming POST data properly, so it is very important for it to be set. The onreadystatechange event handler is very similar to that of the GET example; the only change is the call to saveResult() instead of displayCustomerInfo(). The last line is very important, as the sBody string is passed to send() so that it will become part of the request body. This effectively mimics what the browser does, so all server-side logic should work as expected.

Creating an XMLHttp Object in PHP AJAX

The first step to using an XMLHttp object is, obviously, to create one. Because Microsoft's implementation is an ActiveX control, you must use the proprietary ActiveXObject class in JavaScript, passing in the XMLHttp control's signature:
var oXmlHttp = new ActiveXObject("Microsoft.XMLHttp");
This line creates the first version of the XMLHttp object (the one shipped with IE 5.0). The problem is that there have been several new versions released with each subsequent release of the MSXML library. Each release brings with it better stability and speed, so you want to make sure you are always using the most recent version available on the user's machine. The signatures are:
1 Microsoft.XMLHttp 2 MSXML2.XMLHttp 3 MSXML2.XMLHttp.3.0 4 MSXML2.XMLHttp.4.0 5 MSXML2.XMLHttp.5.0
Unfortunately, the only way to determine the best version to use is to try to create each one. Because this is an ActiveX control, any failure to create an object will throw an error, which means that you must enclose each attempt within a try...catch block. The end result is a function such as this:
function createXMLHttp() { var aVersions = [ "MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp","Microsoft.XMLHttp" ]; for (var i = 0; i < oxmlhttp =" new">
The createXMLHttp() function stores an array of XMLHttp signatures, with the most recent one first. It iterates through this array and tries to create an XMLHttp object with each signature. If the creation fails, the catch statement prevents a JavaScript error from stopping execution; then the next signature is attempted. When an object is created, it is returned. If the function completes without creating an XMLHttp object, an error is thrown indicating that the creation failed. Fortunately, creating an XMLHttp object is much easier in other browsers. Mozilla Firefox, Safari, and Opera all use the same code:
var oXmlHttp = new XMLHttpRequest();
Naturally, it helps to have a cross-browser way of creating XMLHttp objects. You can create such a function by altering the createXMLHttp() function defined previously: function createXMLHttp() { if (typeof XMLHttpRequest != "undefined") { return new XMLHttpRequest(); } else if (window.ActiveXObject) { var aVersions = [ "MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp","Microsoft.XMLHttp" ]; for (var i = 0; i < oxmlhttp =" new">
The other option for creating cross-browser XMLHttp objects is to use a library that already has cross-browser code written. The zXml library, written by two of your authors, is one such library and is available for download at www.nczonline.net/downloads/. This library defines a single function for the creation of XMLHttp objects: var oXmlHttp = zXmlHttp.createRequest(); The createRequest() function, and the zXml library itself, will be used throughout this book to aid in cross-browser handling of Ajax technologies. Using XMLHttp After you have created an XMLHttp object, you are ready to start making HTTP requests from JavaScript. The first step is to call the open() method, which initializes the object. This method accepts the following three arguments:
Request Type: A string indicating the request type to be made — typically, GET or POST (these are the only ones currently supported by all browsers). URL: A string indicating the URL to send the request to. Async: A Boolean value indicating whether the request should be made asynchronously.
The last argument, async, is very important because it controls how JavaScript executes the request. When set to true, the request is sent asynchronously, and JavaScript code execution continues without waiting for the response; you must use an event handler to watch for the response to the request. If async is set to false, the request is sent synchronously, and JavaScript waits for a response from the server before continuing code execution. That means if the response takes a long time, the user cannot interact with the browser until the response has completed. For this reason, best practices around the development of Ajax applications favor the use of asynchronous requests for routine data retrieval, with synchronous requests reserved for short messages sent to and from the server. To make an asynchronous GET request to info.txt, you would start by doing this:
var oXmlHttp = zXmlHttp.createRequest(); oXmlHttp.open("get", "info.txt", true);
Note that the case of the first argument, the request type, is irrelevant even though technically request types are defined as all uppercase. Next, you need to define an onreadystatechange event handler. The XMLHttp object has a property called readyState that changes as the request goes through and the response is received. There are five possible values for readyState:
0 (Uninitialized): The object has been created but the open() method hasn't been called. 1 (Loading): The open() method has been called but the request hasn't been sent. 2 (Loaded): The request has been sent. 3 (Interactive). A partial response has been received. 4 (Complete): All data has been received and the connection has been closed.
Every time the readyState property changes from one value to another, the readystatechange event fires and the onreadystatechange event handler is called. Because of differences in browser implementations, the only reliable readyState values for cross-browser development are 0, 1, and 4. In most cases, however, you will check only for 4 to see when the request has returned: var oXmlHttp = zXmlHttp.createRequest(); oXmlHttp.open("get", "info.txt", true); oXmlHttp.onreadystatechange = function () { if (oXmlHttp.readyState == 4) { alert("Got response."); } }; The last step is to call the send() method, which actually sends the request. This method accepts a single argument, which is a string for the request body. If the request doesn't require a body (remember, a GET request doesn't), you must pass in null:
var oXmlHttp = zXmlHttp.createRequest(); oXmlHttp.open("get", "info.txt", true); oXmlHttp.onreadystatechange = function () { if (oXmlHttp.readyState == 4) { alert("Got response."); } }; oXmlHttp.send(null); That's it! The request has been sent and when the response is received, an alert will be displayed. But just showing a message that the request has been received isn't very useful. The true power of XMLHttp is that you have access to the returned data, the response status, and the response headers.
To retrieve the data returned from the request, you can use the responseText or responseXML properties. The responseText property returns a string containing the response body, whereas the responseXML property is an XML document object used only if the data returned has a content type of text/xml. (XML documents are discussed in Chapter 4.) So, to get the text contained in info.txt, the call would be as follows:
var sData = oXmlHttp.responseText;
Note that this will return the text in info.txt only if the file was found and no errors occurred. If, for example, info.txt didn't exist, then the responseText would contain the server's 404 message. Fortunately, there is a way to determine if any errors occurred. The status property contains the HTTP status code sent in the response, and statusText contains the text description of the status (such as "OK" or "Not Found"). Using these two properties, you can make sure the data you've received is actually the data you want or tell the user why the data wasn't retrieved: if (oXmlHttp.status == 200) { alert("Data returned is: "+ oXmlHttp.responseText; } else { alert("An error occurred: "+ oXmlHttp.statusText; } Generally, you should always ensure that the status of a response is 200, indicating that the request was completely successful. The readyState property is set to 4 even if a server error occurred, so just checking that is not enough. In this example, the responseText property is shown only if the status is 200; otherwise, the error message is displayed. Important The statusText property isn't implemented in Opera and sometimes returns an inaccurate description in other browsers. You should never rely on statusText alone to determine if an error occurred. As mentioned previously, it's also possible to access the response headers. You can retrieve a specific header value using the getResponseHeader() method and passing in the name of the header that you want to retrieve. One of the most useful response headers is Content-Type, which tells you the type of data being sent:
var sContentType = oXmlHttp.getResponseHeader("Content-Type"); if (sContentType == "text/xml") { alert("XML content received."); } else if (sContentType == "text/plain") { alert("Plain text content received."); } else { alert("Unexpected content received."); } This code snippet checks the content type of the response and displays an alert indicating the type of data returned. Typically, you will receive only XML data (content type of text/xml) or plain text (content type of text/plain) from the server, because these content types are the easiest to work with using JavaScript. If you'd prefer to see all headers returned from the server, you can use the getAllResponseHeaders() method, which simply returns a string containing all of the headers. Each heading in the string is separated by either a new line character (\n in JavaScript) or a combination of the carriage return and new line (\r\n in JavaScript), so you can deal with individual headers as follows:
var sHeaders = oXmlHttp.getAllResponseHeaders(); var aHeaders = sHeaders.split(/\r?\n/); for (var i=0; i <>
It's also possible to set headers on the request before it's sent out. You may want to indicate the content type of data that you'll be sending, or you may just want to send along some extra data that the server may need to deal with the request. To do so, use the setRequestHeader() method before calling send():
var oXmlHttp = zXmlHttp.createRequest(); oXmlHttp.open("get", "info.txt", true); oXmlHttp.onreadystatechange = function () { if (oXmlHttp.readyState == 4) { alert("Got response."); } }; oXmlHttp.setRequestHeader("myheader", "myvalue"); oXmlHttp.send(null); In this code, a header named myheader is added to the request before it's sent out. The header will be added to the default headers as myheader: myvalue. Up to this point, you've been dealing with asynchronous requests, which are preferable in most situations. Sending synchronous requests means that you don't need to assign theonreadystatechange event handler because the response will have been received by the time the send() method returns. This makes it possible to do something like this: var oXmlHttp = zXmlHttp.createRequest(); oXmlHttp.open("get", "info.txt", false); oXmlHttp.send(null); if (oXmlHttp.status == 200) { alert("Data returned is: "+ oXmlHttp.responseText; } else { alert("An error occurred: "+ oXmlHttp.statusText; }
Sending the request synchronously (setting the third argument of open() to false) enables you to start evaluating the response immediately after the call to send(). This can be useful if you want the user interaction to wait for a response or if you're expecting to receive only a very small amount of data (for example, less than 1K). In the case of average or larger amounts of data, it's best to use an asynchronous call.

XMLHttp Requests in PHP

When Microsoft Internet Explorer 5.0 introduced a rudimentary level of XML support, an ActiveX library called MSXML was also introduced (discussed at length in Chapter 4). One of the objects provided in this library quickly became very popular: XMLHttp. The XMLHttp object was created to enable developers to initiate HTTP requests from anywhere in an application. These requests were intended to return XML, so the XMLHttp object provided an easy way to access this information in the form of an XML document. Since it was an ActiveX control, XMLHttp could be used not only in web pages but also in any Windows-based desktop application; however, its popularity on the Web has far outpaced its popularity for desktop applications.
Picking up on that popularity, Mozilla duplicated the XMLHttp functionality for use in its browsers, such as Firefox. Shortly thereafter, both the Safari (as of version 1.2) and Opera (version 7.6) browsers had duplicated Mozilla's implementation. Today, all four browsers support XMLHttp to some extent. (Safari and Opera still have incomplete implementations, supporting GET and POST but no other request types.)

Advantages and Disadvantages of XMLHttp in php ajax

you can see the advantage of using XMLHttp for client-server communication instead of hidden frames. The code you write is much cleaner and the intent of the code is much more apparent than using numerous callback functions with hidden frames. You have access to request and response headers as well as HTTP status codes, enabling you to determine if your request was successful.

The downside is that, unlike hidden frames, there is no browser history record of the calls that were made. The Back and Forward buttons do not tie in to XMLHttp requests, so you have effectively cut off their use. It is for this reason that many Ajax applications use a mixture of XMLHttp and hidden frames to make a truly usable interface.
Another disadvantage, which applies to Internet Explorer only, is that you depend on ActiveX controls being enabled. If the user has your page set up in a particular security zone that doesn't allow ActiveX controls, you cannot access the XMLHttp object. In that case, you may have to default to using hidden frames.

XMLHttp GET Requests in php ajax

It's time to revisit the hidden frame GET example to see how the process could be improved using XMLHttp. The first change will be to GetCustomerData.php, which must be changed from an HTML page to simply return an HTML snippet.

0) { $aValues = mysql_fetch_array($oResult,MYSQL_ASSOC); $sInfo = $aValues['Name']."
".$aValues['Address']."
". $aValues['City']."
".$aValues['State']."
". $aValues['Zip']."

Phone: ".$aValues['Phone']."
". "". $aValues['E-mail'].""; } else { $sInfo = "Customer with ID $sID doesn't exist."; } mysql_close($oLink); echo $sInfo; ?>
As you can see, there are no visible HTML or JavaScript calls in the page. All the main logic remains the same, but there are two additional lines of PHP code. The first occurs at the beginning, where the header() function is used to set the content type of the page. Even though the page will return an HTML snippet, it's fine to set the content type as text/plain, because it's not a complete HTML page (and therefore wouldn't validate as HTML). You should always set the content type in any page that is sending non-HTML to the browser. The second added line is towards the bottom, where the $sInfo variable is output to the stream by using the echo command. In the main HTML page, the basic setup is this:

Enter customer ID number to retrieve information:

Customer ID:

The requestCustomerInfo() function previously created a hidden iframe but now must be changed to use XMLHttp: function requestCustomerInfo() { var sId = document.getElementById("txtCustomerId").value; var oXmlHttp = zXmlHttp.createRequest(); oXmlHttp.open("get", "GetCustomerData.php?id=" + sId, true); oXmlHttp.onreadystatechange = function () { if (oXmlHttp.readyState == 4) { if (oXmlHttp.status == 200) { displayCustomerInfo(oXmlHttp.responseText); } else { displayCustomerInfo("An error occurred: "+ oXmlHttp.statusText); } } }; oXmlHttp.send(null); }
Note that the function begins the same way, by retrieving the ID the user entered. Then, an XMLHttp object is created using the zXml library. The open() method is called, specifying an asynchronous GET request for GetCustomerData.php (which has the aforementioned ID added to its query string). Next comes the assignment of the event handler, which checks for a readyState of 4 and then checks the status of the request. If the request was successful (status of 200), the displayCustomerInfo() function is called with the response body (accessed via responseText). If there was an error (status is not 200), then the error information is passed to displayCustomerInfo().
There are several differences between this and the hidden frame/iframe example. First, no JavaScript code is required outside of the main page. This is important because any time you need to keep code in two different places there is the possibility of creating incompatibilities; in the frame-based examples, you relied on separate scripts in the display page and the hidden frames to communicate with one another. By changing GetCustomerInfo.php to return just the data you're interested in, you have eliminated potential problems with JavaScript calling between these locations. The second difference is that it's much easier to tell if there was a problem executing the request. In previous examples, there was no mechanism by which you could identify and respond to a server error in the request process. Using XMLHttp, all server errors are revealed to you as a developer, enabling you to pass along meaningful error feedback to the user. In many ways, XMLHttp is a more elegant solution than hidden frames for in-page HTTP requests.

Overview of Changes in PHP 6

PHP 6.0 is, in many ways, a “cleanup” release for the language. In addition to
cleaning up the object model and fixing many bugs, PHP 6.0 adds full Unicode
support from the ground up. It introduces large integers (64-bit) and better SQL
Lite functionality, and includes all of the changes from PHP 5.1 through the final
releases of the 5.0 line, as well as everything new in 6.0.

Friday, May 8, 2009

Understanding Variable Scope in PHP

Understanding Variable Scope

inside a function to variables that hold arguments don't affect those variables outside of the function. This is because activity inside a function happens in a different scope. Variables defined outside of a function are called global variables. They exist in one scope. Variables defined inside of a function are called local variables. Each function has its own scope.

Imagine each function is one branch office of a big company, and the code outside of any function is the company headquarters. At the Philadelphia branch office, co-workers refer to each other by their first names: "Alice did great work on this report," or "Bob never puts the right amount of sugar in my coffee." These statements talk about the folks in Philadelphia (local variables of one function), and say nothing about an Alice or a Bob who works at another branch office (local variables of another function) or at company headquarters (global variables).

Local and global variables work similarly. A variable called $dinner inside a function, whether or not it's an argument to that function, is completely disconnected from a variable called $dinner outside of the function and from a variable called $dinner inside another function. Example 5-20 illustrates the unconnectedness of variables in different scopes.

Variable scope
$dinner = 'Curry Cuttlefish';
function vegetarian_dinner( ) {

print "Dinner is $dinner, or ";
$dinner = 'Sauteed Pea Shoots';
print $dinner;
print "\n";
}

function kosher_dinner( ) {
print "Dinner is $dinner, or ";
$dinner = 'Kung Pao Chicken';
print $dinner;
print "\n";
}

print "Vegetarian ";
vegetarian_dinner( );
print "Kosher ";
kosher_dinner( );
print "Regular dinner is $dinner";

prints:
Vegetarian Dinner is , or Sauteed Pea Shoots
Kosher Dinner is , or Kung Pao Chicken
Regular dinner is Curry Cuttlefish


In both functions, before $dinner is set to a value inside the function, it has no value. The global variable $dinner has no effect inside the function. Once $dinner is set inside a function, though, it doesn't affect the global $dinner set outside any function or the $dinner variable in another function. Inside each function, $dinner refers to the local version of $dinner and is completely separate from a variable that happens to have the same name in another function.

Like all analogies, though, the analogy between variable scope and corporate organization is not perfect. In a company, you can easily refer to employees at other locations; the folks in Philadelphia can talk about "Alice at headquarters" or "Bob in Atlanta," and the overlords at headquarters can decide the futures of "Alice in Philadelphia" or "Bob in Charleston." With variables, however, you can access global variables from inside a function, but you can't access the local variables of a function from outside that function. This is equivalent to folks at a branch office being able to talk about people at headquarters but not anyone at the other branch offices, and to folks at headquarters not being able to talk about anyone at any branch office.

There are two ways to access a global variable from inside a function. The most straightforward is to look for them in a special array called $GLOBALS. Each global variable is accessible as an element in that array. demonstrates how to use the $GLOBALS array.

The $GLOBALS array
$dinner = 'Curry Cuttlefish';

function macrobiotic_dinner( ) {
$dinner = "Some Vegetables";
print "Dinner is $dinner";
// Succumb to the delights of the ocean
print " but I'd rather have ";
print $GLOBALS['dinner'];
print "\n";

}

macrobiotic_dinner( );
print "Regular dinner is: $dinner";

prints:

Dinner is Some Vegetables but I'd rather have Curry Cuttlefish
Regular dinner is: Curry Cuttlefish

accesses the global $dinner from inside the function as $GLOBALS['dinner']. The $GLOBALS array can also modify global variables.

Modifying a variable with $GLOBALS
$dinner = 'Curry Cuttlefish';

function hungry_dinner( ) {
$GLOBALS['dinner'] .= ' and Deep-Fried Taro';
}

print "Regular dinner is $dinner";
print "\n";
hungry_dinner( );
print "Hungry dinner is $dinner";

prints:

Regular dinner is Curry Cuttlefish
Hungry dinner is Curry Cuttlefish and Deep-Fried Taro
Inside the hungry_dinner( ) function, $GLOBALS['dinner'] can be modified just like any other variable, and the modifications change the global variable $dinner. In this case, $GLOBALS['dinner'] has a string appended to it using the concatenation operator.

The second way to access a global variable inside a function is to use the global keyword. This tells the PHP interpreter that further use of the named variable inside a function should refer to the global variable with the given name, not a local variable. This is called "bringing a variable into local scope."

The global keyword
$dinner = 'Curry Cuttlefish';

function vegetarian_dinner( ) {
global $dinner;
print "Dinner was $dinner, but now it's ";
$dinner = 'Sauteed Pea Shoots';
print $dinner;
print "\n";
}

print "Regular Dinner is $dinner.\n";
vegetarian_dinner( );
print "Regular dinner is $dinner";

prints:

Regular Dinner is Curry Cuttlefish.
Dinner was Curry Cuttlefish, but now it's Sauteed Pea Shoots
Regular dinner is Sauteed Pea Shoots

The first print statement displays the unmodified value of the global variable $dinner. The global $dinner line in vegetarian_dinner( ) means that any use of $dinner inside the function refers to the global $dinner, not a local variable with the same name. So, the first print statement in the function prints the already-set global value, and the assignment on the next line changes the global value. Since the global value is changed inside the function, the last print statement outside the function prints the changed value as well.
The global keyword can be used with multiple variable names at once. Just separate each variable name with a comma.
For example:
global $dinner, $lunch, $breakfast;

Generally, I recommend that you use the $GLOBALS array to access global variables inside functions instead of the global keyword. Using $GLOBALS provides a reminder on every variable access that you're dealing with a global variable. Unless you're writing a very short function, it's easy to forget that you're dealing with a global variable with global and become confused as to why your code is misbehaving. Relying on the $GLOBALS array requires a tiny bit of extra typing, but it does wonders for your code's intelligibility.

You may have noticed something strange about the examples that use the $GLOBALS array. These examples use $GLOBALS inside a function, but don't bring $GLOBALS into local scope with the global keyword. The $GLOBALS array, whether used inside or outside a function, is always in scope. This is because $GLOBALS is a special kind of pre-defined variable, called an auto-global . Auto-globals are variables that can be used anywhere in your PHP programs without anything required to bring them into scope. They're like a well-known employee that everyone, at headquarters or a branch office, refers to by his first name.

The auto-globals are always arrays that are automatically populated with data. They contain things such as submitted form data, cookie values, and session information.

Error Reporting in PHP

Error Reporting

Types of Errors in PHP
Before we can get into remedying ugly error messages on your site, you need to understand the different types of errors. PHP4 can produce 11 different errors, as defined in Table 8-1 below (note that fatal errors stop the script from executing):

PHP Error Types

NAME VALUE DESCRIPTION
E_ERROR 1 Fatal error that occurs at script runtime.
E_WARNING 2 Nonfatal error that occurs at runtime (for example, if the script is unable to connect to MySQL).
E_PARSE 4 Error that occurs at compile time due to invalid syntax.
E_NOTICE 8 Nonfatal "notice." Not exactly an error, but a hint that you may be doing something you don't want to, such as dividing a number by zero.
E_CORE_ERROR 16 Fatal error that occurs when the PHP engine starts. You cannot run any PHP scripts if this error occurs.
E_CORE_WARNING 32 Nonfatal error that occurs when the PHP engine starts. You can still run PHP scripts, but you may have one or more problems depending on the error (for example, the GD library cannot be found).
E_COMPILE_ERROR 64 Fatal error that occurs when the script is compiled.
E_COMPILE_WARNING 128 Nonfatal error that occurs when the script is compiled.
E_USER_ERROR 256 User-generated fatal error. Same as E_ERROR, but never thrown by PHP. You can throw this error with the trigger_error() function. If you are using PHP's default error handler, then using this error causes script execution to stop.
E_USER_WARNING 512 User-generated nonfatal error. Same as E_WARNING, but never thrown by PHP. You can throw this error with the trigger_error() function.
E_USER_NOTICE 1024 User-generated notice. Same as E_NOTICE, but never thrown by PHP. You can throw this error with the trigger_error() function.
E_ALL 2047 Not really a type of error. Instead, it is all the errors rolled into one. This makes it easy to say that you want to report all of the errors when using the error_reporting() function.


Of all of these errors, the ones you should mainly concern yourself when it comes to reporting and logging are the following:

E_WARNING

E_NOTICE

E_USER_ERROR

E_USER_WARNING

E_USER_NOTICE

Other errors that occur usually result in the script not executing. Your reporting and logging function won't even be run, since there is no script execution.

Error Reporting Settings in php.ini
Side Note
This information applies to PHP Version 4 and later. These settings do not work with PHP Version 3.


The reason you see those "ugly" errors when you are coding is that PHP by default is set to show all errors (E_ALL), with the exception of PHP-generated notices (E_NOTICE). Open your php.ini file and scroll down to the section entitled "Error handling and logging." At the end of all those comments, you should see a line like the following:

error_reporting = E_ALL & ~E_NOTICE

This is the default error reporting setting. It's written using bitwise operators and is translated simply to "For Error Reporting Use Everything And Not E_NOTICE." You could also write it as follows (note that we leave out E_NOTICE):

[View full width]
error_reporting = E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_CORE_WARNING |
E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE

However, since you are a PHP developer, you really should set this line to read as follows when you are developing an application:

error_reporting = E_ALL

You want to see all the errors that your script is producing. You'd be surprised at how many uninitialized variables you might be using.

error_reporting()
The error_reporting() function allows you to override the default error reporting setting used in php.ini:

error_reporting(settings);

The error_reporting function takes one argument, which can either be a string that lists the names of the error reporting settings that you want to use (separated by bitwise operators), or an integer that is the sum of the values that you want to use. For example:

error_reporting(10);

is equivalent to:

error_reporting("E_WARNING | E_NOTICE");

The first version is easier to type, but the second version is more verbose. Additionally, you can subtract values from the E_ALL value (2047) to use "all but" reporting. The example below allows you to display all errors (E_ALL) except for E_NOTICE (2047 - 8):

error_reporting(2039);

If you do not want to report any errors, then you could simply use:

error_reporting(0);

This stops PHP from displaying any error messages on the screen that are caused by E_WARNING, E_NOTICE or any of the user-thrown warnings. Remember, any of the other warnings are thrown automatically by PHP because there is something either really wrong with the script (parse errors) or really wrong with the server itself.

You still may run into a problem if there is an error that causes the script to fail to compile (such as with parse errors). In that case, no portions of your script are even executed, and the error_reporting() variable is not run. When this happens, PHP uses its php.ini setting for error reporting.

php.ini Setting: display_errors
Additionally, there is another setting that stops error messages from being displayed on the user's browser. This setting, display_errors, can be found in php.ini. In the event that you want to be sure that errors are never displayed on the screen, you can change this setting to "0" in your php.ini file. You should leave this setting to "1" or "On" while you are developing your application.

You can also change the display_errors setting on a per file basis using the ini_set() function. The ini_set() function allows you to change php.ini file settings for the current script. For example, if you had turned off display_errors in your php.ini file, then you could turn it on to debug your script by using the following code, which is the php.ini equivalent of display_errors = On:

ini_set("display_errors",1);

Remember, if your script encounters an error that does not allow it to execute, then PHP uses the settings it finds in php.ini, regardless of what you have specified in your script.