Here is the part of my code:
// ... code ...
$action = self::defineAction( $request->getPath() );
try {
$response = Controller::$action( $request );
} catch( \BadMethodCallException $exception ) {
Logger::logError( $exception );
$response = new NotFoundResponse();
}
// ... code ...
I try to catch an exception if by some accident the action of the controller with the defined name is not implemented or if the name is defined wrongly.
But instead of catching exception I get Fatal Error in Apache's error log:
PHP Fatal error: Call to undefined method app\\Controller::testingAction() ...
If I try to call an undefined method inside the existing (defined and callable) action of the controller, I also can't catch the aforementioned exception - the Fatal Error occurs instead:
PHP Fatal error: Call to undefined method app\\SomeClass::someUndefinedMethod() in /********/Controller.php on line *** ...
Replacing the "\BadMethodCallException" by the "\Exception" has no effect: I'm keeping get the Fatal Errors.
Putting the "try-catch" block inside the every action of the controller is not the acceptable solution for me.
Why the exception can't be caught this way? How can I solve this problem?
I'm running PHP 5.3.8.
Catch blocks can only catch thrown exceptions, not errors. Call to undefined method is an error and you will need to test for this and throw an exception yourself. Please see this for differences between exceptions and errors.
You can test whether a method exists by doing something like this:
if( !method_exists('app\Controller', 'testingAction') ) {
throw new \BadMethodCallException();
}
Related
I'm handling some PHP errors during an Ajax call and I get the following message in Chrome Console:
An uncaught Exception was encountered
Type: Error
Message: Call to undefined function data()
Filename: /var/www/application/models/M_ajax.php
Line Number: 604
Backtrace:
File: /var/www/application/controllers/Global_fxns.php
Line: 47
Function: _4___signIn
File: /var/www/html/index.php
Line: 349
Function: require_once
The thing is, its inside a try/catch block. And PHP errors should be caught. For example, if i execute this code inside the try block
strlen();
The code is caught as you would expect, as strlen expects a parameter. But this error is not caught. The line of code that is triggering the error is
if ( ! $this->M_account->addUserTrafficEvent( $userId, data('Y-m-d >H:i:s'), 2.1, '' ) ) {
And it's an error because I meant to type 'date' instead of 'data' to use PHP's date function, and because 'data' is not a function its creating an error. Why isn't this error being caught? Is there some kind of difference between errors created with PHP functions and user-defined functions, and if so shouldn't it still be caught? It's generating a PHP error message after-all
Thanks
From PHP 7 you can use catch(Error $err).
<?php
try {
data('Y-m-d >H:i:s');
} catch (Exception $exc) {
echo 'Fatal exception caught: '.$exc->getMessage();
} catch (Error $err) {
echo 'Fatal error caught: '.$err->getMessage();
}
?>
Checkout the Fiddle I've made for you
I am using Twig 1.28.2 and I have the following issue:
in production mode (debug=false, strict_variables=false), twig just ignores undefined vars within templates.
in devel mode, twig throws a Twig_Error_Runtime exception, which stops rendering of the page unless I catch the exception somewhere.
I would like to get a notice thrown just like PHP does with undefined php variables, so I could log those notices in both devel and production modes for analyzing later.
I could define an exception handler for Twig_Error_Runtime, but this type of exception is thrown in many other contexts, not only undefined vars. So it's probably not the best idea to catch this exception and continue executing code.
I looked into twig code, and it doesn't look very promissing:
final protected function getContext($context, $item, $ignoreStrictCheck = false)
{
if (!array_key_exists($item, $context)) {
if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
return;
}
throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist.', $item), -1, $this->getTemplateName());
}
return $context[$item];
}
Any ideas how to solve this?
So if a function produces a warning/notice we get the LINE within the function.
I could validate before, during AND/OR after the function call but I am curious is there a way to AUTOMATICALLY be given the error producing LINE_ of the function call that called the function?
You need to use a try catch statement like this:
try{
//your code that errors here
}catch(Exception $e){
echo "Line number:" . $e->getLine();
//you could throw the exception here again
//throw $e;
//or create a new exception and throw that with the data you supply
//$newException = new Exception('New message goes here', 'exception code goes here');
//then throw it
//throw $newException;
exit;
}
Here is the link to the docs:
http://php.net/manual/en/exception.getline.php
You might also be interested in these methods (amongst others) that also belong to the Exception class:
getMessage
getCode
getFile
getMessage
As per your comment and creating a new exception check out the Exception class here:
http://php.net/manual/en/class.exception.php
Use a PHP IDE with a debugger and set breakpoints, watch the call stack.
How do I catch this type of error?
ContextErrorException: Catchable Fatal Error: Argument 1 passed to AA\SomeBundle\Entity\SomeEntity::setCity() must be an instance of AA\SomeBundle\Entity\City, null given, called in /srv/dev/some_path/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php on line 360 and defined in /srv/dev/some_path/src/AA/SomeBundle/Entity/SomeEntity.php line 788
And I am trying to catch everything like that:
$form = $this->createForm(new SomeFormType(), $instanceOfSomeEntity);
try {
$form->handleRequest($request);
} catch (\Exception $e) {
$form->addError(new FormError('missing_information'));
}
The easiest way to fix this is to prefix the offending code with the # symbol, so any warnings are suppressed. Any errors should then be caught in the try...catch.
Not ideal as # has non-trivial performance implications, but otherwise, you're looking at perhaps replacing the error handling or in my case, when reading from XML, checking the existence of every tag before trying to get the value.
This is my code, fixed by adding the '#'
try {
$value = #$this->XML->StructuredXMLResume->ContactInfo->ContactMethod->PostalAddress->DeliveryAddress->AddressLine;
} catch (\Exception $e) {
$value = '';
}
As you can imagine, checking every level down to AddressLine would be ridiculous.
You have to disable the error reporting and catch the last error with error_get_last() function, here an example, from the Symfony Finder component : https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Finder/SplFileInfo.php#L65
The other way is to create a custom error handler, here an example from Monolog : https://github.com/Seldaek/monolog/blob/master/src/Monolog/ErrorHandler.php
The entry point (front controller) for our software is wrapped in a try catch block which catches exceptions and then includes a PHP file to show a friendly error page, as well as emailing us about the exception. This work perfectly, however it misses PHP fatal errors which just show a HTTP 500 response. I'm trying to catch those errors in the same way as exceptions.
At the moment, we have this in the application's entry point:
try {
// Register a shutdown handler for fatal errors
register_shutdown_function(function() {
$error = error_get_last();
// Did this request throw an error that wasn't handled?
if ($error !== null) {
throw new Exception('PHP fatal error!');
}
});
// ...normal front controller stuff
} catch (Exception $e) {
// show fancy error screen with debug information
include 'themes/error/500.php';
}
Here, I'm throwing an exception when PHP throws a fatal error in the hopes that it gets handled by the normal exception handling procedure. However, the exception never gets caught:
Fatal error: Uncaught exception 'Exception' with message 'PHP fatal error!'
How can I achieve what I want to do here?
You should not use register_shutdown_function() for that - it makes no sense since you're already at stage when script is exiting. PHP allow you to handle errors via set_error_handler() function.
But note, you can not handle fatal errors with that (such as calling undefined functions) - and, of cause, parse error as well:
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.