WEBVTT

00:00.350 --> 00:00.950
Okay guys.

00:00.950 --> 00:06.950
So let's do a throwback to when we implemented error handling in the first project.

00:07.100 --> 00:12.860
So a quick reminder of how the errors work in PHP.

00:13.280 --> 00:17.810
Now obviously you are talking about that because this video is about error handling.

00:19.190 --> 00:23.270
So in PHP you've got two kinds of errors.

00:23.480 --> 00:33.230
One is when there is an error that is not an exception, and the other is when there is a thrown exception

00:33.230 --> 00:36.410
that is unhandled anywhere else.

00:36.650 --> 00:44.420
Now this exists for legacy reasons because before exceptions you only had errors.

00:44.420 --> 00:51.440
So to handle errors or to customize the way it's handled, which you typically would like to do, and

00:51.440 --> 00:59.060
all the PHP frameworks do that, you need to register two functions or two callbacks.

00:59.480 --> 01:04.850
That would be one for handling exceptions and one for handling errors.

01:04.850 --> 01:08.690
And this would be what I'd like to do in this video.

01:08.720 --> 01:14.180
At least I'd like to begin, because we're gonna make it a little bit more better.

01:14.180 --> 01:23.840
So, uh, to just get straight to the point, we'd like to create an error handler class that will handle

01:23.870 --> 01:31.730
both the exceptions and errors, but also will recognize whether we are currently running inside the

01:31.730 --> 01:35.330
web server environment or inside the command line.

01:35.330 --> 01:36.320
Why is that?

01:36.320 --> 01:43.820
Because on the web server, you'd like to display an error page with different amount of information

01:43.820 --> 01:53.120
depending if we are in a debug mode or production mode, and in the command line you'd like to display

01:53.120 --> 02:02.160
the error message in the command line, you would not like to render a page, and additionally on top

02:02.160 --> 02:02.760
of that.

02:02.760 --> 02:11.220
In all cases, we'd like to log something to the error log, and this time we won't be logging everything

02:11.220 --> 02:14.760
directly to the CLI output.

02:14.790 --> 02:22.020
We'd like to store the error logs to a file so that it can be later reviewed.

02:22.050 --> 02:30.570
Okay, so without further ado, let's jump into implementing this in our current project.

02:31.860 --> 02:36.120
So let me begin with creating the new file.

02:36.240 --> 02:38.460
Now that's a core feature.

02:38.460 --> 02:42.810
So we are creating a file inside the core namespace.

02:43.560 --> 02:46.680
This would be called error handler.

02:47.700 --> 02:51.840
And it's going to be handling all types of errors.

02:51.870 --> 02:57.300
Now let's define the core namespace and the class name.

02:57.300 --> 02:59.700
That's an error handler.

02:59.700 --> 03:03.570
So the most generic Function that we need.

03:03.570 --> 03:07.170
Here is the handle exception one.

03:07.290 --> 03:09.600
Now you're going to see why.

03:09.630 --> 03:12.900
So I've said that we need to handle both.

03:12.930 --> 03:17.310
Exceptions and errors that are not exceptions.

03:17.670 --> 03:27.660
But we can do a simple trick so that everything goes through this single handle exception method.

03:27.720 --> 03:36.660
It accepts an argument of type throwable, which is something more generic than an exception.

03:37.710 --> 03:39.900
This is an exception.

03:40.620 --> 03:42.930
And let me add another one.

03:42.930 --> 03:47.730
So this would be public static function.

03:50.010 --> 03:51.720
Handle error.

03:52.350 --> 04:00.090
Now this needs some specific attributes like the error level the message the file.

04:00.090 --> 04:03.610
It happened in and on which line.

04:04.420 --> 04:05.140
Okay.

04:05.140 --> 04:10.390
So we're going to use this method to register non exception errors handling.

04:10.390 --> 04:19.270
But what I'm going to do here is I'm just going to create a new error exception.

04:19.570 --> 04:24.130
And I'm just going to pass all those parameters to it.

04:24.130 --> 04:27.580
So this would be a message.

04:29.320 --> 04:32.410
Let's just set the default code of zero.

04:32.440 --> 04:34.090
Then we're going to pass the level.

04:34.120 --> 04:41.650
As you can see I'm just passing exactly the parameters that the constructor of this exception expects.

04:42.070 --> 04:44.860
So there is also the file name.

04:45.070 --> 04:54.160
And the last is the line exactly as the parameters on this exception okay.

04:54.190 --> 04:56.620
So I'm creating a new exception.

04:56.620 --> 05:03.640
And instead of throwing it I just call handle Exception.

05:03.640 --> 05:05.590
Passing the exception.

05:06.970 --> 05:14.620
That way, this is the only place where we need to implement the actual logic of what needs to happen

05:14.620 --> 05:17.260
with any kind of errors.

05:20.440 --> 05:26.020
So what needs to happen here is first we need to log the error.

05:28.120 --> 05:35.710
And this means just log it to whatever is configured as the current logger, whether this is the output

05:35.710 --> 05:39.280
directly in the terminal or stored in a file.

05:39.640 --> 05:41.260
We're going to be handling that later.

05:41.260 --> 05:46.450
And next step is to see what environment we are currently in.

05:46.570 --> 05:53.200
So in PHP there is a function called PHP sub name.

05:53.830 --> 06:00.700
If this is CLI this means we are in a command line environment.

06:00.700 --> 06:07.990
And this would not include a up will be built in server which you start through command line.

06:08.500 --> 06:19.390
This only means scripts that are being run directly when you type, like in our case we do PHP binary.

06:19.420 --> 06:30.700
Let's say load schema PHP and if that's the case we're gonna call a method.

06:30.730 --> 06:32.590
Or maybe I can use just static.

06:32.590 --> 06:39.730
And this would be render CLI error passing the exception.

06:40.420 --> 06:48.400
Otherwise it means we have a server error on a web server, which means we need to render an error page

06:48.760 --> 06:50.740
which we also pass the exception.

06:50.770 --> 06:53.770
Now obviously those methods don't exist.

06:53.800 --> 06:55.930
We're gonna implement them next.

06:58.750 --> 06:59.140
Okay.

06:59.140 --> 07:04.580
Next thing I'd like us to work on is formatting of the error message.

07:05.030 --> 07:07.190
For that, let's define a private.

07:07.220 --> 07:13.790
Private static method that will be called format error message.

07:14.240 --> 07:25.280
And this one responsibility is to convert the exception into a string with an error message with the

07:25.310 --> 07:26.690
given format.

07:27.020 --> 07:33.560
And this will be used both to output the error on the CLI and on the website.

07:33.590 --> 07:44.360
And this accepts the variable which is exception and string which would be a format.

07:45.320 --> 07:52.280
This just means we need different formats of output on the website and on the CLI, specifically on

07:52.280 --> 07:52.940
the website.

07:52.940 --> 08:00.770
We just might want to produce a text error that's a string, but on the CLI we've got more options.

08:00.770 --> 08:08.270
We can, for example add some colors For it to be more distinguishable, that it isn't actually an error.

08:08.270 --> 08:14.450
And that's why we're going to accept different format strings.

08:14.450 --> 08:19.880
You're gonna see how exactly this works very, very soon.

08:19.880 --> 08:26.930
Anyway, we're going to use Sprintf function, to which you pass the format.

08:27.080 --> 08:37.910
And the format has some placeholders for dates, integers, etc. and then we're just gonna pass some

08:37.910 --> 08:44.630
data that we just know about the error, like we're gonna generate the current date.

08:44.630 --> 08:53.270
So current year month and day and then an hour minute and a second.

08:53.270 --> 08:56.480
That's just an exact format for a date.

08:57.350 --> 09:02.540
Then we're gonna provide the class name of the exception.

09:02.540 --> 09:06.170
You can get that using Getclass function in PHP.

09:06.620 --> 09:12.920
And next up we're going to give the message from the exception.

09:15.440 --> 09:17.390
The file from the exception.

09:17.390 --> 09:22.280
So where the error happened exactly and on which line.

09:24.140 --> 09:31.970
Now it's job of the other methods using this one format error message to come up with the proper format

09:31.970 --> 09:32.630
string.

09:32.750 --> 09:35.450
We're going to get to that very, very soon.

09:36.740 --> 09:42.470
First, maybe we can work on the errors in the CLI.

09:42.530 --> 09:49.550
And this should be a little simpler because for the web errors we also need to produce a view.

09:49.790 --> 09:55.640
So first maybe we can implement this method render CLI error.

09:58.790 --> 10:02.270
Now this method is obviously private.

10:02.300 --> 10:05.130
There is no point in making it public.

10:05.130 --> 10:07.710
It is an internal method.

10:09.180 --> 10:18.750
So it is render CLI error and it accepts variable and the name is the exception.

10:20.280 --> 10:23.820
So its void doesn't return anything.

10:24.270 --> 10:29.250
Now at this point we need to figure out if we are in the debug mode.

10:29.340 --> 10:34.050
So I'd like to use the app container and get the config.

10:34.110 --> 10:35.520
So a quick reminder.

10:35.520 --> 10:40.590
How does it look like we've got this app key and debug key inside.

10:42.300 --> 10:43.680
So we're going to use that.

10:44.400 --> 10:48.090
There is an app key which should have the debug key.

10:48.120 --> 10:54.180
If this happens to be undefined we just provide a default which is false.

10:56.700 --> 11:04.080
Next up if we are in the debug mode we're going to handle it differently than if we are not.

11:05.280 --> 11:09.210
So we need to produce the error message.

11:11.280 --> 11:17.550
And that's the time where we are using the format error message.

11:19.440 --> 11:21.690
Maybe I'm gonna use the static keyword here.

11:24.780 --> 11:28.080
And the first argument there is the exception.

11:28.080 --> 11:29.910
But the second is the format.

11:29.910 --> 11:33.000
Let's produce the format for the CLI.

11:34.740 --> 11:42.660
So in this format parameter we need to just add a placeholders which will be filled with the values

11:42.660 --> 11:43.320
in order.

11:43.320 --> 11:46.740
They are passed to the format error message.

11:46.860 --> 11:48.810
And that's the order.

11:48.810 --> 11:52.290
So we get the date the class message file and line.

11:52.710 --> 11:56.790
So I just enabled the split view so we can see that.

11:57.090 --> 12:02.160
So in the square brackets we might output the time.

12:02.520 --> 12:05.190
And this is done by adding percent s.

12:05.230 --> 12:10.480
This means we want this as a string which would relate to that date.

12:12.850 --> 12:16.360
And then we can say we've got an error.

12:17.980 --> 12:21.100
Then percent s would be the class name.

12:22.090 --> 12:28.630
We can have another colon and the percent s would be the message.

12:31.750 --> 12:46.660
Then we can say in another S string placeholder that would be the file online percent d as that's an

12:46.660 --> 12:47.260
integer.

12:47.260 --> 12:49.030
So we have a number.

12:49.360 --> 12:51.790
So D stands for decimal.

12:53.230 --> 12:55.660
At the end we can add a line break.

12:55.690 --> 13:01.660
And that would be the basic error we can display in a terminal.

13:02.290 --> 13:05.590
Now obviously I'd like to spice up things a little bit.

13:05.590 --> 13:09.220
We can close this window already.

13:09.250 --> 13:12.700
And I'd like to add some CLI colors.

13:12.730 --> 13:15.130
Now it's pretty easy to do.

13:15.160 --> 13:16.690
You just need some.

13:16.690 --> 13:19.330
You just need to know some specific symbols.

13:19.420 --> 13:27.760
So what I'm typing right here is the exact symbol that will change the color in the terminal to red.

13:29.020 --> 13:31.330
So you need this slash.

13:32.230 --> 13:39.130
Oh 33 opening square bracket 31.

13:40.030 --> 13:49.270
M so this here is an exact combo that will change the color of all the output to red.

13:49.270 --> 13:52.690
And we don't want really everything to be in red.

13:52.690 --> 13:55.720
So we need to reset that at one point.

13:56.050 --> 14:00.310
And it's up to us where to do that.

14:00.340 --> 14:03.220
Maybe we can do it right after the error.

14:03.310 --> 14:07.030
So to reset we're gonna do again.

14:07.180 --> 14:08.080
Slash.

14:08.110 --> 14:14.590
Oh 33 opening square bracket zero.

14:15.160 --> 14:20.890
M this would just reset the color to the default one, whatever that is.

14:20.920 --> 14:26.950
And that way we would have a really nicely formatted error that is super visible.

14:28.570 --> 14:30.100
But that's not everything.

14:30.100 --> 14:33.520
We can also get a so-called stack trace.

14:34.570 --> 14:39.730
So from the exception we can grab get trace as string.

14:39.730 --> 14:46.930
And what stack Trace is, is basically what were the subsequent method or function calls.

14:46.930 --> 14:50.770
So we can track what was called in what order.

14:50.770 --> 14:57.370
And potentially uh, it's easier to find the flows in the logic of your programs.

14:57.400 --> 14:59.080
We're going to see it obviously.

14:59.230 --> 15:07.190
Now, if we are not in the debug mode, then we might want a simpler error.

15:09.020 --> 15:13.040
So for such cases, we're going to have a simpler error message.

15:13.040 --> 15:17.750
And the trace would be an empty string.

15:18.320 --> 15:22.640
So you don't really want to show your stack trace of your errors.

15:22.700 --> 15:28.820
Uh, if you are not in the debug mode, even on the terminal.

15:28.850 --> 15:35.090
So here the message, I think we can still use the colors.

15:35.870 --> 15:37.760
That's why I'm copying this.

15:38.870 --> 15:40.310
And.

15:44.000 --> 15:46.160
We're going to output the error right here.

15:46.160 --> 15:49.220
And I'm going to remove everything else.

15:50.720 --> 15:53.720
So that's the changing of the color to red.

15:53.720 --> 15:55.910
And this is resetting to the default.

15:55.910 --> 16:04.910
And we're just going to say an unexpected error occurred.

16:06.770 --> 16:15.170
Please check logs or please check error log for details.

16:16.190 --> 16:17.060
And that's it.

16:17.090 --> 16:18.890
Now we can remove those spaces.

16:18.920 --> 16:22.520
I just added them so it's more clear.

16:22.520 --> 16:27.860
But remember that this is just a specific code for changing to red.

16:28.040 --> 16:34.100
And this is a specific code that terminals understand that will reset to the default one.

16:34.880 --> 16:36.590
So we are almost there.

16:36.620 --> 16:39.410
Now we need to output this someplace.

16:39.410 --> 16:44.360
And you do it using f right function.

16:44.360 --> 16:52.700
And we just say that we want to write to the so-called standard error output where we give the error

16:52.700 --> 16:53.750
message.

16:53.750 --> 17:01.940
And if we have the trace we're also going to write it to the standard error output.

17:05.450 --> 17:19.770
Where we can additionally say that maybe after a new line that the stack trace is then another trace

17:20.430 --> 17:23.190
and maybe another new line.

17:25.890 --> 17:26.340
Right.

17:26.340 --> 17:35.190
And then let's make sure we exit with an error code that's non-zero, which would mean that there was

17:35.190 --> 17:36.120
an error.

17:37.260 --> 17:37.500
Okay.

17:37.530 --> 17:42.540
So a lot of stuff was done I think that next up we should try this out.

17:42.540 --> 17:47.070
Let me comment out this line because we don't have this one implemented yet.

17:47.070 --> 17:54.420
Anyway, I think we might try to trigger some error even manually in any of the command line scripts.

17:54.420 --> 18:02.220
But we're going to do this next time, because we also need to register those new error handlers in

18:02.220 --> 18:04.050
our bootstrap file.

18:04.410 --> 18:07.890
So we're going to be testing this next up.
