<chapter id="features.error-handling">
  <title>Error Handling</title>
 
  <para>
   There are several types of errors and warnings in PHP.  They are:

   <table>
    <title>PHP error types</title>
    <tgroup cols="4">
     <thead>
      <row>
       <entry>Value</entry>
       <entry>Constant</entry>
       <entry>Description</entry>
       <entry>Note</entry>
      </row>
     </thead>
     <tbody>
      <row>
       <entry>1</entry>
       <entry>E_ERROR</entry>
       <entry>fatal run-time errors</entry>
       <entry></entry>
      </row>
      <row>
       <entry>2</entry>
       <entry>E_WARNING</entry>
       <entry>run-time warnings (non fatal errors)</entry>
       <entry></entry>
      </row>
      <row>
       <entry>4</entry>
       <entry>E_PARSE</entry>
       <entry>compile-time parse errors</entry>
       <entry></entry>
      </row>
      <row>
       <entry>8</entry>
       <entry>E_NOTICE  </entry>
       <entry>
        run-time notices (less serious than warnings)
       </entry>
       <entry></entry>
      </row>
      <row>
       <entry>16</entry>
       <entry>E_CORE_ERROR</entry>
       <entry>fatal errors that occur during PHP's initial startup</entry>
       <entry>PHP 4 only</entry>
      </row>
      <row>
       <entry>32</entry>
       <entry>E_CORE_WARNING</entry>
       <entry>
    warnings (non fatal errors) that occur during PHP's initial
    startup
       </entry> 
       <entry>PHP 4 only</entry>
      </row>
      <row>
       <entry>64</entry>
       <entry>E_COMPILE_ERROR</entry>
       <entry>fatal compile-time errors</entry>
       <entry>PHP 4 only</entry>
      </row>
      <row>
       <entry>128</entry>
       <entry>E_COMPILE_WARNING</entry>
       <entry>compile-time warnings (non fatal errors)</entry>
       <entry>PHP 4 only</entry>
      </row>
      <row>
       <entry>256</entry>
       <entry>E_USER_ERROR</entry>
       <entry>user-generated error message</entry>
       <entry>PHP 4 only</entry>
      </row>
      <row>
       <entry>512</entry>
       <entry>E_USER_WARNING</entry>
       <entry>user-generated warning message</entry>
       <entry>PHP 4 only</entry>
      </row>
      <row>
       <entry>1024</entry>
       <entry>E_USER_NOTICE </entry>
       <entry>user-generated notice message</entry>
       <entry>PHP 4 only</entry>
      </row>
      <row>
       <entry></entry>
       <entry>E_ALL</entry>
       <entry>all of the above, as supported</entry>
       <entry></entry>
      </row>
     </tbody>
    </tgroup>
   </table>
  </para>

  <para>
   The above values (either numerical or symbolic) are used to build
   up a bitmask that specifies which errors to report. You can use the
   <link linkend="language.operators.bitwise">bitwise operators</link>
   to combine these values or mask out certain types of errors. Note
   that only '|', '~', '!', and '&amp;' will be understood within
   <filename>php.ini</filename>, however, and that no bitwise
   operators will be understood within <filename>php3.ini</filename>.
  </para>
  <para>
   In PHP 4, the default <link
   linkend="ini.error-reporting">error_reporting</link> setting is
   <literal>E_ALL &amp; ~E_NOTICE</literal>, meaning to display all errors
   and warnings which are not E_NOTICE-level. In PHP 3, the default
   setting is <literal>(E_ERROR | E_WARNING | E_PARSE)</literal>,
   meaning the same thing. Note, however, that since constants are not
   supported in PHP 3's <filename>php3.ini</filename>, the <link
   linkend="ini.error-reporting">error_reporting</link> setting there
   must be numeric; hence, it is <literal>7</literal>.
  </para>

  <para>
   The initial setting can be changed in the ini file with the <link
   linkend="ini.error-reporting">error_reporting</link> directive, in
   your Apache <filename>httpd.conf</filename> file with the
   php_error_reporting (php3_error_reporting for PHP 3) directive, and
   lastly it may be set at runtime within a script by using the
   <function>error_reporting</function> function.
  </para>
  
  <warning>
   <para>
    When upgrading code or servers from PHP 3 to PHP 4 you should
    check these settings and calls to
    <function>error_reporting</function> or you might disable
    reporting the new error types, especially E_COMPILE_ERROR.  This
    may lead to empty documents without any feedback of what happened
    or where to look for the problem.
   </para>
  </warning>
    
  <para>
   All <link linkend="language.expressions">PHP expressions</link> can
   also be called with the "@" prefix, which turns off error reporting
   for that particular expression.  If an error occurred during such
   an expression and the <link
   linkend="ini.track-errors">track_errors</link> feature is enabled,
   you can find the error message in the global variable
   <literal>$php_errormsg</literal>.
  </para>

  <note>
   <para>
    The <link linkend="language.operators.errorcontrol">@
    error-control operator</link> prefix will not disable messages
    that are the result of parse errors.
   </para>
  </note>

  <warning>
   <para>
    Currently the <link linkend="language.operators.errorcontrol">@
    error-control operator</link> prefix will even disable error
    reporting for critical errors that will terminate script
    execution. Among other things, this means that if you use <link
    linkend="language.operators.errorcontrol">@</link> to suppress
    errors from a certain function and either it isn't available or
    has been mistyped, the script will die right there with no
    indication as to why.
   </para>
  </warning>

  <para>
   Below we can see an example of using the error handling capabilities in
   PHP. We define a error handling function which logs the information into
   a file (using an XML format), and e-mails the developer in case a critical
   error in the logic happens.
   <example>
    <title>Using error handling in a script</title>
    <programlisting role="php">
&lt;?php
// we will do our own error handling
error_reporting(0);

// user defined error handling function
function userErrorHandler ($errno, $errmsg, $filename, $linenum, $vars) {
    // timestamp for the error entry
    $dt = date(&quot;Y-m-d H:i:s (T)&quot;);

    // define an assoc array of error string
    // in reality the only entries we should
    // consider are 2,8,256,512 and 1024
    $errortype = array (
                1   =&gt;  &quot;Error&quot;,
                2   =&gt;  &quot;Warning&quot;,
                4   =&gt;  &quot;Parsing Error&quot;,
                8   =&gt;  &quot;Notice&quot;,
                16  =&gt;  &quot;Core Error&quot;,
                32  =&gt;  &quot;Core Warning&quot;,
                64  =&gt;  &quot;Compile Error&quot;,
                128 =&gt;  &quot;Compile Warning&quot;,
                256 =&gt;  &quot;User Error&quot;,
                512 =&gt;  &quot;User Warning&quot;,
                1024=&gt;  &quot;User Notice&quot;
                );
    // set of errors for which a var trace will be saved
    $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);
    
    $err = &quot;&lt;errorentry&gt;\n&quot;;
    $err .= &quot;\t&lt;datetime&gt;&quot;.$dt.&quot;&lt;/datetime&gt;\n&quot;;
    $err .= &quot;\t&lt;errornum&gt;&quot;.$errno.&quot;&lt;/errnumber&gt;\n&quot;;
    $err .= &quot;\t&lt;errortype&gt;&quot;.$errortype[$errno].&quot;&lt;/errortype&gt;\n&quot;;
    $err .= &quot;\t&lt;errormsg&gt;&quot;.$errmsg.&quot;&lt;/errormsg&gt;\n&quot;;
    $err .= &quot;\t&lt;scriptname&gt;&quot;.$filename.&quot;&lt;/scriptname&gt;\n&quot;;
    $err .= &quot;\t&lt;scriptlinenum&gt;&quot;.$linenum.&quot;&lt;/scriptlinenum&gt;\n&quot;;

    if (in_array($errno, $user_errors))
        $err .= &quot;\t&lt;vartrace&gt;&quot;.wddx_serialize_value($vars,&quot;Variables&quot;).&quot;&lt;/vartrace&gt;\n&quot;;
    $err .= &quot;&lt;/errorentry&gt;\n\n&quot;;
    
    // for testing
    // echo $err;

    // save to the error log, and e-mail me if there is a critical user error
    error_log($err, 3, &quot;/usr/local/php4/error.log&quot;);
    if ($errno == E_USER_ERROR)
        mail(&quot;phpdev@mydomain.com&quot;,&quot;Critical User Error&quot;,$err);
}


function distance ($vect1, $vect2) {
    if (!is_array($vect1) || !is_array($vect2)) {
        trigger_error(&quot;Incorrect parameters, arrays expected&quot;, E_USER_ERROR);
        return NULL;
    }

    if (count($vect1) != count($vect2)) {
        trigger_error(&quot;Vectors need to be of the same size&quot;, E_USER_ERROR);
        return NULL;
    }

    for ($i=0; $i&lt;count($vect1); $i++) {
        $c1 = $vect1[$i]; $c2 = $vect2[$i];
        $d = 0.0;
        if (!is_numeric($c1)) {
            trigger_error(&quot;Coordinate $i in vector 1 is not a number, using zero&quot;, 
                            E_USER_WARNING);
            $c1 = 0.0;
        }
        if (!is_numeric($c2)) {
            trigger_error(&quot;Coordinate $i in vector 2 is not a number, using zero&quot;, 
                            E_USER_WARNING);
            $c2 = 0.0;
        }
        $d += $c2*$c2 - $c1*$c1;
    }
    return sqrt($d);
}

$old_error_handler = set_error_handler(&quot;userErrorHandler&quot;);

// undefined constant, generates a warning
$t = I_AM_NOT_DEFINED;

// define some &quot;vectors&quot;
$a = array(2,3,&quot;foo&quot;);
$b = array(5.5, 4.3, -1.6);
$c = array (1,-3);

// generate a user error
$t1 = distance($c,$b).&quot;\n&quot;;

// generate another user error
$t2 = distance($b,&quot;i am not an array&quot;).&quot;\n&quot;;

// generate a warning
$t3 = distance($a,$b).&quot;\n&quot;;

?&gt;
    </programlisting>
   </example>
   This is just a simple example showing how to use the 
   <link linkend="ref.errorfunc">Error Handling and Logging
   functions</link>.
  </para>

  <para>
   See also <function>error_reporting</function>,
   <function>error_log</function>,
   <function>set_error_handler</function>,
   <function>restore_error_handler</function>, 
   <function>trigger_error</function>,
   <function>user_error</function>
  </para>

 </chapter>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->