I have the following code snippet:
<?php
ini_set('display_errors', '1');
error_reporting(E_ALL | E_NOTICE);
print $bla;
print 7;
?>
which prints out a warning that bla is undefined, but continues afterwards. I want php to throw an error and stop code execution when an undefined variable is encountered. How to do that?
The above is just an example. I want to handle EACH undefined variable within a multi thousand block clode piece.
You could write your own error handler. And make it halt execution when you encounter this type of notice. Take a look at
http://php.net/manual/en/function.set-error-handler.php
A small and simple example:
function new_error_handler($errno, $errstr, $errfile, $errline) {
switch ($errno) {
case E_NOTICE:
if (strstr($errstr, 'Undefined variable')) {
die('Undefined variable found');
}
break;
}
}
set_error_handler('new_error_handler');
echo $foo;
Implement an error handler with set_error_handler and put a die inside.
if(!isset($bla)){
throw new Exception('bla variable is not defined');
}
Related
Came across this today, not sure how to solve it.
I want to catch an E_WARNING level error issued by hex2bin().
I thought I might be able to use a try()catch() exception method but it did not work.
try {
$foo = hex2bin($bar);
}
catch (Exception $e) {
die('Custom message');
}
The standard E_WARNING that is issued is, of course:
Warning: hex2bin(): Input string must be hexadecimal string
In this particular situation I do not want to use the standard methods to disable errors, such as:
error_reporting(-1);
error_reporting(E_ALL);
ini_set("display_errors", 1);
Nor do I want to suppress the error using a #hex2bin method.
I actually want to have a custom error displayed, but I just do not seem to be able to find a way to catch when hex2bin throws an error.
You can check the input value to verify that it is hex before passing it to the hex2bin method.
if (ctype_xdigit($bar) && strlen($bar) % 2 == 0) {
$foo = hex2bin($bar);
} else {
//display error here
}
Per the documentation, hex2bin returns:
the binary representation of the given data or FALSE on failure.
That means you can do something like this if you want to use it in a try/catch block:
try {
$foo = #hex2bin($bar);
if(false === $foo) {
throw new Exception("Invalid hexedecimal value.");
}
} catch(Exception $e) {
echo $e;
}
Yes, hex2bin is suppressed. You can remove the # if you set error_reporting to suppress warnings.
Alternatively, you can check the type of $foo with ctype_xdigit() prior to using hex2bin().
I am trying to create a custom error function (following a tutorial). I have:
<?php
error_reporting(E_ERROR);
function handleError ($errno, $errstr,$error_file,$error_line){
echo "<b>Error:</b> [$errno] $errstr - $error_file:$error_line";
echo "<br />";
echo "Terminating PHP Script";
die();
}
//set the error handler here, override the default
set_error_handler("handleError");
//cause a crash
myfunction();
?>
However my script isn't calling the function. It just prints the default error message. Could someone give me a pointer to what I might be doing wrong here please? Is my error_reporting value wrong?
There is nothing wrong with your code. However, the capabilities of set_error_handler are limited.
From the PHP documentation:
The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING,
E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised
in the file where set_error_handler() is called.
If you indeed need to catch compilation errors as in your example, there is one workaround mentioned in the comments of the documentation above - the use of a shutdown function:
<?php
error_reporting(E_ERROR);
function handleError($errno, $errstr, $error_file, $error_line) {
echo "<b>Error:</b> [$errno] $errstr - $error_file:$error_line";
echo "<br />";
echo "Terminating PHP Script";
die();
}
function checkForError() {
$error = error_get_last();
if ($error["type"] == E_ERROR) {
handleError($error["type"], $error["message"], $error["file"], $error["line"]);
}
}
register_shutdown_function("checkForError");
// cause a crash
myfunction();
?>
Note that the default error handler will still be called, so this prints out:
Fatal error: Call to undefined function myfunction() in path\to\file.php on line 24
Error: [1] Call to undefined function myfunction() - path\to\file.php:24
Terminating PHP Script
You can get rid of the default message by disabling error reporting with error_reporting(0);.
If you want to handle errors from within your method execution (i.e. you have defined myfunction somewhere), your original example might already work, depending on your concrete case. Proof, e.g.:
<?php
error_reporting(E_ERROR);
function handleError($errno, $errstr, $error_file, $error_line) {
echo "<b>Error:</b> [$errno] $errstr - $error_file:$error_line";
echo "<br />";
echo "Terminating PHP Script";
die();
}
function myfunction() {
fopen("nonexistingfile", "r");
}
// set the error handler here, override the default
set_error_handler("handleError");
// cause a crash
myfunction();
?>
This uses the custom error handler as expected and prints out:
Error: [2] fopen(nonexistingfile): failed to open stream: No such file or directory - path\to\file.php:12
Terminating PHP Script
I got this code from w3schools, I think you might have a need to trigger it
<?php
// A user-defined error handler function
function myErrorHandler($errno, $errstr, $errfile, $errline) {
echo "<b>Custom error:</b> [$errno] $errstr<br>";
echo " Error on line $errline in $errfile<br>";
}
// Set user-defined error handler function
set_error_handler("myErrorHandler");
$test=2;
// Trigger error
if ($test>1) {
trigger_error("A custom error has been triggered");
}
?>
I am building an app with Symfony 2, and I am wondering, how could I handle errors when I try to read a index in an array that doesn't exist? Sadly this kind of errors don't throw exceptions, so I can't really use a try-catch block.
Example:
$test = array();
$test["323"]; // Undefined index error!
Please, ideas how to handle this errors?
Update: I have seen many solutions with isset. The problem with this is that I would have to do it with every single access to an array index. Can anyone offer me a more DRY solution?
Both:
if(isset($test["323"])){
//Good
}
and
if(array_key_exists('123', $test)){
//Good
}
Will allow you to check if an array index is defined before attempting to use it. This is not a Symfony-specific error. Its a common PHP warning that occurs whenever you attempt to access an array element that doesn't exist.
$val = isset($test["323"]) ? $test["323"] : null;
An option would be to use set_error_handler() in order to, somehow, simulate exceptions. An example usage would be the following, although I'm sure you can adjust this to your specific use case:
function my_error_handler($errno,$errstr)
{
/* handle the issue */
return true; // if you want to bypass php's default handler
}
$test = array();
set_error_handler('my_error_handler');
$use_it=$test["323"]; // Undefined index error!
restore_error_handler();
You can see that we "wrap" our "critical" piece of code around set_error_handler() and restore_error_handler(). The code in question can be as little as a line, to as large as your whole script. Of course, the larger the critical section, the more "intelligent" the error handler has to be.
use array_key_exists(), like
if (array_key_exists('123', $test)) {
echo "it exists";
}
You can catch this bx surrounding it with isset:
if(isset($test["323"])){
//The value fo this key is set.
}
May be you wanted to achieve this ?
$test = array();
$test[]="323";
echo $test[0];//323
Simple way to try/catch undefined or many php errors.
try{
set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext){
if (0 === error_reporting()) { return false; }
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});
$data = $json['name']; ---> Undefined Index name
}catch(Exception $e){
//Perform Furthur action
}
I wrote the following snippet in order to handle errors.
(Page.php gets included in index page through : array( falseNamePage=> page.php, ....ect))
Perfoming some tests to see how it reacts, I delete a page.php from public_html.
RESULT :
-error logging ok
-alert email sending ok
-recording in DB : ERROR :
Notice: Undefined variable: $database in /home/.../public_html/index.php on line 40
Warning: mysql_query() expects parameter 2 to be resource, null given in /home/.../public_html/index.php on line 40 "impossible to connect with DB2"
I do not understands why it fails connecting to the DB in this case and sends back an error.
DB Connection works fine in every other cases ( delete, select,update, insert ...)
function errorHandler($errno, $errstr, $errfile, $errline)
{
require_once('connection.php');
$now = time();
$date = date("Y-m-d H:i:s",$now);
switch ($errno) {
case E_NOTICE:
case E_USER_NOTICE:
case E_DEPRECATED:
case E_USER_DEPRECATED:
case E_STRICT:
............ 5 first cases code...............
case E_WARNING:
case E_USER_WARNING:
$message_warning = "Warning : ".$errno." : ".$errstr." : ".$errfile." : ".$errline;
error_log ( $message_warning ,0);
$mail = 'my_mail#yahoo.com'; $sujet = $message_warning; $body_warning = $date." : ".$message_warning;
mail($mail,'=?UTF-8?B?'.base64_encode($sujet).'?=',stripslashes($body_warning));
$query_warning =" INSERT INTO errorlog (severity,errno,errstr,errfile,errline,time)
VALUES ('WARNING','".$errno."','".$errstr."','".$errfile."','".$errline."','".$date."')";
$result_warning = mysql_query($query_warning,$database) or die("impossible to connect with DB2");
break;
case E_ERROR:
case E_USER_ERROR:
............... 2 last cases code ..........
}
}
set_error_handler("errorHandler");
The final question is :
WHY IS AN INCLUDE ERROR ECHOED 4 TIMES ?
Does the system attempts 4 times to "open stream"?
I did :
function errorHandler($errno, $errstr, $errfile, $errline)
{
if ($errno == E_NOTICE )
{ echo "<br/>".$errno."== E_NOTICE<br/>";}
if ($errno == E_USER_NOTICE)
{ echo "<br/>".$errno."== E_USER_NOTICE<br/>";}
if ($errno == E_DEPRECATED)
{ echo "<br/>".$errno."== E_DEPRECATED<br/>";}
if ($errno == E_USER_DEPRECATED)
{ echo "<br/>".$errno."== E_USER_DEPRECATED<br/>";}
if ($errno == E_STRICT)
{ echo "<br/>".$errno."== E_STRICT<br/>";}
if ($errno == E_WARNING)
{ echo "<br/>".$errno."== E_WARNING<br/>";}
if ($errno == E_USER_WARNING)
{ echo "<br/>".$errno."== E_USER_WARNING<br/>";}
if ($errno == E_ERROR)
{ echo "<br/>".$errno."== E_ERROR<br/>";}
if ($errno == E_USER_ERROR)
{ echo "<br/>".$errno."== E_USER_ERROR<br/>";}
}
set_error_handler("errorHandler");
RESULT :
2== E_WARNING
2== E_WARNING
2== E_WARNING
2== E_WARNING
Probably connection.php has already been included before, so when you use require_once in your code, it does not include connection.php again. Then, $database variable will not be defined, and you will got that error message.
Your problem is simple, and, in my opinion, it's YAPHPB: you're using require_once within a function definition, hoping that the file will be included just once - to shape up a function's body.
But it doesn't work like that: this code will be parsed each time (well, it's a bit simplified, but the reasons still the same) the function will get called. And because it's require_once, your file will be included just once indeed - only when the function is called first time. All the next calls will skip the file's inclusion, hence $database will not be defined.
The easiest way to fix it is to replace require_once with require. But I think the problem just will be covered - but not solved. The real solution would be to restructure your code in such way that your $database will actually become a record in registry - and will be lazily extracted from that registry if needed.
There are many ways to implement such behaviour: we often use Zend_Registry component for that. And in this topic there are some examples of how to use this component effectively.
When there is no function definition and no constant definition in connection.php use require instead of require_once.
The variable $database will not be available when the function is called the second time, because of require_once. It is a little bit bad designed here.
A solution would be to have $database as a constant, so it acts like a global variable no matter if connection.php was the included first or second time.
PHPs token_get_all function (which allows converting a PHP source code into tokens) can throw two errors: One if an unterminated multiline comment is encountered, the other if an unexpected char is found.
I would like to catch those errors and throw them as Exceptions.
Problem is: As those errors are parse errors they cannot be handled with an error handling function you would normally specify using set_error_handler.
What I have currently implemented is the following:
// Reset the error message in error_get_last()
#$errorGetLastResetUndefinedVariable;
$this->tokens = #token_get_all($code);
$error = error_get_last();
if (preg_match(
'~^(Unterminated comment) starting line ([0-9]+)$~',
$error['message'],
$matches
)
) {
throw new ParseErrorException($matches[1], $matches[2]);
}
if (preg_match(
'~^(Unexpected character in input:\s+\'(.)\' \(ASCII=[0-9]+\))~s',
$error['message'],
$matches
)
) {
throw new ParseErrorException($matches[1]);
}
It should be obvious that I'm not really excited to use that solution. Especially the fact that I reset the error message in error_get_last by accessing an undefined variable seems pretty unsatisfactory.
So: Is there a better solution to this problem?
Set a custom errorhandler using set_error_handler.
Call token_get_all.
Then unset the error handler by calling restore_error_handler.
This will allow you to catch warnings. Make sure you remove the # suppressor.
You can for instance register an error handler that is in a class that will just record any warnings for inspection later on.
Untested example code:
class CatchWarnings {
private $warnings = array();
public function handler($errno, $errstr, $errfile, $errline) {
switch ($errno) {
case E_USER_WARNING:
$this->warnings[] = $errstr;
return true; // cancel error handling bubble
}
return false; // error handling as usual
}
public function has_warnings() {
return count($this->warnings) > 0;
}
}
$cw = new CatchWarnings();
set_error_handler(array($cw, "handler"));
token_get_all();
restore_error_handler();
Usually validation and execution are two separate things, but it seems like there is no way to validate/lint a piece of PHP code (not since 5.x anyway).