This is about DateTime::__construct. According to this comment:
If time cannot be parsed an exception of type Exception is thrown which can be caught, however an E_WARNING is emitted as well. This might be confusing if you are converting warnings to exceptions in your error or shutdown handler.
Can I avoid the warning? I have a code like (I don't care if the date is well formed or not):
try {
$var = new DateTime('some invalid date format');
} catch (Exception $exception) {
$var = null;
}
But it still send a E_WARNING that is reported to my error catcher (I use NewRelic in a Laravel application). And I don't want this error to be reported because it's not an error, I catched it.
How can I avoid DateTime::__construct emit a warning?
This is possibly one of the few cases where it's acceptable to use:
try {
$var = #new DateTime('some invalid date format');
} catch (Exception $e) {
$var = null;
}
However you can avoid the # operator by doing:
try {
$oldErrorReporting = error_reporting();
error_reporting($oldErrorReporting & ~E_WARNING);
$var = new DateTime('some invalid date format');
error_reporting($oldErrorReporting);
} catch (Exception $e) {
$var = null;
}
Use the date_create() function instead.
It (I assume) internally works similar to the try/catch block you want to avoid and returns FALSE if the date is not valid. It doesn't trigger any error or warning.
The code:
$var = date_create('some invalid date format');
is, more or less, the same as:
try {
$var = new DateTime('some invalid date format');
} catch (Exception $exception) {
$var = false;
}
You should create an error handler like this:
//set_error_handler();
set_error_handler(function($msg, $code, $severity, $file, $lineno, $errText) {
if (0 === error_reporting()) {
return false;
}
throw new ErrorException($msg, $code, $severity, $file, $lineno);
});
Then,
try {
$var = new DateTime('some invalid date format');
} catch (ErrorException $exception) {
$var = null;
}
Related
Here is my code:
try {
if ( condition 1 ) {
throw;
} else {
// do something
}
// some code here
if ( condition 2 ){
throw;
}
} catch (Exception $e) {
echo "something is wrong";
}
As you see, my catch block has its own error message, And that message is a constant. So really I don't need to pass a message when I use throw like this:
throw new Exception('error message');
Well can I use throw without anything? I just need to jump into catch block.
Honestly writing an useless error message is annoying for me.
As you know my current code has a syntax error: (it referring to throw;)
Parse error: syntax error, unexpected ';' in {path}
message parameter is optional in the Exception constructor. So if you don't have/want to put - just don't:
throw new Exception;
But you still must throw an instance of the Exception class (or a class that extends it), since it is a part of the php language syntax.
If you want all your exceptions to have the same message, you can extend it and define the message in your class:
class AmbiguousException extends Exception {
public function __construct($message = 'Something is wrong.', $code = 0, Exception $previous = null) {
parent::__construct($message, $code, $previous);
}
}
Then:
throw new AmbiguousException();
You can use the below throw everytime you need.
throw new Exception();
and catch will remain same as your code.
As stated in the PHP manual:
The thrown object must be an instance of the Exception class or a subclass of Exception. Trying to throw an object that is not will result in a PHP Fatal Error.
You can throw an exception without any message:
throw new Exception();
Perhaps something to help you from duplicating the same exception is as follows:
$e = new Exception('something is wrong');
try {
throw $e;
} catch (Exception $ex) {
echo $ex->getMessage();
}
You can create an instance with default message and then throw that instance.
$Exception = new Exception("some error message!");
try {
throw $Exception;
} catch (Exception $ex) {
var_dump($ex);
}
You cannot use the throw keyword on its own. However, you can use throw new Exception(); without specify the $message parameter, because it'll just fallback to the default message. Check out the Exceptions section in the PHP manual: http://php.net/manual/en/language.exceptions.extending.php
I have code like this:
try {
$providerError = false;
$providerErrorMessage = null;
$nbg_xml_url = "http://www.somesite.com/rss.php";
$xml_content = file_get_contents($nbg_xml_url);
// ... some code stuff
} catch (Exception $e) {
$providerError = true;
$providerErrorMessage = $e -> getMessage();
$usd = 1;
$rate = null;
$gel = null;
} finally {
// .. Write in db
}`
and problem is that, when file_get_contents can not read url (may be site not responding or something like this..) my code writes error: failed to open stream: HTTP request failed! and execution goes direct to finally block bypass catch block without entering in it..
any ideas?
You can set an empty error handler to prevent the warning and afterward throw a custom exception in case of failure. In this case I would write a custom file_get_content like so:
function get_file_contents($url) {
$xml_content = file_get_contents($url);
if(!$xml_content) {
throw new Exception('file_get_contents failed');
}
return $xml_content;
}
and would use it in your block:
set_error_handler(function() { /* ignore errors */ });
try {
$providerError = false;
$providerErrorMessage = null;
$nbg_xml_url = "http://www.somesite.com/rss.php";
$xml_content = get_file_contents($nbg_xml_url); //<----------
// ... some code stuff
} catch (Exception $e) {
$providerError = true;
$providerErrorMessage = $e -> getMessage();
$usd = 1;
$rate = null;
$gel = null;
} finally {
// .. Write in db
}
Then remember to restore the error handler calling:
restore_error_handler();
Note that when using your own error handler it will bypass the
error_reporting
setting and all errors included notices, warnings, etc., will be passed to it.
$xml_content = file_get_contents($nbg_xml_url);
The function file_get_contents does not throw an exception. Thus an exception will not be thrown if as you say the file is not found.
From the docs:
An E_WARNING level error is generated if filename cannot be found...
This function returns the read data or FALSE on failure. So you could check if $xml_content is FALSE ($xml_content === false) and proceed accordingly.
This is a php code for catching any error or exception.
Throwable is the base interface for any object that can be thrown via a throw statement, including Error and Exception.
This will catch fatal errors too. Without throwable it will not catch fatal errors.
try {
// Code that may throw an Exception or Error.
} catch (Throwable $t) {
// Executed only in PHP 7, will not match in PHP 5.x
} catch (Exception $e) {
// Executed only in PHP 5.x, will not be reached in PHP 7
}
Say we have define a function that takes a reference paramter which will contain an error message, but we don't always need the error message, so we allow that reference parameter to be omitted:
function isSpider($bug, &$errorMsg = null) {
if(gettype($bug) !== "object") {
$errorMsg = "An error occurred: bug must be an object";
return false;
}
return $bug->species === "spider";
}
When we omit the reference parameter, is $errorMsg just a local variable? I tried assigning to it like in the example above and it produced no error messages with E_ALL on. It seems strange that you can assign a default value to a variable that is a reference to nothing. It's useful, but I just want to make sure I understand the intended behavior. The PHP docs are skimpy on this.
The two use cases that the optional reference parameter permits:
// we want to print the error message
if(!isSpider($bug1, $errorMsg)) echo $errorMsg;
or:
// don't care about the error message
if(isSpider($bug)) doSomething();
I think its better use try-catch to do error in your case.
function isSpider($bug, $alarm=TRUE) {
if (gettype($bug) !== "object") {
if ($alarm === TRUE) {
throw new Exception("An error occurred: bug must be an object");
}
return false;
}
return $bug->species === "spider";
}
If you want to print the error message:
try {
if (isSpider($bug1)) {
// do something
}
} catch (Exception $e) {
echo "We have an error: ".$e->getMessage();
}
If you want to store the error message for later use:
$errorMsg = FALSE;
try {
if (isSpider($bug1)) {
// do something
}
} catch (Exception $e) {
$errorMsg = $e->getMessage();
}
if ($errorMsg != FALSE) {
// do something with the error message
}
And if you want to ignore the message
// silent mode
if (isSpider($bug, FALSE)) {
// do something
}
I wonder if it's posible to get all the exceptions throwed.
public function test()
{
$arrayExceptions = array();
try {
throw new Exception('Division by zero.');
throw new Exception('This will never get throwed');
}
catch (Exception $e)
{
$arrayExceptions[] = $e;
}
}
I have a huge try catch block but i want to know all the errors, not only the first throwed. Is this possible with maybe more than one try or something like that or i am doing it wrong?
Thank you
You wrote it yourself: "This will never get throwed" [sic].
Because the exception will never get thrown, you cannot catch it. There only is one exception because after one exception is thrown, the whole block is abandoned and no further code in it is executed. Hence no second exception.
Maybe this was what the OP was actually asking for. If the function is not atomic and allows for some level of fault tolerance, then you can know all the errors that occurred afterwards instead of die()ing if you do something like this:
public function test()
{
$arrayExceptions = array();
try {
//action 1 throws an exception, as simulated below
throw new Exception('Division by zero.');
}
catch (Exception $e)
{
//handle action 1 's error using a default or fallback value
$arrayExceptions[] = $e;
}
try {
//action 2 throws another exception, as simulated below
throw new Exception('Value is not 42!');
}
catch (Exception $e)
{
//handle action 2 's error using a default or fallback value
$arrayExceptions[] = $e;
}
echo 'Task ended. Errors: '; // all the occurred exceptions are in the array
(count($arrayExceptions)!=0) ? print_r($arrayExceptions) : echo 'no error.';
}
I have an extended class for dateTime who makes some extra validation steps.
When a given date is invalid, it throws an exception.
Now I have some MySQL records with dates in zero (0000-00-00 00:00:00). In those cases, I want to show the text "never", so I have to catch the exception, and now I have this horrible mess...
try
{
$sellDate = new Date();
$sellDate ->setFromMySQL($this->_data['lastSell']);
$sellDateDMY = $dateSell->getDMY(TRUE);
}
catch (Exception $e)
{
if($e->getMessage() == 'Invalid date.')
$sellDateDMY = 'Never';
else
throw new Exception($e->getMessage());
}
$info[] = array('desc' => 'Last Sell: ' , 'data' => $sellDateDMY);
Any better way to do this?
Depends on which method it is that throws. The simplest would be to subclass Date again (maybe as NullableDate?) and override that method to not throw. The getDMY method would then return null, at which point you can display Never using the ternary operator ?:.
This way you won't have to use the ugly try/catch, and the intent of the code will also be clear to anyone who reads it for info on validation requirements -- by instantiating a NullableDate you definitely don't mind if its value is empty.
class DateException extends Exception {
public function __construct(Exception $e) {
if($e->getMessage() == 'Invalid date.') {
$this->message = 'Never';
} else {
$this->message = $e->getMessage();
}
}
}
try
{
$sellDate = new Date();
$sellDate ->setFromMySQL($this->_data['lastSell']);
$sellDateDMY = $dateSell->getDMY(TRUE);
}
catch (Exception $e)
{
throw new DateException($e);
}
You could start throwing different type of exceptions. Specific to the problem. Instead of the generic catch, you could do this
catch (DateInvalidException $de) {
//code
} catch (DateSomeOtherException $dso) {
//code
} catch (Exception $e) {
//general
}
But that's not a good solution. You're mixing up program exceptions and error validations.
Make your own Exception class for your Date functions.
class MyOwnDateException extends Exception {
... // Do something or probably nothing
}
And call it in your code:
try {
if($someErrorYouWantToCatch) {
throw new MyOwnDateException("error message", 100 /* Error code = optional */);
}
} catch(MyOwnDateException $mode) {
$sellDateDMY = 'Never';
}