I've searched a few questions for a reason my code is not throwing an error correctly, but I can't figure it out.
I have the following function in my controller
<?php
public function suspend($id)
{
try {
$this->collection = $this->class::find($id);
$this->collection->delete();
return $this->respond_with_success();
} catch (\Exception $e) {
return $this->respond_with_error('Failed to suspend resource with id: ' . $id);
}
}
For reference, I'm using soft deletes. I can suspend a resource once no problem. If I try to suspend one that's already suspended, Laravel correctly throws a 500 as I can see in the log file /storage/logs/laravel.log
This is part of the error I see;
local.ERROR: Call to a member function delete() on null....
Without using
withTrashed() in the query, a row quite obviously cannot be found. So this makes sense.
Great...so why does my catch not actually catch anything? I see a 500 error in the browser, but my application should allow me to continue and handle that error correctly. But it just falls over completely...
The respond_with_error function is below. I've tried changing the $code to 200 in testing, but this doesn't change anything. I've tested returning a simple string rather than with this function to no avail, so I don't think there's anything wrong with this part.
<?php
protected function respond_with_error($message = 'error', $code = 500)
{
return Response::json([
'success' => false,
'message' => $message,
], $code);
}
I'm running Laravel 5.6.29
There are two ways to address this. The first thing to note is ERROR: Call to a member function delete() on null is not an exception, it is a fatal error.
You can use findOrFail instead of find to throw an Exception when the model is not found and that will work.
You could also catch Throwable instead of Exception to catch errors and exceptions (as of PHP7) or just Error to catch errors.
As the Error hierarchy does not inherit from Exception, code that uses catch (Exception $e) { ... } blocks to handle uncaught exceptions in PHP 5 will find that these Errors are not caught by these blocks. Either a catch (Error $e) { ... } block or a set_exception_handler() handler is required.
Read more on PHP7 Error Handling here: http://php.net/manual/en/language.errors.php7.php
Related
Here's a simple event loop with a ReactPHP promise:
new React\Http\Server([
function(ServerRequestInterface $request) {
$deferred = new React\Promise\Deferred();
$promise = $deferred->promise();
$deferred->reject(new Response(500));
return $promise;
}
]);
In this case everything works fine and the server returns 500, because the promise was returned and it was rejected.
But how to handle cases like this:
new React\Http\Server([
function(ServerRequestInterface $request) {
$deferred = new React\Promise\Deferred();
$promise = $deferred->promise();
SynTaxErrO..2!((r();
$deferred->reject(new Response(500));
return $promise;
}
]);
The server/loop will still be running, but the connection will be hanging, since a syntax error happened before the promise was returned.
My first assumption was to use try-catch, but it doesn't seem to work in PHP.
try {
SynTaxErrO..2!((r();
} catch($e) {
$deferred->reject(new Response(500));
return $promise;
}
Is there a way to deal with cases like this and still return 500 instead of just hanging and waiting for a promise that was never returned? In real code I have a router function that returns a promise. The promise is never retuned if one of the routes have a syntax error, and thus the connection just hangs. There are no error messages as well.
You cannot catch syntax errors. If there is a syntax error before your catch statement, then execution never reaches your catch and therefore is like it didn't exist. To detect syntax error use a linter (for instance, php -l) before executing your code.
For other kinds of errors, provided you are using PHP 7, then you can use
catch (Error $e) { ... }
or a set_exception_handler() handler to catch errors.
If you want to catch both errors and exceptions, then you can use a block like
catch (Throwable $e) { ... }
If you only want to catch exceptions, use
catch (Exception $e) { ... }
See http://php.net/manual/en/language.errors.php7.php for more info
Hey ReactPHP team member here. Looks like the culput of you issue is SynTaxErrO..2!((r();, PHP can't parse that: https://3v4l.org/02cli
The best solution is not to have any syntax errors. A package that you could use to lint all your files before committing/deploying is: https://github.com/JakubOnderka/PHP-Parallel-Lint
I want to set a custom message to be displayed to the user when I throw an error in Laravel 5.1. For example, in a controller I might have:
if(!has_access()){
abort('401', 'please contact support to gain access to this item.');
}
Then my custom error page I would display the error with:
$exception->getMessage();
However, what if there was a SQL error or other event? Wouldn't that also set the Exception Message which I would be unknowingly outputting on my error page?
The PHP docs for getMessage() don't go into much detail about this.
How can I set a specific exception message without introducing any security risk?
However, what if there was a SQL error or other event? Wouldn't that also set the Exception Message which I would be unknowingly outputting on my error page?
Potentially, yes. PHP makes no guarantees that the contents of exception messages will be "safe" to display to users, and it's quite likely that some classes will throw exceptions which include sensitive information in the message.
If you want to use exceptions to display errors to users, use a specific subclass of Exception for those exceptions, and only print the message if the exception was an instance of that subclass, e.g.
class UserVisibleException extends Exception {
// You don't need any code in here, but you could add a custom constructor
// if you wanted to.
}
// Then, in your abort() function...
throw new UserVisibleException($message);
// Then, in your exception handler...
if ($exc instanceof UserVisibleException) {
print $exc->getMessage();
} else {
print "An internal error occurred.";
}
If you access your app.php file:
'debug' => env('APP_DEBUG', false),
In your production env, set this to false. This would make sure that no debug errors would be displayed in the production environment.
Once this is set, you can respond to normal exceptions through your controller. Anything else, laravel wouldn't display the error page.
Yes,
$e->getMessage() can potentially reveal more information about your code IF you use it in a similar way:
try {
$executeSomethingHereForWhichYouExpectAnException();
// Basic \Exception that reports everything
} catch (\Exception $e) {
$error = $e->getMessage();
}
even with 'debug' => false in app.php. For example if you have an error with your code $error would display it - basically ANY type of error (PHP,MYSQL,ETC);
However, there is a fix - to catch your CustomException messages and prevent typical error displaying if you use it in like so:
try {
$executeSomethingHereForWhichYouExpectAnException();
// Our custom exception that throws only the messages we want
} catch (\CustomException $e) {
// Would contain only 'my_custom_message_here'
$error = $e->getMessage();
}
What is the difference you may ask - the difference is that instead of \Exception which is the basic error reporting, we use \CustomException class, which you throw from $executeSomethingHereForWhichYouExpectAnException() function:
executeSomethingHereForWhichYouExpectAnException(){
if (something) {
throw new CustomException("my_custom_message_here", 1);
}
}
If you have more exceptions you can include them like so (as of PHP7.1):
try {
something();
} catch(\CustomException | \SecondCustomException $e) {
// custom exceptions
} catch(\Exception $e) {
// basic exception containing everything
}
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 was just wondering something. In index.php, I am currently doing something like this
function performFtpOperation() {
global $config;
try {
$ftp = new FTP\FtpClient();
$ftp->connect($config::FTP_SERVER);
$ftp->login($config::FTP_USER, $config::FTP_PASSWORD);
} catch (Exception $e) {
echo 'Error: ', $e->getMessage();
}
}
What I was wondering is if that try catch block is needed? Reason I question it is because my FTP class throws errors if something goes wrong. For instance this is the connect function
public function connect($host, $ssl = false, $port = 21, $timeout = 90)
{
if ($ssl) {
$this->conn = #$this->ftp->ssl_connect($host, $port, $timeout);
} else {
$this->conn = #$this->ftp->connect($host, $port, $timeout);
}
if (!$this->conn) {
throw new Exception('Unable to connect');
}
return $this;
}
So would a try/catch be needed if errors are handled within the class?
Thanks
When an exception is thrown, the code following it will not be executed, and PHP will try to find the matching "catch" block.
If an exception is not caught, a fatal error will be issued with an "Uncaught Exception" message.
Proper exception code should include:
Try - A function using an exception should be in a "try" block. If the exception does not trigger, the code will continue as normal. However if the exception triggers, an exception is "thrown"
Throw - This is how you trigger an exception. Each "throw" must have at least one "catch"
Catch - A "catch" block retrieves an exception and creates an object containing the exception information
The connect class throws exceptions that you need to catch and handle somewhere in your code. It is up to you where to handle it depending on your application design and requirements.
If you decided that you wanted to handle them in the performFtpOperation function, then your use of try...catch there is correct.
If you don't handle them in the performFtpOperation function, then they will bubble up to the code that calls the performFtpOperation function and you can catch & handle them there if you like using try...catch similar to how you did it here. Just remember that you need to catch them somewhere.
Well since you are throwing an exception from within your FTP code, then Yes.
You need to try catch if you work with exeptions, otherwise you generate fatal errors and your script/site will stop work at this point, so try/catch is a part of the exeption handling.
you can inform yourself about this in the php manual
http://php.net/manual/en/language.exceptions.php
I am new in zendframework. I am using apigility for rest services and ApiProblemListner to return the response if any error occures.
I have one function in model and this function just through an exception using php exception to use in catch block
I am using model function as the utility function in controller to catch those Exception. While catching exception I am using as
try{
imageUploade(); // this function in model and throwing exception if any error
}catch(\Exception $e){
return new ApiProblemResponse(new ApiProblem(500 , $e->getMessage()));
}
if imageUploade() throw an exception if the image size is more then I am able to catch the exception in catch block. I tried echo $e->getMessage(); and its printing the exception bt if I use new ApiProblem(500 , $e->getMessage()) it is not retuning the json error response with the 500 message. It is returning nothing. even it is not showing any error.
Seems like it is unable to render the error with this class. I am not sure if any event needs to add.
I have tried to search for documents but unable to find it.
Thanks in advance.
Normally it should work if you return an ApiProblemResponse straight from a controller action.
Are you sure your Api-Problem module is active?
Try once like this:
<?php
Application\Namespace;
use ZF\ApiProblem\ApiProblem;
use ZF\ApiProblem\ApiProblemResponse;
class IndexController
{
/**
* #return ApiProblemResponse
*/
public function indexAction()
{
return new ApiProblemResponse(new ApiProblem(500, 'test'));
}
}
If that doesn't work then I think your Api-Problem module is not running or the exception is never caught.