PHP system/user error handling

I am working on a custom MVC inspired framework, mainly for learning purposes, and have gotten to the point where I need to create a better error handling class, I currently have a temp one just so i can see the errors better and save them to the database.

I have been reading about this subject for a few days now and need some clarification.

The errors i want to track are:

  1. System errors - if there is a problem with the actual code of the framework/app
  2. User input errors - forms for example, if they entered wrong information, or no information in required fields

What i want to do with the errors:

  1. Save them to the error log
  2. Save them to the database to an errors table
  3. Display certain errors to the users and developers (for forms for example, or if they clicked a button that failed, they should see an alert/error message) based on a debug mode settings
  4. Show form input errors, if a user didn’t enter the correct data in to a form input, i want that input error to be saved so that i can display the correct error next to the correct input

My current error handling:
Not much to say here i think as it was just temporary, but what i have is really simple and poor class that i wrote just to be able to see the errors in a better way. I have been testing different things in it also so its not really working as it should. But basically the way i have it is like this:
setError() is the main function that is used, it receives the error lever and the error message, this function then sends it to another function that saves the error in the session and in the db and to another function that sends an email about the error.
I also have another function that saves input errors, for example, if a user submitted an input with too many chars, an error is set for that input and is saved in the session, so when the user returns to that form (either through reload or ajax), i can get the input errors and show a message by the input.
There are a few more functions but that’s basically what i have at the moment, i’m trying to create a “real” error handler class now, so the current class doesn’t really matter to me.

My questions:

  1. How should i implement this in an MVC type framework, i would think that i could set the set_error_handler() function to use my custom ErrorHandler() class before the framework initiates (before calling the routers and everything), and then any errors saved will use that class, is this correct?
  2. How should i track user input errors? If i have a form input that should be an email address, and the user enters something that is not an email or the email is already taken or any other form input error, should i use trigger_error for it? What error code should i give it?
  3. I haven’t fully understood where i should be using try, catch, and throw. What i do at the moment is use if statements where ever i think there could be an error. For example, if i try to insert data in to a table and it fails, i return false to which ever controller asked for this, and that controller would set an error (in my current temporary error handler) and save it without using try, throw, or anything like that, it would use a function i wrote called setError(), and this would save it to the database and session for showing the users a message.

I don’t think you should be conflating system errors with form errors. Form errors are basically user errors. Trying to have one approach that handles what are basically unrelated things will probably not end well.

For what you call system errors, just toss an exception and then catch it using application level try/catch block.

# app.php
$request = new Request();
try {
    $response = process_request($request);
}
catch (Exception $e) {
    // do your logging or whatever
    exit();
}
$response->send();

I would avoid trying to use trigger errors for this sort of stuff. Exceptions tend to be cleaner and should be thrown when a problem is encountered. Your database insert should trigger an exception when it fails. Your controller never even needs to know about it. And think about it. What exactly could a controller do if the insert fails?

As far as forms go, I would have a validator which basically check each input and makes a list of errors encountered. These error would in turn eventually be displayed back to the user. No real need to log if a user incorrectly fills out a form field. Maybe take a look at how Symfony does things for ideas.

By this you mean to just have that one try/catch on the application level, and then in the actual controllers and models to throw exceptions?

Why is that? I couldn’t really see a benefit from using one over the other when i was reading about it.

None of my models set errors, they only receive requests from controllers and return the results. If a controller requests data from a model and receives false, it will set an error or possibly do another functionality that could request something else from a model.

So basically your saying that system errors and form errors are two different things and that they
should not be handled by the same class?

Also, what about showing the users an alert message?
If i do set these two things up as separate classes, in the end i want to show alerts to users, should i create an additional class for alerts?

You should pack your errors handling in specific class and start it before request processing begins.

Errors handling cathes development errors only. Invalid user data is not the case.

If you assume that some data or result should be not valid, use exception. Error handling is for situations, where error has not assumed.

I don’t fully understand what you mean

Are you saying to do what ahundiak suggested, which is to do a try/catch on the response request?

I don’t understand what you mean by the reset of your post

Are you saying to do what ahundiak suggested, which is to do a try/catch on the response request?

No.

I don’t understand what you mean by the reset of your post

What exactly?

ok, then i don`t really understand what you meant.

Then does this mean that i should just have a class for error handling that should be instantiated before the app gets started?

What is the actual difference then? Should error handling be for system/coding error only, or also for, for example, a user lands on a page they are not suppose to be on, is that not considered also a type of error? I guess i need to know first what actually counts as an error, and then how they should be handled.

I don`t understand this part.

Then does this mean that i should just have a class for error handling that should be instantiated before the app gets started?

Yes. Hm… Before rest app gets started.

What is the actual difference then?

Invalid request - is not error of your application. Request should be validated with validators, and if errors found, application will send validation error messages back to client.

I don`t understand this part.

Exception…

class Collection
{
    private $items = [];

    public function has($key)
    {
          return isset($this->items[$key]);
    }

    public function get($key)
    {
        if (!$this->has($key)) {
             throw new \Exception('Key not found: ' . $key);
        }

        return $this->items[$key];
    }

    public function getOptional($key, $defaultValue = null)
    {
        try {
            $result = $this->get($key);
        } catch (\Exception $e) {
            $result = $defaultValue;
        }

        return $result;
    }

Error…

public function set(SomethingInterface $something)

If by execution of your code $something will be not instance of SomethingInterface, that fires error. This error should be catched with your error handler, and your error handler should to show you complete backtracing for this error.

1 Like

ok now i’m understanding it better, so:

Ok, before i actually run the application, the request and router and anything that could produce an error, i should instantiate the error handler class, and it will handle all of the errors, right?

Also, if there is an error like this, should the handler send the users to a 404 page or an error page of some sort?

In this code you wrote, what would actually be happening with that exception?
throw new \Exception('Key not found: ' . $key); - does this product an error or show an alert?
I do this but i just don’t throw anything, in this exact case i would just do an if statement, and if it failed, i would return false, so why would throwing an exception be preferred?

Ok, before i actually run the application, the request and router and anything that could produce an error, i should instantiate the error handler class, and it will handle all of the errors, right?

Yes.

Also, if there is an error like this, should the handler send the users to a 404 page or an error page of some sort?

No. Errors must be fixed. They are not the part of application life cycle.

does this product an error or show an alert?

Without catch just backtracing will shown. But you should catch this exception in your application and e.g. send 500 or 404 back to client.

so why would throwing an exception be preferred?

Due correct development style. Your method should to get data of some type. If it returns either $something or false, potentially that is source of problems.

Right, but what about if its production? What should the users see in that case, or how should the app continue once an error occurs?

So exceptions should show a 500 or 404 page?

In production user should to see nothing or 500 e.g. with proposition to send email to resource admin.

So exceptions should show a 500 or 404 page?

On your decision for concrete usecase. There is no common rule about.

Ok, so this is what i understand until now, hope its correct :sweat_smile:

  1. For production: if there is a framework/code error, the user should see a 500 error page
  2. For production: if there is an exception, the user could see a 500 page (no common rule about this)
  3. In development: if there is an error, it should always be shown in someway and fixed
  4. User actions should be validated separately from the error and exception handling.

I still have these questions:

  1. For development environment, what should be done with exceptions? Are these things that should be fixed, should they be ignored?
  2. Should exceptions be tracked in someway?
  3. Is there a common way to show users alerts for error/invalid user input? i would think that i should maybe create a new class for alerts, and when ever there is an invalid user input or an error of some sort, i would add an alert and use that class to handle them/show them.

User actions should be validated separately from the error and exception handling.

From error only. Exceptions could be used. E.g. user calls some product profile site with product id. Product with this id didn’t exists. Somewhere in your code will be produced exception. This exception will be catched, and user receives 404 with exception message.

But this is just a variant.

For development environment, what should be done with exceptions? Are these things that should be fixed, should they be ignored?

It depends. Some of them should be fixed. In example above exception is part of your functionality.

Should exceptions be tracked in someway?

PHP Exceptions show backtracing. If you need something more than standard, use exception handler.

Is there a common way to show users alerts for error/invalid user input?

No. It could be inexistent entity or invalid data or failed CSRF check… In any concrete case a proper processing should be used.

So basically, exceptions are the in between of errors and invalid user input, and depending on the case, should either be fixed or not. If its a functionality exception, then its just part of the script, if its an “error” exception then it should be fixed?

yes, i meant if they should be saved to the database or a file to be tracked?

I meant, after already validating user input, and knowing what is not valid, how should we tell the user that they have made a mistake or that a mistake has been made? Should there be an alerts class to inform them?

There are several things at play here:

  1. A mistake in the code (a bug) that needs to be logged for a developer to look at and fix it
  2. A user filling in a form and making mistakes

The first one is (usually / hopefully) unexpected, or exceptional, and warrants throwing exceptions which can then be caught somewhere else.

The second part is completely expected because users fill in forms incorrectly all the time. If they didn’t we wouldn’t have to build any tooling around it :wink:

Normally, you’d log / email / whatever errors of the first kind, and handle errors of the second kind completely differently, exactly because they are to be expected.

Depending on how far you want to go with this you could return an array with errors from the controller, or create a full blown form framework with classes that can hold errors and render them etc like Symfony does.

Something like… But it is very philosophic term.:grinning:

yes, i meant if they should be saved to the database or a file to be tracked?

In some special case, probably…

I meant, after already validating user input, and knowing what is not valid, how should we tell the user that they have made a mistake or that a mistake has been made? Should there be an alerts class to inform them?

As I said, it depends of mistake’s kind and your own code concept. E.g. if you have invalid form data, you just should to show this form with invalid controls and error messages - above or near the any control. And I think, special class for it doesn’t required.

1 Like

so, if i already have a form class that handles the forms, i could store form errors in it. But then what, how would i display those errors to the user? I could just get an array from that class and show the user, but there are also other alerts to show users, for example, if they click on a button to go to a page or load something, and the response produces an error, instead of them clicking the button and not knowing whats going on, i want to show them an alert.
So i think its a matter of combining those two, showing the form input error alerts, and showing the code error alerts. This is why im thinking of creating an alerts class that will get the alerts from the different locations, and display them to the user.
Is there a common way of handling this, or is my idea actually ok?

Right, so i would have an error handling class, that would handle errors, and another class, a form class that would handle user form errors.
I’m still not too sure about how to handle the exceptions though, when i should use exceptions and when not to.

Also, there is also the trigger_error() function, when would i use that and when would i use exceptions?

I would think that maybe for the exceptions that SHOULD be saved an fixed, i could use trigger_error instead of exception? That way it will be treated as an error, and logged so that it can be fixed?

Also, in regards to forms, i send a form token with all forms to valid the forms, and if the form token is not present in the handling of the form, or the token is wrong, then it produces an error. What kind of error would this be, an error, an exception, a user input?

I would think that maybe for the exceptions that SHOULD be saved an fixed, i could use trigger_error instead of exception? That way it will be treated as an error, and logged so that it can be fixed?

It could be. But you should to understand, that ability to catch it will be losed. If this ok, why not.