CodeIgniter Forums
Exceptions exceptions... - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: CodeIgniter 4 (https://forum.codeigniter.com/forumdisplay.php?fid=28)
+--- Forum: CodeIgniter 4 Support (https://forum.codeigniter.com/forumdisplay.php?fid=30)
+--- Thread: Exceptions exceptions... (/showthread.php?tid=76158)



Exceptions exceptions... - Gary - 04-17-2020

Hi,

The CI framework throws a variety of exceptions… many of them are difficult (or perhaps just inconvenient) to place within a try-catch block.

Is there some easy way to be able to intercept these in a more generic way at the final output stage so that every occurrence of an exception is gracefully handled (perhaps with a generic response), even in the case of an exception being thrown somewhere where it’s not anticipated?

Some of the reason for this is that if one is using CSRF tokens that are updated on every submission, a single system-generated response will throw the server/client out of sync and break the website (or cause the client to be unnecessarily booted).

I’ve read though everything I can find in the CI user documentation on Error Handling, Using Exceptions, Custom Exceptions and Replacing Common Functions, and have even considered to use Events… as best I can tell, only way this can (sensibly) be done is by changing/extending the Core System Class:  CodeIgniter\HTTP\Response.  However, being a noob, I take note of the warning that is on ALL of the relevant documentation pages: “Messing with a core system class has a lot of implications, so make sure you know what you are doing before attempting it”

Any advice would be appreciated, thanks.

As an aside, I started off trying to configure Apache's config: with ErrorDocument 500 "Cutom 500" (as a global, then a virtual host, and also as a directory option, as well as in .htaccess)... and that seems to get totally ignored, which is why I packed up on the idea of doing it this way.


RE: Exceptions exceptions... - Leo - 04-19-2020

Hi Gary,
Any progress? I've just encountered same issue in my project.


Details: A user downloads an image from some website that is labeled with a .jpeg extension. It is actually a .heic image (if microsoft paint is to be trusted) and I get an exception during attempted upload. Instead, when this happens, I want to display an info message: "This image type is unsupported/image has additional copyright measures added. You may try and open it in ms paint and re-save it as .jpeg (works 100%)". Instead I get throw ImageException::forInvalidImageCreate('Ima'); in GDHandler.php

So far solved like this:
PHP Code:
try {
     
//my library function for image uploading, editing
     $new_images $simpleImg->upload();
} catch (\
CodeIgniter\Images\Exceptions\ImageException $e) {
     session()->setFlashdata('message',
'This image type is unsupported/image has additional copyright measures added. You may try and open it in ms paint and re-save it as .jpeg (works 100%)');


This code catches ALL exceptions within \CodeIgniter\Images\Exceptions\ImageException
How do I display my own message exactly for forInvalidImageCreate?


RE: Exceptions exceptions... - Gary - 04-19-2020

Hey Leo,

I suspect simply checking if $e is that particularly type of exception inside your catch block, and then returning your Flashdata message if it is (look in \system\\CodeIgniter\Images\Exceptions\ImageException.php for all of the CI system image exception types), and also follow this check with a rethrow of the exception if it's not of your Images.unsupportedImageCreate exception... may work.

Depending on how you've done your validation, I suspect you could also push a message into the validation error array (instead of using Flashdata), so that it'll show up like any of the other- more automated- existing validation checks using something like this:

Code:
$validation->setError('field_name_where_error_will_show', 'custom_message_and_user_insults_here');    // see \system\Validation\Validation.php for setError() details



RE: Exceptions exceptions... - Leo - 04-20-2020

PHP Code:
try {
    $new_images $simpleImg->upload();
} catch (
ImageException $e) {
    if(substr($e066) === 'CodeIgniter\Images\Exceptions\ImageException: Your server does not') {
          $validation->setError('img_path'lang('mixed.imageException', [], 'custom'));
    }



Thanks for the tip with validation. It is now a lot easier to read than a flash message, along with other possible errors.


RE: Exceptions exceptions... - Gary - 04-20-2020

That looks like it'll work... to be rigorously correct, it should also have a re-throw of any other exception below your mixed.imageException check.


RE: Exceptions exceptions... - Leo - 04-20-2020

No its not working. I've been hacking at it for a while but I can't get the picture error to display with other errors. I get other form field errors showing fine, but not my custom one, not showing at all.

PHP Code:
        $model = new ProductsModel();
        $validation Services::validation();
        $validation->setRules($model->validationRules);

        if(isset($_POST['submit'])) {

            $validation->withRequest($this->request)->run();

            //check image
            if(isset($_FILES['img_path'])) {
                $upload_config = (object)[
                    'width' => 280,
                    'height' => 200,
                    'dir' => WRITEPATH.'uploads',
                    'name' => 'img_path',
                    'multiple' => false,
                    'fit_or_cover' => 'cover',
                    'crop' => true,
                    'keepName' => false,
                    'returnOnlyFileName' => true
                
];
                $simpleImg = new SimpleImg($upload_config);
                try {
                    $new_images $simpleImg->upload();
                } catch (ImageException $e) {
                    //forInvalidImageCreate
                    if(substr($e066) === 'CodeIgniter\Images\Exceptions\ImageException: Your server does not') {
                        $validation->withRequest($this->request)->setError('img_path'lang('mixed.imageException', [], 'custom'));
                    }
                }
            }



And 
in my view file I have this:

$errors = \Config\Services::validation()->listErrors() ?? null;
echo 
$errors



RE: Exceptions exceptions... - Gary - 04-20-2020

Did you try it with only TWO parameters, as what the framework's function definition appears to call for?

As in:
$validation->setError('field_name_where_error_will_show', 'custom_message_and_user_insults_here');

As an aside, using setError will overwrite any existing error messages in previous validation calls... and is purely intended as an easy way to inject error messages into the program flow to use one's existing error display. So, without my having followed though/checked what's happening in the framework validation code, to be safe, it is best applied as the last validation-related call in the controller before the error display is invoked in the view.

Looking at your code, it looks like if the imageException is called, it will overwrite all of the other validations... it probably needs to be done in two steps (because of this overwriting, not appending to):
1) general validation of the upload -> display these validation errors in the view
2) once general validation all clear, process the file -> catch these exceptions -> use setError to inject these into the validation error message array -> display validation errors (which now contains the injected message) in the view


RE: Exceptions exceptions... - Leo - 04-20-2020

I figured it out. It was a very dumb mistake on my part. I develop in English, with my comments, etc. in English. But I make Russian websites. So when I switched language in app/config - back to english - EVERYTHING WORKED AS EXPECTED.

However this mistake brought me back to my comment from 9 hours ago.

if(substr($e, 0, 66) === 'CodeIgniter\Images\Exceptions\ImageException: Your server does not') {
          $validation->setError('img_path', lang('mixed.imageException', [], 'custom'));
}

This solution is flawed. I shouldn't match my exception with string contained in $e...I somehow have to figure out another way to figure out if its an exception from forInvalidImageCreate. For now, I'll just have to check for string in English and Russian until I figure out an easier way to catch/figure out exceptions.

UPDATE: solution:
PHP Code:
try {
     $new_images $simpleImg->upload();
} catch (
ImageException $e) {
     //forInvalidImageCreate
     if(strpos($elang('Images.unsupportedImageCreate'))) {
          $validation->setError('img_path'lang('mixed.imageException', [], 'custom'));
     }




RE: Exceptions exceptions... - Gary - 04-20-2020

And using only the portion that won't change: if(substr($e, 0, 45) === 'CodeIgniter\Images\Exceptions\ImageException:') {... ?