1 00:00:00,750 --> 00:00:04,470 In the last video we discussed how PHP was exception light and 2 00:00:04,470 --> 00:00:08,260 used optional error messages or false E values to report a problem. 3 00:00:08,260 --> 00:00:10,540 The core itself might not use exceptions much, but 4 00:00:10,540 --> 00:00:12,450 they are available if you wish to use them in your own code. 5 00:00:12,450 --> 00:00:15,600 And you'll certainly run into them using components or frameworks. 6 00:00:16,800 --> 00:00:20,300 The problem with giving false E values is that you have to go looking for a mistake 7 00:00:20,300 --> 00:00:23,210 and check the documentation to see which method provides the error message. 8 00:00:23,210 --> 00:00:26,490 It's be much better to have an exception thrown at you to make it 9 00:00:26,490 --> 00:00:28,140 extremely obvious. 10 00:00:28,140 --> 00:00:31,120 Let's take a look at how we can throw various types of an exception from 11 00:00:31,120 --> 00:00:34,050 a function and have PHP react differently to each of them. 12 00:00:34,050 --> 00:00:36,780 If we look in the workspace we'll see a couple of files there which you 13 00:00:36,780 --> 00:00:38,830 should recognize already from composer. 14 00:00:38,830 --> 00:00:40,160 We open the index.php. 15 00:00:40,160 --> 00:00:42,660 There's quite a lot of code in here, but don't panic. 16 00:00:42,660 --> 00:00:44,129 I'm gonna explain what all of this means. 17 00:00:45,240 --> 00:00:48,560 On line three here we have display errors which we're already familiar with. 18 00:00:48,560 --> 00:00:52,070 This will help us recognize any errors that are unexpected. 19 00:00:52,070 --> 00:00:57,150 We have a include vendor autoload.php which once again is, composer related. 20 00:00:57,150 --> 00:00:59,980 And this is where our, our new code starts. 21 00:00:59,980 --> 00:01:04,020 Basically, this is a HTTP download script which will download the body of 22 00:01:04,020 --> 00:01:05,890 any URL that we provide. 23 00:01:05,890 --> 00:01:09,190 On lines eight to ten here, we define multiple types of exception. 24 00:01:09,190 --> 00:01:11,410 You can just use the core exception class, but 25 00:01:11,410 --> 00:01:14,940 defining your own exceptions by extending the exception class makes it 26 00:01:14,940 --> 00:01:18,600 much easier to distinguish different types of exception later on. 27 00:01:18,600 --> 00:01:22,100 I'm breaking a few rules here by defining multiple classes and functions in the same 28 00:01:22,100 --> 00:01:25,700 body, normally these should be split out into different files, but for the sake of 29 00:01:25,700 --> 00:01:29,700 demonstrating, I, I kind of broke the rules there and threw them in together. 30 00:01:29,700 --> 00:01:35,680 On line 13 here we're defining a function named fetch http body and 31 00:01:35,680 --> 00:01:38,650 it takes one argument which is a URL. 32 00:01:38,650 --> 00:01:42,790 This argument is a string value of the URL that we'd like to download. 33 00:01:43,840 --> 00:01:47,530 Line 15 here instantiates a class called browser which lives 34 00:01:47,530 --> 00:01:48,710 inside the buzz name space. 35 00:01:48,710 --> 00:01:52,990 This is a handy little package which lets us work with HTTP interactions in 36 00:01:52,990 --> 00:01:55,630 a much more sane fashion than the curl extension, and we 37 00:01:55,630 --> 00:01:59,870 can rely on this working even if the curl extension is not installed on the server. 38 00:01:59,870 --> 00:02:03,660 Line 16 here is using our newly instantiated browser object and 39 00:02:03,660 --> 00:02:04,750 running the get method. 40 00:02:04,750 --> 00:02:06,910 And passing the URL as an argument. 41 00:02:06,910 --> 00:02:08,940 The response is an object. 42 00:02:08,940 --> 00:02:10,470 And it's stored in this response variable. 43 00:02:11,670 --> 00:02:15,190 Then on lines 18 we're downloading the content of the response. 44 00:02:15,190 --> 00:02:16,550 This is the HTTP body. 45 00:02:16,550 --> 00:02:19,100 The actual HTML of the response. 46 00:02:19,100 --> 00:02:22,730 On line 19 here we are looking at the response object. 47 00:02:22,730 --> 00:02:25,250 And running the getStatusCode method. 48 00:02:25,250 --> 00:02:28,160 And storing that in a status code variable. 49 00:02:28,160 --> 00:02:30,064 We'll use both these items in a moment. 50 00:02:30,064 --> 00:02:33,800 On line 21 we're creating a status group variable. 51 00:02:33,800 --> 00:02:37,470 And we're doing some string work on the status code to find out 52 00:02:37,470 --> 00:02:38,890 what the very first digit is. 53 00:02:38,890 --> 00:02:43,030 This means that if we get a code of 400 back then we only want the four. 54 00:02:43,030 --> 00:02:45,910 If you're not familiar with HTTP status codes, 55 00:02:45,910 --> 00:02:48,820 just know that there are lots of different codes, each with a different meaning. 56 00:02:48,820 --> 00:02:51,360 And we can group these codes based on the first digit. 57 00:02:51,360 --> 00:02:55,500 For example, if we get code 404 that means a missing page. 58 00:02:55,500 --> 00:02:59,770 And because it starts with a four we know that it's a HTTP client error. 59 00:02:59,770 --> 00:03:04,680 An HTTP client could be a web browser or in this case our PHP code. 60 00:03:04,680 --> 00:03:05,650 Because the client asked for 61 00:03:05,650 --> 00:03:08,550 a missing page we should tell them that they messed up. 62 00:03:08,550 --> 00:03:13,570 So this status code variable can contain two, three, four, or five. 63 00:03:13,570 --> 00:03:16,880 Depending on the type of exception we throw the outside code will want to 64 00:03:16,880 --> 00:03:18,610 interact differently. 65 00:03:18,610 --> 00:03:21,590 By using the status group variable in a switch element we can 66 00:03:21,590 --> 00:03:23,230 throw different exceptions. 67 00:03:23,230 --> 00:03:25,500 These rules are based on the HTTP specification, so 68 00:03:25,500 --> 00:03:28,250 just go along with them if you don't completely understand the HTTP spec. 69 00:03:29,930 --> 00:03:32,480 So 23, we have a switch statement looking at the status group. 70 00:03:32,480 --> 00:03:33,950 And then we have a case for 71 00:03:33,950 --> 00:03:37,180 each different potential value the status group can contain. 72 00:03:37,180 --> 00:03:39,990 By line 25, we know the value starts with a 2, 73 00:03:39,990 --> 00:03:43,840 which according to the HTTP specification, means everything worked. 74 00:03:43,840 --> 00:03:45,110 That means we can go ahead and 75 00:03:45,110 --> 00:03:48,330 return the content variable and there is no need for an exception. 76 00:03:48,330 --> 00:03:53,340 On line 27, we know the code started with a 3 which means a redirection happened. 77 00:03:53,340 --> 00:03:57,410 To let the function call know about that we can throw in new HTTP, redirect 78 00:03:57,410 --> 00:04:01,830 exception with a human readable message and the specific status code included. 79 00:04:01,830 --> 00:04:04,030 If we get to line 29 here. 80 00:04:04,030 --> 00:04:05,730 We know that the code started with a four and 81 00:04:05,730 --> 00:04:08,500 that must mean that the client made a bad request. 82 00:04:08,500 --> 00:04:12,370 We can let them know about that by throwing a new HTTP client exception. 83 00:04:12,370 --> 00:04:15,370 On line 31 here, we have a code starting with a 5, 84 00:04:15,370 --> 00:04:19,380 which the HTTP specification explains means a server error. 85 00:04:19,380 --> 00:04:23,470 So let's throw a HTTP server exception with another human readable string. 86 00:04:23,470 --> 00:04:26,070 Finally, line 32 has a default case. 87 00:04:26,070 --> 00:04:28,860 That means if we get an unexpected value in the status group then we 88 00:04:28,860 --> 00:04:31,570 can throw a generic exception explaining that we don't know what's going on, 89 00:04:31,570 --> 00:04:33,270 something weird happened. 90 00:04:33,270 --> 00:04:36,520 Now, I know that's quite a lot to take in but the main takeaway here is 91 00:04:36,520 --> 00:04:39,750 that different types of problem have different types of exceptions. 92 00:04:39,750 --> 00:04:42,300 So reactions can differ based on the exception. 93 00:04:42,300 --> 00:04:46,060 Let's take a look at some code that reacts differently based on different exceptions. 94 00:04:46,060 --> 00:04:51,880 If wee look at line 39 here we'll see that we're calling our fetch HTTP body and 95 00:04:51,880 --> 00:04:54,180 we're echoing the result directly. 96 00:04:54,180 --> 00:04:55,950 We're also passing in a string. 97 00:04:55,950 --> 00:04:59,510 This string contains a URL which will go into the URL parameter in our 98 00:04:59,510 --> 00:05:01,280 function defined above. 99 00:05:01,280 --> 00:05:04,970 You'll also notice that on the line above, on line 38, we have a try block. 100 00:05:04,970 --> 00:05:08,030 This try means that it should look out for any exceptions being thrown, and 101 00:05:08,030 --> 00:05:12,010 if the exceptions being thrown match any of these four here, 102 00:05:12,010 --> 00:05:15,450 then the piece of code in that catch block will run. 103 00:05:15,450 --> 00:05:18,570 We'll know which type of exception is being thrown by looking at the output of 104 00:05:18,570 --> 00:05:21,490 our error, because we have this string appended on the front. 105 00:05:23,610 --> 00:05:25,660 We're then outputting getMessage. 106 00:05:26,770 --> 00:05:29,430 And in the case of these first three, we're also outputting the code. 107 00:05:29,430 --> 00:05:34,020 If you're not sure how printf works it's just a, a, a pretty way to format strings. 108 00:05:34,020 --> 00:05:36,470 Look it up in the manual if you need to understand it, 109 00:05:36,470 --> 00:05:40,390 but these basically put, these values into place. 110 00:05:40,390 --> 00:05:42,710 So I think it's about time that we ran our script to see what happened. 111 00:05:42,710 --> 00:05:44,320 If we go to the Preview icon here. 112 00:05:45,860 --> 00:05:51,020 Then we see example domain, this is exactly the output we were expecting. 113 00:05:51,020 --> 00:05:54,910 We got to example.org ourselves, then that's what you see, 114 00:05:54,910 --> 00:05:56,890 looks exactly the same, brilliant. 115 00:05:56,890 --> 00:06:00,310 Now let's try and break it, if I put in a garbage URL like this, so 116 00:06:00,310 --> 00:06:02,580 it definitely doesn't exist on the website. 117 00:06:02,580 --> 00:06:05,080 Then we should be able to refresh, and perfect. 118 00:06:05,080 --> 00:06:06,130 We got a client error and 119 00:06:06,130 --> 00:06:09,490 the code 404 which as I explained earlier means page missing. 120 00:06:09,490 --> 00:06:11,700 We go back to our code, and try and break it in another way. 121 00:06:13,530 --> 00:06:16,920 We got a general error saying it failed to open stream. 122 00:06:16,920 --> 00:06:20,730 Now, this isn't one of our exceptions, but it is being caught by our code. 123 00:06:20,730 --> 00:06:22,590 This exception is being thrown by buzz. 124 00:06:23,830 --> 00:06:27,030 They've thrown some sort of exception that we haven't made a catch for. 125 00:06:27,030 --> 00:06:31,330 But because we have this catchall statement here we're catching it anyway. 126 00:06:31,330 --> 00:06:32,150 This is great. 127 00:06:32,150 --> 00:06:33,740 It's not only if we ensured that we're looking out for 128 00:06:33,740 --> 00:06:37,070 specific events from our code and reacting to them accordingly, but we're also 129 00:06:37,070 --> 00:06:40,590 using a catchall block to catch any other exceptions that we didn't expect. 130 00:06:40,590 --> 00:06:43,340 Instead of simply echoing out these errors we can use them to do 131 00:06:43,340 --> 00:06:45,160 useful things in our code. 132 00:06:45,160 --> 00:06:48,820 A HTTP server exception might retry the connection. 133 00:06:48,820 --> 00:06:52,670 A HTTP client exception might send an error to the user. 134 00:06:52,670 --> 00:06:55,960 A general exception might fire off an email to somebody on the development team, 135 00:06:55,960 --> 00:06:58,300 letting them know that code needs to be improved. 136 00:06:58,300 --> 00:07:01,820 The point here is by reacting to specific expectations, 137 00:07:01,820 --> 00:07:04,950 you can get very granular in how you react to specific problems. 138 00:07:04,950 --> 00:07:06,720 Which is so much more useful than just looking for 139 00:07:06,720 --> 00:07:09,000 a false return value, and then saying nope. 140 00:07:09,000 --> 00:07:09,600 That didn't work. 141 00:07:10,870 --> 00:07:13,900 Exceptions can take a little while to get your head around, but on a very basic 142 00:07:13,900 --> 00:07:18,220 level, custom exception classes should be used like a category of exception. 143 00:07:18,220 --> 00:07:22,280 Then the specific error message and code provide further information. 144 00:07:22,280 --> 00:07:24,760 This is much easier than trying to work out if false is good or bad.