catch is not working because there is installed an exception handler using set_exception_handler()
I need "catch" to work, so I guess I need to unset the exception handler somehow. Things such as set_exception_handler(NULL) isn't working.
Any ideas how to unset the exception handler?
function my_exception_handler($exception) {
error_log("caught exception: " . $exception->getMessage() );
}
set_exception_handler("my_exception_handler");
// QUESTION: how does on unset it ?
//set_exception_handler(NULL);
try {
throw new Exception('hello world');
error_log("should not happen");
} catch(Exception $e) {
error_log("should happen: " . $e->getMessage());
}
Actual output:
caught exception: hello world
Desired output:
should happen: hello world
restore_exception_handler, which is linked from the manual entry for set_exception_handler.
BTW, these exception handlers should only come into play when an exception is uncaught. A catch block should always have precedence.
Reading a little bit in the comments on the Exceptions page brings you to this bug and this bug. They describe exactly what you experience, Exceptions can't be caught when a custom error handler is defined.
Solution:
Fixed in 5.3 and HEAD, won't be backported to 5.2.
The function is restore_exception_handler. However, the handler should only be called when an exception is unhandled. It does not disable catches.
Related
I want to know what errors can be thrown that I am not catching, for dynamic code - not static code. For example, my code may run without throwing any Exceptions for 10 years and then throw UncaughtException
I want to specifically (non-generically) catch every type of Exception that can be thrown by the methods I am using. How can I know what Exceptions MAY be thrown by these methods?
I want to non-generically catch every type of error that can possibly be thrown for a section of PHP code.
Examples of exceptions that may be thrown:
PDOException
ExpiredException
Now I have this around everything:
try{
...
}catch(Exception $e){
...
}
I'd like to replace it with something like this:
try{
...
}catch(PDOException $e){
...
}catch(ExpiredException $e){
...
}catch(Exception $e){
...
}
I'd like to be confident that I am catching all different kinds of Exception that can be thrown by the methods in the section of code
And if I catch all Exceptions individually, will it be safe to remove this part?:
catch(Exception $e){
...
}
Or are there methods which will simply throw Exception?
My solution preference list (1 is the most-preferred solution):
1: A flag I can turn on that will cause php.exe to warn me about each and every possible type of Exception that is not specifically being caught
2: A way to individually check each method and see what errors can be thrown. Is the documentation the only way to check? or is there some IDE or PHP block that will tell me which Exceptions may be thrown by individual methods?
You can set callback function by using register_shutdown_function() which will call on every end of your php code execution. In this callback function you can check whether any error occurs or not using error_get_last().
For Example:
// Register shutdown function
register_shutdown_function("shutdownTracker");
// Define all error types you want to catch and handle
define('E_FATAL', E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR);
function shutdownTracker() {
$error = error_get_last(); // This will return empty if no error occurs while executing php code.
if(!empty($error) && ($error['type'] & E_FATAL)) {
// Write your code here to handle you error
}
}
Note: You should include this code on top of your code.
Well if you are talking exceptions, you already have the answer
try{
...
}catch(PDOException $e){
...
}catch(ExpiredException $e){
...
}catch(Exception $e){
echo get_class($e); // get's the class of unrecorded exceptions.
//catches any exceptions missed by the above
}
Now if you are talking about "errors" you can do is use a custom error handler
if(!function_exists('myErrorHandler')){
function myErrorHandler($severity, $message, $file = 'UNKNOWN', $line = 'UNKNOWN')
{
throw new ErrorException(
$message,
1,
$severity,
$file,
$line
);
}
set_error_handler('myErrorHandler');
}
What it does is convert all PHP errors to exceptions or rather to ErrorExceptoins.
Now you can go a step further and use these other two functions.
register_shutdown_function
AND
set_exception_handler
I'm actually working on porting what I use to it's own stand alone github project. Right after I finish my eJinn project, which you may be interested in. eJinn is designed to build exception classes based off a config file, so you can have one error per exception file and unique error codes in a project.
You can catch all exceptions without even call try.
function hello($e)
{
if ($e instanceof PDOException){
echo "something".
}else echo $e->getMessage();
}
set_exception_handler('hello');
this should catch all exceptions.
UPDATE 2
I've edited the code so you know what exceptions will be thrown using get_class();
class mycustomException extends Exception{} // making new exception
function hello($e)
{
if ($e instanceof PDOException){ // exception already known
echo "something";
}else{
echo get_class($e); // get exception name.
}
}
set_exception_handler('hello');
throw new mycustomException(); // throw exception that we made.
I'm studying PHP right now and I'm using w3schools, but when I use the code below my page gets broken (stops from where the code is):
<?php
function myException($exception) {
echo "<b>Exception:</b> " . $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
?>
This code is for creating an exception when no catch block was found.
I tried the others examples in the page and everything works fine. I thought it may be happening because there is no try block, but I'm confused and I don't know how to use it in this situation.
Thanks in advance!
set_exception_handler documentation from php.net:
http://php.net/manual/en/function.set-exception-handler.php
Execution will stop after the exception_handler is called.
Actually the output you are getting is correct.
As stated in W3Schools documentation set_exception_handler() only sets a user-defined function to handle all uncaught exceptions (as in the example you quoted above). So the output should be something like this:
Exception: Uncaught Exception occurred
Please notice the form of exception is what you have defined in your function (myException); which means first it prints the word Exception: and then it prints the reason (message) of exception, in this case Uncaught Exception occurred.
EDIT
As mentioned in the comments the error handler causes the script to stop being executed. To avoid this situation is better always to handle exceptions using try catch blocks.
P.S: I'd suggest you to use better resources other than W3Schools (like the PHP documentations itself) if you are starting to learn PHP.
try this. Hope it helps. If not please let me know.
function myException($exception) {
try {
throw new Exception("Some error message");
} catch(Exception $e) {
echo $e->getMessage();
}
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
I suppose that the exception system of PHP will catch all. but it doesn't.
try{
$obj = new Asdfasdfasdf()
} catch(Exception $e){
trace(...something...)
}
But it doesn't catch this kind of error, and I have searched php document, which didn't say which kind of exception/error is catch-able in try,catch clause.
So, how can I know that which kind of exception/error will be catched by my catch clause ?
P.S.
I finnally understand the 'error' from php engine is not the 'exception' from use land code. If you want use exception to handle engine 'error', you should manually wrap all 'error' in exception.
If you want to throw an Exception in the event that a class does not exist it, you could use class_exists().
A naive example might look something like:
function createClass($class)
{
if (!class_exists($class)) {
throw new Exception(
sprintf('Class %s does not exist', $class)
);
}
return new $class;
}
try {
$asdfasdfasdf = createClass('Asdfasdfasdf');
} catch (Exception $e) {
echo $e->getMessage();
}
From my experience, most PHP frameworks throw some sort of exception when a class is not found - for example, Symfony2 throws a ClassNotFoundException. That said, I don't know if you can 'catch' that, it's probably really just a development aid.
PHP 7 has just been released and from what I understand from the spec, you will be able to catch a fatal error as an EngineException. I don't know if it would work for your example; I haven't tested it because I have not installed PHP 7 stable yet. I tried your example with an alpha release of PHP 7 on an online REPL, and it appears that it does not work.
However for completeness, here's an example from the RFC:
function call_method($obj) {
$obj->method();
}
try {
call_method(null); // oops!
} catch (EngineException $e) {
echo "Exception: {$e->getMessage()}\n";
}
// Exception: Call to a member function method() on a non-object
In any case, as noted by #MarkBaker and #MarcB in the question's comments, you cannot "catch" a fatal error in previous versions of PHP.
Hope this helps :)
I am having an issue where an exception is being thrown but not caught in Module.php. The code that throws the exception is wrapped in a try/catch. There's nothing really fancy going on so I am assuming ZF2 has a quirk and/or reason for not allowing exceptions to be caught here.
The code is as follows (simplified as necessary):
class Module
{
public function onBootstrap(MvcEvent $e)
{
// Get service manager, etc.
// Set up some environment stuff
try {
// exception is thrown
}
catch (\Exception $e) {
echo $e->get_message();
exit;
}
}
}
Why is the exception not being caught?
In an ideal world there would be a way to catch this exception here. But if that is not possible, or is too convoluted to be worth the effort, an alternative process to fetching this data (regardless of source) as early in the page loading process as possible would be appreciated.
meta
I know the code in Module.php is supposed to be lightweight. But we have to fetch some data immediately before any action is performed as it will contain data vital to those actions to be performed. This data is cached after the first visit so every other page load will avoid this overhead.
I also have Googled this but apparently no one else has either experienced this, asked about it, or documented it.
This code works just fine for me in a module class:
public function onBootstrap(MvcEvent $e)
{
try {
// exception is thrown
throw new \Exception('My exception here');
}
catch (\Exception $e) {
echo $e->getMessage();
exit;
}
}
It displays the exception message and exits.
One way to investigate what is happening is to use xdebug for step by step debugging.
Just add a breakpoint in your Module and see what ZF is doing.
Given that I have a custom PHP error handler already, does it make sense to define an exception handler as an "forwarder" like this:
function exception_handler(Exception $e) {
trigger_error($e->getMessage(), E_USER_ERROR);
}
set_exception_handler('exception_handler');
The idea is to utilize the already existing error handler to handle exception too, to avoid repeating the same code. Does triggering an error from inside an exception handler cause some problems?
No problem with it at all. I have the same setup, my error handler emails me with exceptions as well as errors.
Here is my exception handler, I put in the error that I have an uncaught exception. This way I know that it was caused by an exception and not an error. It also will tell me the exception because of the get_class.
function exception_handler(Exception $e) {
trigger_error('Uncaught ' . get_class($e) . ', code: ' . $e->getCode() . "<br/>\n Message: " . htmlentities($e->getMessage()), E_USER_WARNING);
}
Since my error handler sends an HTML email I have html in the exception handler. You may want to remove that.
I've seen errors and exceptions mixed in PHP code before. While technically it shouldn't cause any problems, it will likely create confusion for developers maintaining the code. If you have the time, consider refactoring all your trigger_error code to use exceptions instead. Of course you're stuck with any trigger_error stuff that PHP itself is creating but hopefully you can avoid most of those situations.