1 00:00:00,506 --> 00:00:14,076 [ Background sounds ] 2 00:00:14,576 --> 00:00:17,146 >>This is CS50. 3 00:00:17,376 --> 00:00:21,326 And actually this is my Halloween costume. 4 00:00:21,626 --> 00:00:21,966 Actually -- 5 00:00:24,516 --> 00:00:27,596 [Applause] 6 00:00:28,096 --> 00:00:31,076 >>Actually I wasn't quite sure which one to wear. 7 00:00:31,076 --> 00:00:33,306 We can raise the house lights now. 8 00:00:33,626 --> 00:00:39,276 I also debated between this one here, if anyone's of interest. 9 00:00:39,276 --> 00:00:40,566 So I thought at least Rob is here. 10 00:00:40,566 --> 00:00:41,516 Rob would you like to come up 11 00:00:41,516 --> 00:00:43,926 and be Team Boden today or with Boden fever? 12 00:00:45,336 --> 00:00:46,506 Come on awkwardly up. 13 00:00:46,606 --> 00:00:46,906 Woo! 14 00:00:47,516 --> 00:00:52,176 [ Applause ] 15 00:00:52,676 --> 00:00:53,946 >>I have Boden fever. 16 00:00:54,186 --> 00:00:54,476 Okay. 17 00:00:54,476 --> 00:00:59,956 >>So now -- all right. 18 00:01:00,216 --> 00:01:02,676 So I'm the one who has to wear this now all day. 19 00:01:03,136 --> 00:01:07,026 So we left off -- recall -- 20 00:01:07,746 --> 00:01:11,326 introducing something completely new after we left this. 21 00:01:12,046 --> 00:01:14,716 So this was an actual screenshot from one of your classmates 22 00:01:14,976 --> 00:01:16,536 that frankly probably kind of summed 23 00:01:16,536 --> 00:01:18,566 up how you've been feeling the last week or so. 24 00:01:19,266 --> 00:01:20,716 Actually happened. 25 00:01:20,716 --> 00:01:21,976 And he was clever enough 26 00:01:21,976 --> 00:01:24,006 to screen shot it before it was too late. 27 00:01:24,086 --> 00:01:25,846 So now all of that is behind us. 28 00:01:25,846 --> 00:01:29,026 And we move on to things like CS50 Finance, which is going 29 00:01:29,266 --> 00:01:31,906 to be the first of two web-base programming projects 30 00:01:31,906 --> 00:01:32,996 that we'll do this semester. 31 00:01:33,216 --> 00:01:36,066 And you'll find that the skeleton code that we give you 32 00:01:36,066 --> 00:01:38,706 for these problem sets is really meant to empower you 33 00:01:38,706 --> 00:01:40,716 for final projects to have a starting point. 34 00:01:40,716 --> 00:01:43,236 To realize now that what a lot of students do 35 00:01:43,236 --> 00:01:46,246 for final projects is they take their CS50 Finance 36 00:01:46,246 --> 00:01:48,256 or their Problem Set 8, they kind of throw 37 00:01:48,256 --> 00:01:50,376 out code that's irrelevant to their project, 38 00:01:50,376 --> 00:01:53,046 but then use the basics for their own final project. 39 00:01:53,046 --> 00:01:55,356 So realize we're tried to provide you not just 40 00:01:55,356 --> 00:01:57,576 with this framework for implementing this tool, 41 00:01:57,786 --> 00:02:00,466 but really web projects in general. 42 00:02:00,466 --> 00:02:02,356 Toward that end, know that -- 43 00:02:02,746 --> 00:02:04,986 actually I screenshotted this as well. 44 00:02:04,986 --> 00:02:07,186 So this was a screenshot of a penny stock 45 00:02:07,466 --> 00:02:10,376 that we used last year for Problem Set 7. 46 00:02:10,376 --> 00:02:11,926 It's only 40 cents there, 47 00:02:11,926 --> 00:02:13,176 according to the screenshot here. 48 00:02:13,416 --> 00:02:16,136 And I knew about this stock because I'd gotten this email 49 00:02:16,136 --> 00:02:18,906 from a guy named Tim in my spam folder. 50 00:02:19,516 --> 00:02:22,866 We usually change this every year because this is 2010. 51 00:02:22,866 --> 00:02:26,816 In 2011, the A5 Labs are not doing so well, 52 00:02:27,186 --> 00:02:29,846 all thanks perhaps to a bit of excessive trading. 53 00:02:29,846 --> 00:02:31,116 But the stock is still traded. 54 00:02:31,116 --> 00:02:33,036 And you'll see that this is the one that's used 55 00:02:33,036 --> 00:02:34,766 in the Problem Set's examples. 56 00:02:35,316 --> 00:02:37,536 So dinner this week -- for those of you who have not been able 57 00:02:37,536 --> 00:02:39,626 to make the past lunches -- we thought we would do something 58 00:02:39,626 --> 00:02:40,846 on Wednesday at six pm. 59 00:02:40,846 --> 00:02:44,476 If of interest, go ahead to CS50 dot net slash TV. 60 00:02:44,696 --> 00:02:45,946 And then a word on seminars. 61 00:02:45,946 --> 00:02:48,886 So this is the most seminars we've ever offered historically. 62 00:02:48,886 --> 00:02:50,116 All of these will be filmed. 63 00:02:50,116 --> 00:02:51,426 And if you'd like to register for any 64 00:02:51,426 --> 00:02:52,926 of these, go to that URL there. 65 00:02:53,206 --> 00:02:54,676 In particular, let me draw your attention 66 00:02:54,676 --> 00:02:57,926 to two particularly novel ones involving mobile programming. 67 00:02:57,926 --> 00:02:59,586 So some of our friends at Microsoft are going 68 00:02:59,586 --> 00:03:02,036 to be offering, probably tomorrow night, 69 00:03:02,036 --> 00:03:04,546 this appLab phone for Windows programming. 70 00:03:04,546 --> 00:03:07,466 More details can be found at the URL there. 71 00:03:07,866 --> 00:03:12,046 They've offered to present some fabulous prizes for those of you 72 00:03:12,046 --> 00:03:13,316 if you choose to elect 73 00:03:13,316 --> 00:03:15,166 to do some Windows phone-based project. 74 00:03:15,166 --> 00:03:17,816 And also, too, know that we'll have a Blackberry programming 75 00:03:17,856 --> 00:03:19,546 seminar in a week or so. 76 00:03:19,546 --> 00:03:23,186 And for this RIM has kindly donated some Blackberry 77 00:03:23,186 --> 00:03:24,126 Bold phones. 78 00:03:24,126 --> 00:03:26,266 So if you would like to go the route of developing 79 00:03:26,266 --> 00:03:29,166 for Blackberry, drop me a note and we can see 80 00:03:29,166 --> 00:03:31,656 if we can hook you up with some actual hardware for that. 81 00:03:32,396 --> 00:03:34,186 All right. 82 00:03:34,616 --> 00:03:37,536 So PHP. So PHP is fundamentally different from C 83 00:03:37,536 --> 00:03:39,046 in that it's not compiled. 84 00:03:39,376 --> 00:03:40,576 It's interpreted. 85 00:03:40,576 --> 00:03:43,386 And an interpreted language is something that you still write 86 00:03:43,386 --> 00:03:44,766 in the same way with source code, 87 00:03:44,996 --> 00:03:46,946 but you don't actually run it through a compiler 88 00:03:46,946 --> 00:03:49,166 and then run the resulting executable. 89 00:03:49,516 --> 00:03:51,386 Rather, you write your source code. 90 00:03:51,586 --> 00:03:53,516 Then you run and executable and you pass 91 00:03:53,696 --> 00:03:57,686 to that executable the PHP source code at its input -- 92 00:03:57,686 --> 00:03:59,336 as its command line argument, really. 93 00:03:59,626 --> 00:04:00,406 So in the world of PHP, 94 00:04:00,406 --> 00:04:04,406 the interpreter is generally a program called PHP dot exe, 95 00:04:04,406 --> 00:04:07,336 on Windows at least, or PHP dot app on Mac 96 00:04:07,486 --> 00:04:09,076 or PHP on a Linux system. 97 00:04:09,336 --> 00:04:11,146 So what's nice about interpreted languages is 98 00:04:11,146 --> 00:04:12,346 that they actually lend themselves 99 00:04:12,346 --> 00:04:14,236 to much faster programming. 100 00:04:14,236 --> 00:04:15,766 You don't have to jump through as many hoops 101 00:04:16,056 --> 00:04:17,586 to actually get your code working. 102 00:04:17,586 --> 00:04:20,316 And there tend to be much higher level in the sense 103 00:04:20,316 --> 00:04:23,216 that you don't need to worry henceforth about pointers 104 00:04:23,216 --> 00:04:24,406 and locations in memory. 105 00:04:24,646 --> 00:04:27,626 You don't need to worry about memory management anymore. 106 00:04:27,666 --> 00:04:30,576 Rather, the interpreter -- in this case PHP -- 107 00:04:30,576 --> 00:04:33,646 is going to handle a lot of that minutiae -- interesting details, 108 00:04:33,896 --> 00:04:36,426 but tedious details as you advance further 109 00:04:36,426 --> 00:04:38,876 in your understanding and savvy with programming. 110 00:04:38,876 --> 00:04:40,816 So just to give you a sense of PHP, 111 00:04:40,816 --> 00:04:43,766 here is perhaps wonderfully recommended resource 112 00:04:43,766 --> 00:04:45,136 that just talks about the language. 113 00:04:45,136 --> 00:04:45,676 Here is a loop. 114 00:04:45,676 --> 00:04:47,166 Here is a condition and so forth 115 00:04:47,396 --> 00:04:49,676 so that rapid fire you can acclimate to the syntax. 116 00:04:49,816 --> 00:04:53,226 And you will find PHP syntax very similar to C, which is one 117 00:04:53,226 --> 00:04:55,176 of the reasons we use it at this point in the course. 118 00:04:55,606 --> 00:04:57,676 In terms of functions, though, one of the nice things is 119 00:04:57,676 --> 00:05:00,026 that we also don't need to adhere to this convention 120 00:05:00,026 --> 00:05:01,866 of having a main function anymore. 121 00:05:02,026 --> 00:05:04,136 Rather, if you want to write a program in PHP, 122 00:05:04,136 --> 00:05:07,126 you open up a text editor, you create a new file, 123 00:05:07,296 --> 00:05:09,126 and you just start writing PHP code. 124 00:05:09,126 --> 00:05:11,536 You don't have to have a main function per se, 125 00:05:11,726 --> 00:05:14,866 but you can have and will have other functions 126 00:05:14,866 --> 00:05:16,686 that you write or that you use. 127 00:05:16,816 --> 00:05:18,816 So conditions look just like this. 128 00:05:18,816 --> 00:05:21,006 And this is the exact same slide we showed in week one 129 00:05:21,006 --> 00:05:23,886 when we started talking about C. The general format 130 00:05:23,886 --> 00:05:26,576 for conditions in PHP is going to be the same. 131 00:05:26,576 --> 00:05:29,016 In the case of Boolean expressions, these are going 132 00:05:29,016 --> 00:05:31,786 to look the same, both with or's and with and's. 133 00:05:31,786 --> 00:05:33,346 Switches are going to be the same. 134 00:05:33,346 --> 00:05:35,816 In fact, switches are a little more generous in PHP 135 00:05:35,816 --> 00:05:39,596 in that you don't need to just compare integers or chars. 136 00:05:39,796 --> 00:05:42,516 You can actually do string comparisons using these cases. 137 00:05:42,516 --> 00:05:45,746 So that's actually a little more friendly and versatile as well. 138 00:05:45,906 --> 00:05:47,516 Loops are actually going to look the same. 139 00:05:47,516 --> 00:05:48,606 You're going to have for loops. 140 00:05:48,606 --> 00:05:49,936 You're going to have while loops. 141 00:05:50,176 --> 00:05:51,816 You're going to have do while loops. 142 00:05:52,246 --> 00:05:54,316 And so this ultimately is to say that we're going 143 00:05:54,316 --> 00:05:55,996 to see lot of familiar syntax. 144 00:05:56,276 --> 00:05:57,856 We also have arrays in PHP. 145 00:05:57,856 --> 00:06:01,146 But the nice thing about PHP's arrays is that one, 146 00:06:01,146 --> 00:06:03,866 you don't have to declare their size in advance. 147 00:06:03,866 --> 00:06:04,816 If you want an array, 148 00:06:04,816 --> 00:06:06,726 you effectively just say, 'Give me and array.' 149 00:06:07,006 --> 00:06:09,476 And then PHP figures out what size it should be. 150 00:06:09,476 --> 00:06:12,006 And if you keep adding and adding and adding to it, 151 00:06:12,006 --> 00:06:14,416 PHP will take care of resizing it for you. 152 00:06:14,416 --> 00:06:16,806 You don't have to worry about malloc and realloc and all 153 00:06:16,806 --> 00:06:18,496 of these lower level details anymore. 154 00:06:18,816 --> 00:06:21,546 The language is, again, much higher level. 155 00:06:21,546 --> 00:06:22,916 You also have variables. 156 00:06:22,916 --> 00:06:24,186 But variables, syntactically, 157 00:06:24,186 --> 00:06:25,316 you'll find are a little different. 158 00:06:25,316 --> 00:06:27,426 For better or for worse, every variable 159 00:06:27,426 --> 00:06:29,806 in PHP is prefixed with a dollar sign. 160 00:06:30,036 --> 00:06:32,706 The upside of this is that it really is obvious what is 161 00:06:32,706 --> 00:06:33,276 a variable. 162 00:06:33,276 --> 00:06:35,556 The downside that you have dollar signs all over the place. 163 00:06:35,596 --> 00:06:37,466 But this is just a convention that these folks chose. 164 00:06:37,736 --> 00:06:39,426 So in this snippet of sample code here, 165 00:06:39,556 --> 00:06:42,546 I am declaring a variable called S. I'm setting it equal 166 00:06:42,546 --> 00:06:44,316 to a value of 'hello, world'. 167 00:06:44,756 --> 00:06:46,786 And then notice what I'm omitting. 168 00:06:47,196 --> 00:06:49,436 I'm not specifying the word 'string'. 169 00:06:49,436 --> 00:06:51,566 I'm not specifying the word 'char star'. 170 00:06:51,566 --> 00:06:54,126 In fact, when you declare variables in PHP, 171 00:06:54,126 --> 00:06:57,296 you're no longer going to specify the type of a variable. 172 00:06:57,296 --> 00:07:00,246 Rather, PHP is going to figure it out from context. 173 00:07:00,246 --> 00:07:02,096 And indeed the context here is pretty obvious. 174 00:07:02,096 --> 00:07:04,466 The double quotes obviously suggest this is a string. 175 00:07:04,716 --> 00:07:06,516 So there is no need for us, the programmer, 176 00:07:06,516 --> 00:07:09,446 anymore to say 'string s' or 'char star s'. 177 00:07:09,836 --> 00:07:13,136 Same in the case of floats, in integers, and even Booleans. 178 00:07:13,416 --> 00:07:14,886 So we relax that constraint. 179 00:07:14,886 --> 00:07:21,496 PHP is loosely typed whereas C is a strongly typed language. 180 00:07:21,496 --> 00:07:23,056 And so this has both upsides and downs. 181 00:07:23,106 --> 00:07:25,756 But for now it means that a lot of the syntax 182 00:07:25,756 --> 00:07:26,486 that you might have struggled 183 00:07:26,486 --> 00:07:29,326 with for some time will start to slip away. 184 00:07:29,876 --> 00:07:32,216 So loops, too, have some nice new features. 185 00:07:32,266 --> 00:07:35,446 It's a very common paradigm in PHP to want to iterate 186 00:07:35,446 --> 00:07:38,006 over an array because PHP is very often used 187 00:07:38,006 --> 00:07:38,896 in web programming. 188 00:07:39,126 --> 00:07:41,286 Web programming often involves databases. 189 00:07:41,496 --> 00:07:43,476 Databases often involve lots of data. 190 00:07:43,476 --> 00:07:45,826 And so it makes sense that you might want to iterate 191 00:07:45,826 --> 00:07:48,736 over a whole bunch of data like your list of friends 192 00:07:48,736 --> 00:07:51,356 or you stock portfolio and print out, print out, 193 00:07:51,356 --> 00:07:52,776 print out the same kind 194 00:07:52,776 --> 00:07:54,436 of information again and again in a loop. 195 00:07:54,646 --> 00:07:57,366 So PHP is this very nice for-each construct 196 00:07:57,466 --> 00:07:58,706 that C did not have. 197 00:07:58,976 --> 00:08:00,756 And the syntax is generally as follows. 198 00:08:00,756 --> 00:08:02,266 For each and then in a parenthesis, 199 00:08:02,266 --> 00:08:05,926 you specify the name of an array that's stored in a variable. 200 00:08:05,926 --> 00:08:08,166 In this case I arbitrarily called the thing array -- 201 00:08:08,246 --> 00:08:09,036 dollar sign array. 202 00:08:09,036 --> 00:08:13,046 For each array as element -- as is just this new keyword -- 203 00:08:13,246 --> 00:08:15,676 dollar sign element is also arbitrarily named, 204 00:08:15,746 --> 00:08:19,356 but ultimately inside these curly braces I can now do this 205 00:08:19,406 --> 00:08:21,786 again and again with dollar sign element. 206 00:08:21,786 --> 00:08:24,236 On each iteration of the loop PHP is going 207 00:08:24,236 --> 00:08:27,916 to automatically change what value is an element 208 00:08:28,206 --> 00:08:30,986 by taking the next element from array successively. 209 00:08:30,986 --> 00:08:32,216 I don't need to do plus plus. 210 00:08:32,486 --> 00:08:35,636 I don't need to do that sort of manual manipulation anymore. 211 00:08:35,926 --> 00:08:38,906 But perhaps most powerful about PHP and a lot 212 00:08:38,906 --> 00:08:40,216 of these higher level languages -- 213 00:08:40,216 --> 00:08:41,696 Ruby and Python and the like -- 214 00:08:41,986 --> 00:08:44,656 is that they support something called associative arrays, 215 00:08:44,656 --> 00:08:45,786 which is just a new word 216 00:08:45,786 --> 00:08:48,846 for what we spent past week on, namely hash tables. 217 00:08:49,016 --> 00:08:50,996 Those of you with Java backgrounds might have called 218 00:08:50,996 --> 00:08:53,276 these things hash maps back in the day. 219 00:08:53,276 --> 00:08:58,066 But an associative array is simply an array whose indices no 220 00:08:58,066 --> 00:08:59,436 longer need to be numbers. 221 00:08:59,606 --> 00:09:01,536 Up until now, anytime we've had an array, 222 00:09:01,566 --> 00:09:04,276 you index into an array by way of bracket zero, 223 00:09:04,276 --> 00:09:05,926 or one or two or three. 224 00:09:06,236 --> 00:09:07,426 And that's a little limiting. 225 00:09:07,566 --> 00:09:10,576 Because in Problem Set 6, you wanted to answer questions 226 00:09:10,576 --> 00:09:13,726 of the form , not where is this word, but is this word 227 00:09:13,826 --> 00:09:15,946 in my hash table or in my tr1. 228 00:09:16,246 --> 00:09:17,766 And so in the case of hash tables, 229 00:09:17,766 --> 00:09:21,056 the input to your check function was typically the word 230 00:09:21,296 --> 00:09:24,656 that had been pulled from the Austin Powers script 231 00:09:24,656 --> 00:09:26,676 for instance, and so you wanted to say, 232 00:09:26,676 --> 00:09:30,366 is this word 'foo' in the dictionary. 233 00:09:30,366 --> 00:09:33,036 And you wanted to use 'foo' as your key 234 00:09:33,216 --> 00:09:35,456 and get back a value of true or false. 235 00:09:35,456 --> 00:09:38,156 Well PHP makes this so incredibly easy 236 00:09:38,406 --> 00:09:41,296 that you can re-implement the entirety of Problem Set 6 237 00:09:41,666 --> 00:09:42,676 in just a couple of minutes. 238 00:09:42,946 --> 00:09:44,956 And so in fact, let's see how we might do this. 239 00:09:44,956 --> 00:09:46,626 I'm going to over to my -- sorry. 240 00:09:46,876 --> 00:09:48,206 I should have told you last week. 241 00:09:48,536 --> 00:09:50,786 So let me go over to my appliance. 242 00:09:50,786 --> 00:09:51,726 I opened up GEdit. 243 00:09:51,726 --> 00:09:54,186 I created a new file called dictionary dot php. 244 00:09:54,186 --> 00:09:57,006 And I'll go ahead and start typing this. 245 00:09:57,006 --> 00:10:00,026 So the one distinction with PHP that you have to remember is 246 00:10:00,026 --> 00:10:02,086 that you can't quite just start typing code. 247 00:10:02,306 --> 00:10:06,096 You actually have to tell the interpreter that you're 248 00:10:06,096 --> 00:10:08,096 about to start writing PHP code. 249 00:10:08,096 --> 00:10:10,216 And so the convention the world adopted is 250 00:10:10,216 --> 00:10:11,916 that if you're writing a PHP program, 251 00:10:11,916 --> 00:10:14,036 the top of your text file should have open bracket, 252 00:10:14,076 --> 00:10:15,846 question mark, PHP. 253 00:10:15,846 --> 00:10:18,266 And then at the bottom of your text file should be essentially 254 00:10:18,266 --> 00:10:19,676 the opposite but without the word, 255 00:10:19,676 --> 00:10:22,846 so question mark angle bracket. 256 00:10:23,166 --> 00:10:25,526 So most web servers, though, actually allow you 257 00:10:25,526 --> 00:10:27,046 to shorten this to just this. 258 00:10:27,126 --> 00:10:29,026 There's a good amount of religious debate on the web 259 00:10:29,026 --> 00:10:29,806 as to which is better. 260 00:10:29,806 --> 00:10:32,046 Frankly I think this is much simpler and more elegant. 261 00:10:32,286 --> 00:10:33,816 And so you'll see, at least in a lecture, 262 00:10:33,816 --> 00:10:35,036 examples in the Problem Sets 263 00:10:35,326 --> 00:10:37,116 that we use what are called short tags. 264 00:10:37,116 --> 00:10:39,456 We don't bother writing PHP all over the place. 265 00:10:39,456 --> 00:10:42,196 But what these tags means -- and these are not HTML tags. 266 00:10:42,226 --> 00:10:44,466 These are for better or for worse PHP tags. 267 00:10:44,716 --> 00:10:46,566 This means here comes some PHP code. 268 00:10:46,856 --> 00:10:49,556 And so I can start implementing Problem Set 6 269 00:10:49,836 --> 00:10:51,726 by thinking ahead as to what I need. 270 00:10:51,726 --> 00:10:54,706 Well ultimately I'm going to want, for instance, a variable. 271 00:10:54,706 --> 00:10:56,356 And I'll call this size. 272 00:10:56,356 --> 00:10:58,256 That's going to represent the size of my dictionary. 273 00:10:58,536 --> 00:11:00,926 I also want to have an actual dictionary. 274 00:11:01,246 --> 00:11:04,526 And so, a dictionary, I like the approach of hash table. 275 00:11:04,606 --> 00:11:08,356 Just conceptually it's easy in that you insert a word and want 276 00:11:08,356 --> 00:11:09,326 to get back true or false. 277 00:11:09,756 --> 00:11:12,266 So that begs an associative array. 278 00:11:12,266 --> 00:11:14,096 And to declare and array in PHP one 279 00:11:14,096 --> 00:11:17,086 of the ways is literally call function called array, 280 00:11:17,156 --> 00:11:18,996 open prn and close prn. 281 00:11:19,306 --> 00:11:21,546 And that gives you now an array of size zero. 282 00:11:21,786 --> 00:11:24,836 But recall that arrays in PHP will resize themselves 283 00:11:25,166 --> 00:11:27,406 and their indices -- the thing 284 00:11:27,406 --> 00:11:30,866 in square brackets no longer have to be numbers. 285 00:11:30,916 --> 00:11:32,926 And so that allows me to do things like this. 286 00:11:32,926 --> 00:11:34,016 Let me now scroll down. 287 00:11:34,246 --> 00:11:35,796 And let me start implementing something 288 00:11:35,796 --> 00:11:37,176 like the load function. 289 00:11:37,436 --> 00:11:40,686 And I'll call D the name of the file that's being loaded -- 290 00:11:40,686 --> 00:11:43,666 so large or small as in the case of Problem Set 6. 291 00:11:44,186 --> 00:11:46,826 And I have to so something a little annoying in PHP. 292 00:11:46,826 --> 00:11:51,106 I actually have to say global size and global dictionary only 293 00:11:51,106 --> 00:11:53,846 because when I'm inside of a function, unlike C, 294 00:11:54,126 --> 00:11:57,816 I need to say explicitly if I'm trying to use a global variable. 295 00:11:57,976 --> 00:12:00,516 With that said, global variables are not all that common. 296 00:12:00,516 --> 00:12:02,156 I've simply gone this route because it's nice 297 00:12:02,156 --> 00:12:03,546 and simple to get started here. 298 00:12:04,126 --> 00:12:07,586 So let me do something error-checking oriented. 299 00:12:07,586 --> 00:12:11,536 So if it is not the case that this dictionary file -- 300 00:12:11,536 --> 00:12:15,426 dollar sign D -- exists, I'm going to go ahead and say -- 301 00:12:16,096 --> 00:12:18,946 if not exists, I'm going to ahead and say, 'return false'. 302 00:12:19,186 --> 00:12:21,276 So if D does not exist return false. 303 00:12:21,466 --> 00:12:26,326 And also, just for good measure, if not is readable D, go ahead 304 00:12:26,326 --> 00:12:27,666 and also return false. 305 00:12:27,666 --> 00:12:30,056 So you didn't focus on these lines so much 306 00:12:30,056 --> 00:12:32,026 in your own implementation since we wrote a lot 307 00:12:32,026 --> 00:12:34,516 of the error checking code in speller dot c. 308 00:12:34,756 --> 00:12:39,336 But these are now PHP functions that just come with the language 309 00:12:39,336 --> 00:12:41,586 and are a lot easier than some of the techniques we had to deal 310 00:12:41,586 --> 00:12:43,076 with in C. But believe it or not, 311 00:12:43,076 --> 00:12:44,636 the load function is almost done. 312 00:12:44,976 --> 00:12:47,176 I'm going to go ahead now and use this new construct 313 00:12:47,496 --> 00:12:52,406 for each -- let me say -- let's call this -- let's do this. 314 00:12:52,406 --> 00:12:57,796 Words gets file of D. It turns out that file is a function 315 00:12:58,036 --> 00:13:01,716 that loads in a text file and for each of its lines puts each 316 00:13:01,716 --> 00:13:03,846 of those lines in a different element in an array. 317 00:13:04,266 --> 00:13:05,556 So at this point in the story, 318 00:13:05,706 --> 00:13:09,016 'words' is an array containing every word from the dictionary. 319 00:13:09,256 --> 00:13:11,496 So now what I want to do is a little something like this. 320 00:13:11,566 --> 00:13:15,646 For each of those words as, let's call it word. 321 00:13:15,646 --> 00:13:18,626 So this is the construct that's like a for loop, but it's going 322 00:13:18,626 --> 00:13:20,876 to do all of the auto-incrementation for me. 323 00:13:21,226 --> 00:13:23,776 So fore each of those words in the array as a word, 324 00:13:23,776 --> 00:13:25,756 I'm going to go ahead and do this. 325 00:13:25,886 --> 00:13:31,556 Dictionary, word gets true, size plus plus. 326 00:13:31,556 --> 00:13:33,256 Done with my load function. 327 00:13:33,256 --> 00:13:33,716 All right. 328 00:13:33,716 --> 00:13:35,286 How is this actually working? 329 00:13:35,286 --> 00:13:37,426 So dictionary is an associative array. 330 00:13:37,666 --> 00:13:41,256 An associative array is just an array whose keys no longer need 331 00:13:41,256 --> 00:13:41,896 to be numbers. 332 00:13:41,926 --> 00:13:43,366 They can be actual words. 333 00:13:43,576 --> 00:13:45,926 And just like an array with numbers associates key 334 00:13:45,926 --> 00:13:47,496 with value -- number with value -- 335 00:13:47,706 --> 00:13:50,656 an associative array can certainly associate word 336 00:13:50,796 --> 00:13:53,296 with value or in this case word with Boolean. 337 00:13:53,586 --> 00:13:56,826 So now I have this amazing data structure that took me one line 338 00:13:56,826 --> 00:14:00,096 of code to implement that I can just say dollar sign dictionary 339 00:14:00,096 --> 00:14:02,276 bracket word close bracket gets true. 340 00:14:02,516 --> 00:14:03,826 And what's that going to do for me? 341 00:14:03,986 --> 00:14:05,956 Well PHP is going to figure out where 342 00:14:05,956 --> 00:14:08,046 in this data structure called an associative array 343 00:14:08,046 --> 00:14:08,976 to put that word. 344 00:14:09,106 --> 00:14:11,346 And it's going to store the value of true. 345 00:14:11,646 --> 00:14:14,336 Yes, one, whatever the implementation may be 346 00:14:14,336 --> 00:14:15,376 in that data structure. 347 00:14:15,376 --> 00:14:18,166 And size plus plus is just like C. Now I need 348 00:14:18,166 --> 00:14:21,056 to actually do one little thing just for good measure here. 349 00:14:21,666 --> 00:14:23,876 I should probably do this. 350 00:14:23,876 --> 00:14:25,186 And I should probably. 351 00:14:25,186 --> 00:14:27,026 Actually the one little thing I do have to do -- 352 00:14:27,026 --> 00:14:30,436 I have to say a word gets chop word, 353 00:14:30,436 --> 00:14:31,706 in case you're playing along at home, 354 00:14:31,856 --> 00:14:35,266 only because the file function is not quite smart enough 355 00:14:35,266 --> 00:14:37,866 to get rid of the new lines at the end of each line. 356 00:14:38,126 --> 00:14:41,216 So if I want to get rid of those new lines, chop is one way 357 00:14:41,436 --> 00:14:43,956 of eliminating the white space at the end of that word. 358 00:14:43,956 --> 00:14:46,026 But I don't have to deal with lower case or anything like that 359 00:14:46,406 --> 00:14:48,786 because recall that the dictionary we allowed you 360 00:14:48,786 --> 00:14:50,556 to assume would be lowercase. 361 00:14:50,876 --> 00:14:51,516 So return true. 362 00:14:52,056 --> 00:14:53,186 That's it for the load function. 363 00:14:53,186 --> 00:14:55,186 And really the magic is in here. 364 00:14:55,546 --> 00:14:57,716 The rest is just error checking and syntax. 365 00:14:57,946 --> 00:15:00,516 So what about -- how about size? 366 00:15:00,516 --> 00:15:03,116 Well size was pretty easy for all of us, but let's just do 367 00:15:03,116 --> 00:15:04,076 that one for good measure. 368 00:15:04,076 --> 00:15:11,686 So function size -- now I can say global size, return size, 369 00:15:11,996 --> 00:15:13,356 silly though that may seem here. 370 00:15:13,356 --> 00:15:14,976 But it's also certainly pretty simple. 371 00:15:14,976 --> 00:15:16,316 And now let's do check. 372 00:15:16,616 --> 00:15:18,136 Check was kind of the interesting one 373 00:15:18,136 --> 00:15:19,726 because that's the one that was called again 374 00:15:19,726 --> 00:15:20,516 and again and again. 375 00:15:20,846 --> 00:15:22,526 So let me scroll up to the top of my file. 376 00:15:22,846 --> 00:15:23,986 Do function check. 377 00:15:24,086 --> 00:15:25,616 This time I'm going to be checking a word. 378 00:15:25,616 --> 00:15:27,166 Let's arbitrarily call it W. 379 00:15:27,426 --> 00:15:30,096 And in here I need access to the dictionary. 380 00:15:30,146 --> 00:15:31,766 So I have to deal with that little syntax. 381 00:15:32,246 --> 00:15:33,886 But now I can just do this. 382 00:15:33,886 --> 00:15:35,986 First, let me force the word to lower. 383 00:15:35,986 --> 00:15:40,426 So stir to lower is a function in PHP that changes a string 384 00:15:40,656 --> 00:15:41,906 to its lowercase form. 385 00:15:42,196 --> 00:15:43,496 And so now I can just do this. 386 00:15:43,616 --> 00:15:50,806 If in the dictionary array at location W equals equals true, 387 00:15:50,916 --> 00:15:54,706 well return true else return false. 388 00:15:55,066 --> 00:15:56,736 Or if you really want to be fancy, 389 00:15:57,186 --> 00:16:01,146 you can just say return that bam. 390 00:16:02,876 --> 00:16:03,636 Problem Set 6. 391 00:16:04,146 --> 00:16:07,946 So why the hell did we just implement Problem Set 6 in C? 392 00:16:08,146 --> 00:16:11,776 Well the reason that these associative arrays and languages 393 00:16:11,776 --> 00:16:15,266 like PHP and Ruby and Python exist is because of languages 394 00:16:15,266 --> 00:16:19,106 like C. And the fact that this is pretty darn easy to write is 395 00:16:19,106 --> 00:16:20,686 because we've stood on the shoulders 396 00:16:20,686 --> 00:16:21,786 of these previous languages. 397 00:16:21,786 --> 00:16:23,486 In fact, the PHP interpreter -- 398 00:16:23,656 --> 00:16:24,966 the program that we're about to use 399 00:16:24,966 --> 00:16:28,106 to run this program itself -- could be written in C, 400 00:16:28,106 --> 00:16:28,726 and the same thing 401 00:16:28,726 --> 00:16:30,186 for interpreters for other languages. 402 00:16:30,186 --> 00:16:32,266 Because C, as we will see in a moment, 403 00:16:32,446 --> 00:16:34,436 is actually very high performing. 404 00:16:34,666 --> 00:16:37,126 And so actually in the real world when you really care 405 00:16:37,126 --> 00:16:39,086 about the performance of your code as we did 406 00:16:39,086 --> 00:16:41,346 for Problem Set 6, you might want 407 00:16:41,346 --> 00:16:44,176 to sacrifice some rapidity of developer time. 408 00:16:44,506 --> 00:16:47,396 Put more time, put daresay a week or 20 plus hours, 409 00:16:47,396 --> 00:16:49,986 into that implementation so that you really squeeze 410 00:16:49,986 --> 00:16:52,916 out all possible performance. 411 00:16:52,916 --> 00:16:54,526 So let's see what actually happens here. 412 00:16:54,706 --> 00:16:59,606 I'm going to go ahead and go into my terminal window here. 413 00:16:59,936 --> 00:17:02,416 And in here I have two files at the moment, 414 00:17:02,416 --> 00:17:04,636 dictionary dot php and speller. 415 00:17:04,826 --> 00:17:06,696 And just to show you what speller is, 416 00:17:06,696 --> 00:17:08,116 let me go ahead and open speller. 417 00:17:08,466 --> 00:17:10,396 Speller is also implemented in PHP. 418 00:17:10,396 --> 00:17:12,466 And we won't spend time going through this, 419 00:17:12,746 --> 00:17:15,636 but pretty much I sat down one night with the C code open, 420 00:17:15,826 --> 00:17:18,196 with a blank file open, and I just started translating 421 00:17:18,196 --> 00:17:21,606 in my own head the C code to PHP, trying for every line 422 00:17:21,966 --> 00:17:25,426 to call the nearest equivalent PHP function. 423 00:17:25,426 --> 00:17:27,096 So as an at home exercise, definitely look 424 00:17:27,096 --> 00:17:29,866 through this speller file or if you have a printout here today. 425 00:17:29,866 --> 00:17:32,596 But just realize that it's almost a direct translation 426 00:17:32,596 --> 00:17:34,076 from C to PHP. 427 00:17:34,076 --> 00:17:37,626 So as such, it's a nice way of understanding how to go 428 00:17:37,626 --> 00:17:38,576 from one to the other. 429 00:17:38,576 --> 00:17:40,266 And let me point out one little thing here. 430 00:17:40,516 --> 00:17:42,606 You will see in a lot of interpreted languages, 431 00:17:42,926 --> 00:17:44,636 even though they're just written as text files 432 00:17:44,636 --> 00:17:45,846 with simple text editors, 433 00:17:45,846 --> 00:17:48,386 at the very top they have this silly thing called a shebang -- 434 00:17:48,696 --> 00:17:52,166 a sharp bang slash user slash bin slash something. 435 00:17:52,166 --> 00:17:56,106 So this simply means when this is file is executed 436 00:17:56,106 --> 00:17:59,256 at a command prompt, run this interpreter and pass 437 00:17:59,436 --> 00:18:01,886 that interpreter all of the lines below it. 438 00:18:01,886 --> 00:18:05,296 So it's a way of naming your files very simply like speller 439 00:18:05,296 --> 00:18:07,336 as is the case here in my terminal window. 440 00:18:07,616 --> 00:18:10,276 But I don't have to specify a file extension 441 00:18:10,276 --> 00:18:12,416 and therefore tie myself to a specific language. 442 00:18:12,676 --> 00:18:15,776 I can literally just run speller as we could in C. And thanks 443 00:18:15,776 --> 00:18:18,116 to that first line in the speller file, 444 00:18:18,386 --> 00:18:21,076 the operating system will know what to execute. 445 00:18:21,346 --> 00:18:24,146 So let's go ahead and run speller in the PHP version 446 00:18:24,146 --> 00:18:29,726 on CS50 slash PSet6 slash texts 447 00:18:30,556 --> 00:18:32,686 and then Austin Powers for instance. 448 00:18:33,066 --> 00:18:33,926 So let me go ahead and run this. 449 00:18:34,976 --> 00:18:35,326 All right. 450 00:18:36,006 --> 00:18:36,616 So we've got that. 451 00:18:36,956 --> 00:18:39,726 Looks like there were 644 words misspelled. 452 00:18:39,726 --> 00:18:41,416 Words in dictionary seems to check out. 453 00:18:41,416 --> 00:18:44,486 And it just took about half a second, so point 53 seconds. 454 00:18:44,806 --> 00:18:47,076 Well now let me go into another terminal window. 455 00:18:47,636 --> 00:18:54,036 In this window I have implemented PSet6 using C. 456 00:18:54,036 --> 00:18:56,146 So this is my C code from PSet6. 457 00:18:56,306 --> 00:18:57,616 I've already compiled speller. 458 00:18:57,616 --> 00:18:58,886 So let me do the same thing. 459 00:18:58,886 --> 00:19:05,736 Speller on CS50, PSet6 slash text slash Austin Powers enter. 460 00:19:07,586 --> 00:19:09,696 Okay. So I'll zoom in. 461 00:19:10,456 --> 00:19:11,226 This is -- whoops. 462 00:19:11,226 --> 00:19:13,126 Oh, I ran it the same way. 463 00:19:13,226 --> 00:19:14,186 This is before. 464 00:19:14,186 --> 00:19:17,426 Sorry, this is after -- point 03 seconds. 465 00:19:17,886 --> 00:19:21,276 And now if we go back to our misspellings for just a second 466 00:19:21,716 --> 00:19:26,846 and run this again here, it feels slower, right. 467 00:19:26,846 --> 00:19:30,046 If we can do this really explicitly, speller. 468 00:19:31,056 --> 00:19:33,176 Okay, it even got faster that time. 469 00:19:33,586 --> 00:19:34,676 Before, after. 470 00:19:34,886 --> 00:19:36,066 Before, after. 471 00:19:37,396 --> 00:19:41,896 For those who can't see in front, same story. 472 00:19:42,366 --> 00:19:43,566 Before, after. 473 00:19:43,766 --> 00:19:44,846 Before, after. 474 00:19:45,186 --> 00:19:47,136 So this is the price you pay. 475 00:19:47,136 --> 00:19:48,956 And it's not clear perhaps at first glance 476 00:19:48,956 --> 00:19:50,166 if this is now a positive. 477 00:19:50,166 --> 00:19:51,646 It feels like we're about to introduce you 478 00:19:51,646 --> 00:19:53,206 to a really crappy language, right. 479 00:19:53,456 --> 00:19:55,756 Because now you write much less code. 480 00:19:55,756 --> 00:19:57,416 But my God, look at the price you pay. 481 00:19:57,416 --> 00:19:58,926 It's an order of magnitude different. 482 00:19:59,076 --> 00:20:01,356 But this is a little misleading as such. 483 00:20:01,356 --> 00:20:04,356 So on the one hand I'm actually doing things a little less 484 00:20:04,356 --> 00:20:08,296 efficiently in PHP as I could be here because I'm just trying 485 00:20:08,296 --> 00:20:10,626 to make it map as closely as possible 486 00:20:10,626 --> 00:20:12,236 to Problem Set 6's C code. 487 00:20:12,506 --> 00:20:13,596 But also realize this. 488 00:20:13,596 --> 00:20:16,536 We are paying a fundamental penalty, not the result so much 489 00:20:16,536 --> 00:20:20,256 of PHP, but the result of PHP being an interpreted language. 490 00:20:20,386 --> 00:20:23,476 Whereas C is compiled by GCC into zeros and ones 491 00:20:23,476 --> 00:20:25,856 that the underlying CPU understands, 492 00:20:26,186 --> 00:20:28,556 well PHP is not compiled into anything. 493 00:20:28,736 --> 00:20:31,536 Rather, we are running a program -- php dot exe -- 494 00:20:31,616 --> 00:20:32,926 we're passing it all of those lines 495 00:20:32,926 --> 00:20:36,506 of codes we just plus speller and saying please figure 496 00:20:36,506 --> 00:20:38,026 out how to execute these. 497 00:20:38,026 --> 00:20:40,726 And an interpreter pretty much goes top to bottom, 498 00:20:40,726 --> 00:20:44,066 left to right, and converts as best it can each line 499 00:20:44,096 --> 00:20:46,446 into the equivalent zeros and ones, but on the fly. 500 00:20:46,706 --> 00:20:48,186 And if I run my speller again, 501 00:20:48,406 --> 00:20:50,056 the interpreter has to reinterpret it. 502 00:20:50,056 --> 00:20:52,716 If I run my interpreter a third time, it has to reinterpret it. 503 00:20:52,946 --> 00:20:54,466 So one of the disadvantages then 504 00:20:54,466 --> 00:20:56,956 of an interpreted language is you might be doing all 505 00:20:56,956 --> 00:21:00,556 of this work right in the very front to interpret your program, 506 00:21:00,796 --> 00:21:02,486 but then you're throwing those results away 507 00:21:02,796 --> 00:21:04,516 because the program is not saved. 508 00:21:04,686 --> 00:21:06,116 It's because it's not compiled. 509 00:21:06,426 --> 00:21:08,786 Now let's fast forward to the context of the web. 510 00:21:09,036 --> 00:21:11,726 So the reality in the world of the web is 511 00:21:11,726 --> 00:21:14,526 that computers are not the slowest part. 512 00:21:14,656 --> 00:21:17,276 We have the whole internet between us and someone else 513 00:21:17,276 --> 00:21:18,666 across the country if we're trying 514 00:21:18,666 --> 00:21:19,986 to have two computers communicate. 515 00:21:20,146 --> 00:21:22,766 And so there's a lot of other delays that actually might mean 516 00:21:22,966 --> 00:21:25,446 that you know what, it's okay if it doesn't take a split second, 517 00:21:25,446 --> 00:21:26,546 but two split seconds. 518 00:21:26,546 --> 00:21:27,286 All right. 519 00:21:27,316 --> 00:21:29,626 So we might be able to tolerate that performance penalty. 520 00:21:29,626 --> 00:21:32,986 And also in web servers, which we're about to go back to, 521 00:21:33,216 --> 00:21:34,196 you can actually cache PHP. 522 00:21:34,476 --> 00:21:39,596 So you can enable a feature whereby once a PHP file is 523 00:21:39,596 --> 00:21:42,126 interpreted once, the computer -- the web server -- 524 00:21:42,126 --> 00:21:45,936 will actually remember how to do that again so as to save time. 525 00:21:46,026 --> 00:21:48,486 And so you will find that as super majority 526 00:21:48,486 --> 00:21:50,516 of start ups these days of websites 527 00:21:50,516 --> 00:21:53,896 on the web actually do use these high level languages like PHP 528 00:21:53,896 --> 00:21:56,346 and Python and Ruby and Perl and even others 529 00:21:56,676 --> 00:21:59,046 because C is the wrong language with which 530 00:21:59,046 --> 00:22:00,806 to implement most websites. 531 00:22:00,806 --> 00:22:03,186 Once you're at the point of Facebook scale, Google scale, 532 00:22:03,186 --> 00:22:04,646 and even a little smaller than that, 533 00:22:04,876 --> 00:22:07,156 certainly there are small problems that you might want 534 00:22:07,156 --> 00:22:10,536 to solve at the very low level with C, doing database queries 535 00:22:10,846 --> 00:22:13,506 or searching graphs of social networks and the like. 536 00:22:13,796 --> 00:22:16,666 But for implementing something that just spits out html 537 00:22:16,666 --> 00:22:19,256 and spits out a stock portfolio and even prints out your list 538 00:22:19,256 --> 00:22:21,916 of friends, by all means is and interpreted language 539 00:22:21,916 --> 00:22:25,156 like PHP a better choice than C. Case and point, 540 00:22:25,156 --> 00:22:26,326 it took just a few seconds 541 00:22:26,366 --> 00:22:28,606 to implement the entirety of a week's work. 542 00:22:28,836 --> 00:22:30,286 So just realize these tradeoffs. 543 00:22:30,556 --> 00:22:31,796 So let's transition then 544 00:22:31,796 --> 00:22:34,286 to actually running PHP code on a web server. 545 00:22:34,286 --> 00:22:35,786 Right now I ran it at the command line, 546 00:22:35,956 --> 00:22:37,506 which is absolutely possible with one 547 00:22:37,506 --> 00:22:38,636 of these interpreted languages. 548 00:22:38,876 --> 00:22:41,936 But if I instead move my PHP files 549 00:22:42,036 --> 00:22:45,276 into my public underscore html directory or somewhere 550 00:22:45,276 --> 00:22:48,686 like that, I can actually have the web server execute my PHP 551 00:22:48,786 --> 00:22:51,426 code so that I the human no longer need 552 00:22:51,426 --> 00:22:52,606 to manually type commands. 553 00:22:52,606 --> 00:22:55,916 And this is perfect because when a user visits CS50 dot net, 554 00:22:55,916 --> 00:22:58,466 obviously we don't want a human having to run a program saying, 555 00:22:58,726 --> 00:22:59,776 'respond to this user'. 556 00:23:00,016 --> 00:23:01,846 It's all automated by the web server. 557 00:23:02,286 --> 00:23:05,916 So let's then transition back to where we left off last week 558 00:23:06,046 --> 00:23:09,506 on something like implementing the freshman intramural site. 559 00:23:09,706 --> 00:23:13,106 So let me go into my jharvard directory, public html, 560 00:23:13,336 --> 00:23:15,286 and one of the files I have in here today -- 561 00:23:15,286 --> 00:23:17,396 it's all on the CS50 dot net slash lectures -- 562 00:23:17,686 --> 00:23:20,236 is froshims0 dot php. 563 00:23:20,436 --> 00:23:24,896 And this is a simple version of where we left off last week. 564 00:23:24,896 --> 00:23:26,536 So notice we have some familiar stuff. 565 00:23:26,536 --> 00:23:27,776 Now doc type just means, 566 00:23:27,996 --> 00:23:29,856 here comes a webpage written in html5. 567 00:23:29,916 --> 00:23:32,996 The html tag is the root element which says 568 00:23:32,996 --> 00:23:36,106 to the browser more explicitly, here comes the actual webpage. 569 00:23:36,106 --> 00:23:38,546 The head of the page comes next, then the body, 570 00:23:38,736 --> 00:23:40,756 and the real interesting stuff typically happens 571 00:23:40,756 --> 00:23:42,156 in the body of a webpage. 572 00:23:42,296 --> 00:23:45,956 Now we haven't seen all of this html in detail yet, 573 00:23:46,266 --> 00:23:49,336 but frankly it's pretty easy to pick up as you go, 574 00:23:49,336 --> 00:23:51,346 certainly just by Googling things you don't understand. 575 00:23:51,546 --> 00:23:53,646 Div is this invisible division of the page. 576 00:23:53,646 --> 00:23:57,526 Style allows you to specify some CSS, cascading style sheets. 577 00:23:57,796 --> 00:23:59,106 And this one kind of says it all, 578 00:23:59,106 --> 00:24:01,506 text align colon center means everything 579 00:24:01,506 --> 00:24:03,886 on this page should be centered and so forth. 580 00:24:04,016 --> 00:24:06,886 So today and henceforth we won't focus so much on html 581 00:24:07,126 --> 00:24:08,996 but rather how this is functioning 582 00:24:09,146 --> 00:24:10,426 as a dynamic website. 583 00:24:10,486 --> 00:24:12,286 And the most interesting tag toward 584 00:24:12,286 --> 00:24:13,856 that end is this guy here. 585 00:24:14,136 --> 00:24:15,646 So we saw forms last week. 586 00:24:15,646 --> 00:24:17,886 And a form has an action which is the URL 587 00:24:17,886 --> 00:24:21,006 to which the form should be submitted or partial URL 588 00:24:21,006 --> 00:24:22,096 if it's on the same server. 589 00:24:22,336 --> 00:24:23,286 And then there's two methods. 590 00:24:23,466 --> 00:24:25,306 And we've seen get and we've seen post. 591 00:24:25,306 --> 00:24:28,056 And for now the simple distinction is GET requests end 592 00:24:28,056 --> 00:24:28,556 up where? 593 00:24:28,676 --> 00:24:29,806 Where do the parameters end up? 594 00:24:30,806 --> 00:24:32,526 In the URL, in the address bar. 595 00:24:32,526 --> 00:24:35,496 And so GET is generally to be avoided for anything sensitive. 596 00:24:35,496 --> 00:24:37,396 You don't want passwords, credit card numbers, 597 00:24:37,396 --> 00:24:40,766 anything personal going into the address bar with a GET request 598 00:24:41,106 --> 00:24:43,106 if only because it's unnecessary. 599 00:24:43,336 --> 00:24:46,136 Two, it then lends itself to prying eyes, roommates 600 00:24:46,136 --> 00:24:48,376 and such sitting down and looking at your browser history. 601 00:24:48,376 --> 00:24:49,516 It's just bad practice. 602 00:24:49,516 --> 00:24:52,516 So POST is generally preferred for anything sensitive, 603 00:24:52,516 --> 00:24:54,756 as in the case of personal information. 604 00:24:54,996 --> 00:24:56,096 So what does this thing look like? 605 00:24:56,096 --> 00:24:57,576 Well let's go over to a browser. 606 00:24:57,906 --> 00:25:00,846 I am in, recall, local host, which refers 607 00:25:00,846 --> 00:25:03,336 to the appliance, slash tilde jharvard. 608 00:25:03,626 --> 00:25:05,626 And I'm going to go into my froshims directory, 609 00:25:05,626 --> 00:25:07,236 froshim0 dot php. 610 00:25:07,236 --> 00:25:09,976 And this should look familiar from last week. 611 00:25:09,976 --> 00:25:11,286 So register fro froshims. 612 00:25:11,536 --> 00:25:13,756 The fact that I'm using a table is just because I wanted this 613 00:25:13,756 --> 00:25:16,046 to kind of line up nicely with rows and columns. 614 00:25:16,256 --> 00:25:18,166 But let's see what happens when I register. 615 00:25:18,166 --> 00:25:20,196 This form, when I click register, 616 00:25:20,456 --> 00:25:24,316 is going to get submitted to register0 dot php. 617 00:25:24,316 --> 00:25:27,376 So let's take a look at what we should expect there. 618 00:25:27,376 --> 00:25:28,916 Let me open register0. 619 00:25:29,606 --> 00:25:32,946 And this is actually a very simple file. 620 00:25:33,006 --> 00:25:35,186 So the stuff at the top, realize, is just comments. 621 00:25:35,496 --> 00:25:38,366 And the only reason I put my comments inside 622 00:25:38,476 --> 00:25:42,416 of PHP braces is just so that the user doesn't actually see 623 00:25:42,416 --> 00:25:42,976 the results. 624 00:25:43,246 --> 00:25:47,356 Realize that anytime PHP or the web server in this case, 625 00:25:47,396 --> 00:25:50,166 sees open bracket question mark, those lines are going 626 00:25:50,166 --> 00:25:52,526 to get interpreted and the output is going 627 00:25:52,526 --> 00:25:53,516 to get sent to the browser. 628 00:25:53,686 --> 00:25:54,876 Well these are just comments. 629 00:25:55,026 --> 00:25:57,466 So there is, by definition, no output, per se. 630 00:25:57,466 --> 00:25:58,396 They're not function calls. 631 00:25:58,396 --> 00:26:00,096 It's not printf or print or echo. 632 00:26:00,396 --> 00:26:01,556 So nothing ends up going. 633 00:26:01,556 --> 00:26:03,676 That gets stripped from the resulting webpage. 634 00:26:03,946 --> 00:26:06,086 But the result is really just some html. 635 00:26:06,086 --> 00:26:08,566 Most of this is html5 except for this line, 636 00:26:08,966 --> 00:26:12,166 which is a new function, a very helpful function PHP at least 637 00:26:12,166 --> 00:26:15,586 for diagnostic purposes called print r. The R is recursive. 638 00:26:15,856 --> 00:26:18,206 So what I'm saying here is go ahead 639 00:26:18,206 --> 00:26:20,836 when you receive a request from a user. 640 00:26:21,146 --> 00:26:24,776 Create this very, very basic webpage with a head and a body. 641 00:26:24,776 --> 00:26:27,666 And go ahead and print recursively the contents 642 00:26:27,956 --> 00:26:31,646 of a special variable called dollar sign underscore post. 643 00:26:31,886 --> 00:26:34,666 And notice that this is indeed PHP because I have flanked it 644 00:26:34,666 --> 00:26:38,156 with the open bracket question mark on both sides here. 645 00:26:38,406 --> 00:26:40,366 And this is a new tag too for most of you. 646 00:26:40,366 --> 00:26:43,046 The pretag just means use preformatted text. 647 00:26:43,046 --> 00:26:45,316 Use monospaced font so that it actually looks 648 00:26:45,316 --> 00:26:47,776 like programming code and not like Times New Roman 649 00:26:47,776 --> 00:26:48,576 or something like that. 650 00:26:49,006 --> 00:26:51,216 So this is not a useful webpage yet. 651 00:26:51,216 --> 00:26:54,096 This is not a freshman intramural registration system. 652 00:26:54,286 --> 00:26:57,286 It's really just to see what's going on underneath the hood. 653 00:26:57,476 --> 00:26:58,896 So let me go back to my browser. 654 00:26:58,896 --> 00:27:02,696 And let me go ahead and type in, for instance, David, 655 00:27:02,996 --> 00:27:04,536 captain, male, Matthews. 656 00:27:04,936 --> 00:27:05,826 Click register. 657 00:27:05,826 --> 00:27:08,816 And what that webpage is doing for us is simply this. 658 00:27:09,276 --> 00:27:12,736 It's showing us that dollar sign underscore post is apparently 659 00:27:12,736 --> 00:27:13,296 in array. 660 00:27:13,296 --> 00:27:16,136 And inside of it are a bunch of key value pairs. 661 00:27:16,366 --> 00:27:19,566 Those key value pairs are name equals David, captain on, 662 00:27:19,566 --> 00:27:21,726 gender M, dorm Matthews. 663 00:27:21,926 --> 00:27:24,296 So here's what's really powerful about languages like PHP. 664 00:27:24,296 --> 00:27:26,266 I didn't have to do a thing. 665 00:27:26,566 --> 00:27:29,396 I simply called the function that printed out the contents 666 00:27:29,426 --> 00:27:33,166 of a default variable that was automatically populated for me 667 00:27:33,166 --> 00:27:37,376 by the web server and by PHP so that now I can focus just 668 00:27:37,486 --> 00:27:39,506 on getting the job done that I care about, 669 00:27:39,506 --> 00:27:40,496 registering this user. 670 00:27:40,766 --> 00:27:43,496 By contrast, in a language like C, you would actually have 671 00:27:43,526 --> 00:27:45,736 to parse all of those http headers. 672 00:27:45,956 --> 00:27:46,986 You would then have to figure 673 00:27:46,986 --> 00:27:49,346 out that oh the question mark means a parameter. 674 00:27:49,346 --> 00:27:51,136 The ampersand means multiple parameters. 675 00:27:51,286 --> 00:27:53,826 You would have to do all of that crazy string manipulation 676 00:27:53,826 --> 00:27:57,716 yourself when now all I care about is getting real work done. 677 00:27:57,716 --> 00:28:00,026 And that's what these languages tend to facilitate. 678 00:28:00,306 --> 00:28:02,826 So interesting, too, is there was no mention of the word 'on' 679 00:28:02,896 --> 00:28:05,326 in the html, but this is actually the convention. 680 00:28:05,326 --> 00:28:07,406 When you check a checkbox, the value that's sent 681 00:28:07,406 --> 00:28:10,536 from a browser apparently is literally the word 'on'. 682 00:28:11,156 --> 00:28:12,526 So what are these super globals? 683 00:28:12,526 --> 00:28:14,146 Well we're actually going to see a few of them. 684 00:28:14,356 --> 00:28:15,896 So we've seen POST. 685 00:28:15,896 --> 00:28:17,126 And we'll continue using that. 686 00:28:17,306 --> 00:28:19,046 There's an analogue for GET requests, 687 00:28:19,096 --> 00:28:20,396 dollar sign underscore get. 688 00:28:20,676 --> 00:28:22,706 There's going to be another one for something called cookies, 689 00:28:22,706 --> 00:28:24,986 which we'll talk briefly about this week and we'll see 690 00:28:24,986 --> 00:28:26,486 in more detail probably next. 691 00:28:26,746 --> 00:28:28,486 There's dollar sign underscore server, 692 00:28:28,646 --> 00:28:30,726 which actually stores some boring information, 693 00:28:30,946 --> 00:28:33,986 but some interesting information too like the user's IP address 694 00:28:34,396 --> 00:28:36,026 and the browser that they're using. 695 00:28:36,026 --> 00:28:39,486 So if you actually want to get a sense of who your users are 696 00:28:39,486 --> 00:28:40,606 or verify that they're 697 00:28:40,686 --> 00:28:43,196 in Harvard dot edu's IP address range, 698 00:28:43,486 --> 00:28:44,606 you can use tricks like that. 699 00:28:44,886 --> 00:28:46,216 And then the most magical one, 700 00:28:46,216 --> 00:28:49,176 I daresay is dollar sign underscore session. 701 00:28:49,456 --> 00:28:54,386 Recall that when you visit a webpage on the internet, 702 00:28:55,016 --> 00:28:56,436 even something simple like this -- 703 00:28:56,436 --> 00:29:02,506 actually let's go to CS50 dot net slash lectures. 704 00:29:02,846 --> 00:29:04,976 And I hit enter. 705 00:29:05,336 --> 00:29:09,206 And it proceeds very slowly to connect. 706 00:29:10,846 --> 00:29:11,326 There we go. 707 00:29:11,446 --> 00:29:13,576 Come on. [inaudible] network. 708 00:29:13,876 --> 00:29:15,516 This is the trick. 709 00:29:15,516 --> 00:29:17,036 If you guys have experienced this too 710 00:29:17,036 --> 00:29:18,886 where you network connection kind of dies, 711 00:29:19,466 --> 00:29:20,776 so do service network restart. 712 00:29:21,586 --> 00:29:22,936 There we go. 713 00:29:23,436 --> 00:29:25,006 So notice -- this is actually perfect. 714 00:29:25,076 --> 00:29:26,656 Notice how long it's taking, right. 715 00:29:26,726 --> 00:29:28,366 And notice that there's the spinning icon 716 00:29:28,366 --> 00:29:29,676 in the top of the page there. 717 00:29:30,076 --> 00:29:32,646 And in just a moment we'll see the results. 718 00:29:32,646 --> 00:29:33,896 But let's simulate the results. 719 00:29:33,896 --> 00:29:36,466 And then at some point the spinning thing stops, right. 720 00:29:36,466 --> 00:29:39,356 So this is actually an important visual detail. 721 00:29:39,596 --> 00:29:43,546 When that progress bar stops, the end result is of course 722 00:29:43,546 --> 00:29:45,176 that the webpage has finished loading. 723 00:29:45,176 --> 00:29:47,916 So let's pick apparently more reliable websites. 724 00:29:48,136 --> 00:29:53,726 And that's just -- oh, maybe it's in here. 725 00:29:55,316 --> 00:29:56,086 All right. 726 00:29:56,086 --> 00:30:00,526 We will -- let's pretend Google dot come just came up 727 00:30:01,186 --> 00:30:02,986 and the spinning thing stopped. 728 00:30:03,056 --> 00:30:04,976 So the takeaway here and the only message I'm trying 729 00:30:04,976 --> 00:30:08,366 to communicate is that http is what we'll call stateless. 730 00:30:08,466 --> 00:30:10,326 As soon as a webpage finishes loading, 731 00:30:10,546 --> 00:30:13,716 that means that all the html -- all of the gifs and jpegs, 732 00:30:13,716 --> 00:30:15,476 all of the audio, all of the flash files, 733 00:30:15,476 --> 00:30:16,726 whatever composes the page -- 734 00:30:17,006 --> 00:30:19,436 has finished downloading so the little spinning wheel 735 00:30:19,436 --> 00:30:21,256 in whatever your browser is stops. 736 00:30:21,256 --> 00:30:24,156 And the browser at that point has stopped talking 737 00:30:24,156 --> 00:30:24,856 to the server. 738 00:30:24,966 --> 00:30:26,936 This is in contrast to things 739 00:30:26,936 --> 00:30:28,906 like an instant messaging program like GChat 740 00:30:29,206 --> 00:30:31,786 which obviously maintains a constant connection somehow 741 00:30:32,026 --> 00:30:34,366 so that you keep getting instant messages again and again. 742 00:30:34,366 --> 00:30:36,066 And even Facebook is very laden 743 00:30:36,066 --> 00:30:37,896 with something called JavaScript and AJAX. 744 00:30:38,186 --> 00:30:40,336 So that even when your little spinning icon stops 745 00:30:40,336 --> 00:30:43,346 on Facebook dot com, it turns out behind the scenes more 746 00:30:43,346 --> 00:30:45,166 and more http requests are being made 747 00:30:45,336 --> 00:30:48,686 so that you can get these little flashes on your screen 748 00:30:48,686 --> 00:30:51,146 like someone likes your photo or someone has commented. 749 00:30:51,406 --> 00:30:52,716 But in traditional webpages 750 00:30:52,716 --> 00:30:54,296 such as the ones we're writing thus far, 751 00:30:54,576 --> 00:30:56,886 once that spinning icon stops, that's it. 752 00:30:56,886 --> 00:30:58,566 You're no longer talking to the server. 753 00:30:58,786 --> 00:31:00,026 So that begs the question, 754 00:31:00,026 --> 00:31:01,956 how do you possibly implement something 755 00:31:01,956 --> 00:31:04,596 like say a shopping cart 756 00:31:04,596 --> 00:31:07,996 on Amazon dot com whereby I might go to a page of book. 757 00:31:07,996 --> 00:31:10,436 I might click submit to add something to my cart. 758 00:31:10,436 --> 00:31:11,656 And then that's it. 759 00:31:11,656 --> 00:31:14,016 It's as though I've disconnected from the server on Amazon 760 00:31:14,016 --> 00:31:15,786 because my little icon stopped spinning. 761 00:31:16,016 --> 00:31:18,746 And yet I can somehow click to another page and another page 762 00:31:18,746 --> 00:31:19,706 and keep adding things 763 00:31:19,736 --> 00:31:22,946 to my shopping cart even though I don't have this persistent 764 00:31:23,196 --> 00:31:24,376 connection to the server. 765 00:31:24,666 --> 00:31:27,896 So the means by which that can be implemented in PHP is 766 00:31:27,896 --> 00:31:31,636 by storing inside of this special variable called dollar 767 00:31:31,636 --> 00:31:34,886 sign underscore session anything that you want 768 00:31:34,886 --> 00:31:38,156 to persist even across page loads. 769 00:31:38,366 --> 00:31:39,376 So in short, you can think 770 00:31:39,376 --> 00:31:41,736 of dollar sign underscore session as a shopping cart. 771 00:31:41,876 --> 00:31:43,706 And we might not actually store products in it, 772 00:31:43,706 --> 00:31:45,586 but for Problem Set 7, we're going to store 773 00:31:45,586 --> 00:31:48,696 at least one thing -- the ID of the user who's logged in. 774 00:31:48,976 --> 00:31:52,466 So that you don't have to on every page the user visits -- 775 00:31:52,466 --> 00:31:54,486 for CS50 Finance you don't have to ask him 776 00:31:54,486 --> 00:31:55,526 or her, 'Are you logged in?' 777 00:31:55,526 --> 00:31:56,206 'Are you logged in?' 778 00:31:56,206 --> 00:31:56,846 'Are you logged in?' 779 00:31:57,046 --> 00:31:58,466 You can answer that question yourself 780 00:31:58,466 --> 00:32:01,826 by storing those answers in this shopping cart of sorts. 781 00:32:01,826 --> 00:32:04,946 And that's implemented by way of something called cookies. 782 00:32:04,996 --> 00:32:10,146 But we'll see how we get there with these next examples. 783 00:32:10,146 --> 00:32:12,456 So let's open up a little something more sophisticated, 784 00:32:12,456 --> 00:32:14,826 froshims1 dot php. 785 00:32:14,826 --> 00:32:17,866 The form is identical except for this here. 786 00:32:17,906 --> 00:32:20,676 This one's going to submit to register1 dot php. 787 00:32:20,676 --> 00:32:24,596 So let's see what register1 does that register0 did not. 788 00:32:24,786 --> 00:32:27,176 Well this is what we did see on Wednesday. 789 00:32:27,636 --> 00:32:29,976 So we have these conditions at the top. 790 00:32:29,976 --> 00:32:31,026 And notice all this stuff. 791 00:32:31,026 --> 00:32:32,376 Even though most of this is comments, 792 00:32:32,666 --> 00:32:34,466 notice we've got open bracket question mark. 793 00:32:34,466 --> 00:32:36,286 So that means here comes some php code. 794 00:32:36,526 --> 00:32:37,496 These are just comments. 795 00:32:37,496 --> 00:32:39,086 So that's as though they're not even there. 796 00:32:39,336 --> 00:32:40,596 This is a comment too. 797 00:32:40,596 --> 00:32:42,176 So that doesn't really do anything. 798 00:32:42,376 --> 00:32:46,196 But these several lines of an if condition do work some magic. 799 00:32:46,196 --> 00:32:52,396 So if the empty function returns true when passed the name field 800 00:32:52,726 --> 00:32:56,226 in the POST associative array then I'm going 801 00:32:56,226 --> 00:32:59,826 to apparently execute the code inside of these curly braces 802 00:33:00,186 --> 00:33:00,906 which have what affect? 803 00:33:01,326 --> 00:33:03,856 Well this is the way in web programming 804 00:33:04,076 --> 00:33:05,856 to send the user to another page. 805 00:33:05,856 --> 00:33:07,096 You've probably seen this before. 806 00:33:07,276 --> 00:33:09,026 You go to some website, but it redirects you 807 00:33:09,026 --> 00:33:11,146 to some other page either because the page has moved 808 00:33:11,146 --> 00:33:12,276 or they want you to log in. 809 00:33:12,556 --> 00:33:15,146 That is because you can make the browser say, hunh-unh. 810 00:33:15,146 --> 00:33:16,146 There's nothing here. 811 00:33:16,146 --> 00:33:19,526 Instead go to this location, specifically this URL. 812 00:33:19,996 --> 00:33:22,836 So this one-liner is just my way of saying, you know what, 813 00:33:22,836 --> 00:33:25,346 if the user didn't give me a name or their gender 814 00:33:25,346 --> 00:33:26,806 or their dorm, forget it. 815 00:33:26,876 --> 00:33:29,916 Redirect them back to froshims1 dot php 816 00:33:30,126 --> 00:33:32,906 so that they can presumably fill in those blanks. 817 00:33:33,206 --> 00:33:34,626 And there's multiple ways to do this, 818 00:33:34,686 --> 00:33:37,806 but realize the empty function is a pretty neat and simple way 819 00:33:37,806 --> 00:33:41,486 of checking the value inside of one of these associative arrays, 820 00:33:41,726 --> 00:33:43,766 in this case name, then gender, then dorm. 821 00:33:43,926 --> 00:33:45,926 And now down here, notice 822 00:33:45,926 --> 00:33:50,126 that this html is only displayed to the user. 823 00:33:50,126 --> 00:33:52,966 It's only sent to the browser in what circumstances apparently? 824 00:33:53,516 --> 00:33:55,756 [Pause] 825 00:33:56,256 --> 00:33:57,386 >>Logically when is 826 00:33:57,386 --> 00:34:02,946 that highlight html actually sent to the user? 827 00:34:02,946 --> 00:34:03,936 >>[inaudible]. 828 00:34:03,936 --> 00:34:04,086 >>Sorry. 829 00:34:04,086 --> 00:34:04,276 >>[inaudible]. 830 00:34:04,276 --> 00:34:04,856 >>Exactly. 831 00:34:04,856 --> 00:34:06,666 If all those initial things are false, 832 00:34:06,766 --> 00:34:08,686 in other words the user has given me their name 833 00:34:08,686 --> 00:34:11,126 and has given me their gender and has given me their dorm, 834 00:34:11,376 --> 00:34:14,676 then obviously just logically this if condition is not going 835 00:34:14,736 --> 00:34:16,176 to have its lines executed. 836 00:34:16,376 --> 00:34:17,856 So we keep going, keep going. 837 00:34:17,856 --> 00:34:19,426 PHP gets here and says, 'Oh that's it for PHP.' 838 00:34:19,426 --> 00:34:22,766 And even though we're comingling PHP and html, 839 00:34:22,766 --> 00:34:26,176 what webservers will do is as soon as it sees raw html, 840 00:34:26,416 --> 00:34:28,036 it's just going to send it to the browser 841 00:34:28,036 --> 00:34:30,116 as though this were a dot html file. 842 00:34:30,456 --> 00:34:32,676 So we're obviously not doing anything of interest now 843 00:34:32,676 --> 00:34:34,346 with this data, let's at least provide the user 844 00:34:34,346 --> 00:34:35,276 with some more feedback. 845 00:34:35,716 --> 00:34:37,596 So let's go into froshims2. 846 00:34:37,596 --> 00:34:41,296 This too is identical except for this one change. 847 00:34:41,546 --> 00:34:43,916 So froshims2 is going to submit to register2. 848 00:34:43,916 --> 00:34:48,596 So let's go ahead and focus on register2 and we now see this, 849 00:34:48,926 --> 00:34:50,036 a little more dynamism. 850 00:34:50,226 --> 00:34:53,036 Notice that I don't have to have my PHP code all the way 851 00:34:53,036 --> 00:34:54,096 at the top of the file. 852 00:34:54,416 --> 00:34:56,356 Rather, I can comingle it here, 853 00:34:56,966 --> 00:34:58,496 especially for something so simple. 854 00:34:58,756 --> 00:35:01,386 So notice here, no matter what this time, I'm going to spit 855 00:35:01,386 --> 00:35:04,966 out this html doc type and the html element and head and title 856 00:35:04,966 --> 00:35:08,456 and close the head and open the body and then I'm going 857 00:35:08,456 --> 00:35:10,776 to comingle, again some html and PHP. 858 00:35:11,166 --> 00:35:12,666 So this puts me into php mode. 859 00:35:12,666 --> 00:35:15,296 And I'm asking the question, if the name is empty 860 00:35:15,296 --> 00:35:19,046 or gender is empty or dorm is empty, then notice the colon. 861 00:35:19,126 --> 00:35:21,456 C did not have this syntax, but PHP does. 862 00:35:21,756 --> 00:35:26,506 The colon means even though this question mark closed brace is 863 00:35:26,506 --> 00:35:30,836 there, go ahead and execute anything below this line 864 00:35:30,836 --> 00:35:32,976 because this condition was apparently just true. 865 00:35:33,246 --> 00:35:34,996 So in this case, I'm apparently literally going 866 00:35:34,996 --> 00:35:36,226 to send the string to the user. 867 00:35:36,226 --> 00:35:37,976 You must provide your name, gender, and dorm. 868 00:35:37,976 --> 00:35:41,276 Go back. And now notice I'm using the anchor tag 869 00:35:41,496 --> 00:35:42,786 so that this time I'm not sort 870 00:35:42,786 --> 00:35:44,326 of presumptuously redirecting them. 871 00:35:44,366 --> 00:35:45,946 I'm instead giving them an error message 872 00:35:46,146 --> 00:35:48,776 and then giving them a link with which to go back 873 00:35:49,036 --> 00:35:50,896 to the previous screen to fix this problem. 874 00:35:50,896 --> 00:35:52,196 Before, didn't even explain it. 875 00:35:52,496 --> 00:35:55,136 Else, if that's not the case, notice the other colon here. 876 00:35:55,376 --> 00:35:56,936 I just tell the user, 'You are registered.' 877 00:35:56,936 --> 00:35:57,716 Well not really. 878 00:35:57,916 --> 00:36:00,166 Not really because I'm clearly not doing anything 879 00:36:00,166 --> 00:36:01,636 with their form submission just yet. 880 00:36:01,636 --> 00:36:04,026 And then notice this new syntax endif. 881 00:36:04,206 --> 00:36:05,536 It is indeed one word. 882 00:36:05,756 --> 00:36:07,726 C did not have this, but PHP did. 883 00:36:08,166 --> 00:36:09,606 So let's see what the end result here is. 884 00:36:09,606 --> 00:36:13,286 Let me go into froshims2 on local host 885 00:36:13,536 --> 00:36:14,716 in John Harvard's account. 886 00:36:15,486 --> 00:36:17,076 And this is froshims2. 887 00:36:17,296 --> 00:36:19,106 Let me go ahead and I'll just give you my name. 888 00:36:19,106 --> 00:36:20,046 That's all you need. 889 00:36:20,046 --> 00:36:23,266 Register. Oh, I broke it. 890 00:36:23,446 --> 00:36:24,396 Okay, line 20. 891 00:36:24,586 --> 00:36:26,476 So here's an example of how to debug PHP code. 892 00:36:26,536 --> 00:36:28,436 Much like GCC spits out error messages, 893 00:36:28,436 --> 00:36:30,236 this is actually a little more clear. 894 00:36:30,236 --> 00:36:31,676 There's some kind of syntax error. 895 00:36:31,896 --> 00:36:34,156 It expected a colon on line 20. 896 00:36:34,476 --> 00:36:35,876 So let's see where I screwed up. 897 00:36:35,876 --> 00:36:38,306 This is line 20 here. 898 00:36:39,356 --> 00:36:43,436 And I left off a closed parenthesis there. 899 00:36:44,096 --> 00:36:46,516 So let me go back to the browser, reload. 900 00:36:47,196 --> 00:36:47,556 All right. 901 00:36:47,646 --> 00:36:48,366 So there we have. 902 00:36:48,366 --> 00:36:51,256 I'm at register2 dot php according to the URL. 903 00:36:51,256 --> 00:36:52,636 And I indeed got yelled at. 904 00:36:52,766 --> 00:36:56,006 So I can click 'go back' and now I'm back at froshims2. 905 00:36:56,166 --> 00:36:59,396 So this is better, but it's definitely the best interface. 906 00:36:59,396 --> 00:37:01,826 Because the user now has been advised what's wrong, 907 00:37:01,826 --> 00:37:03,066 but they still have to hit back. 908 00:37:03,346 --> 00:37:04,936 Hopefully we can do a little better than this. 909 00:37:05,356 --> 00:37:10,886 So let me go back this time to let's say froshims3, 910 00:37:10,966 --> 00:37:15,106 which will give us a little form like this 911 00:37:15,576 --> 00:37:17,066 that submits to register3. 912 00:37:17,386 --> 00:37:19,556 So let's continue that story in register3. 913 00:37:20,156 --> 00:37:22,196 And now this one's getting a little -- 914 00:37:22,196 --> 00:37:24,426 oh actually we did tease you with this one here. 915 00:37:24,426 --> 00:37:26,136 Let's actually do something with the results. 916 00:37:26,436 --> 00:37:29,856 So in this case here, notice that I again have some PHP code. 917 00:37:29,856 --> 00:37:31,916 And if the name's not empty and gender's not empty 918 00:37:31,916 --> 00:37:34,096 and dorm is not empty, here was our trick 919 00:37:34,386 --> 00:37:35,686 for actually sending mail. 920 00:37:35,856 --> 00:37:37,296 So most of these fields are kind 921 00:37:37,296 --> 00:37:38,836 of self explanatory especially now 922 00:37:38,836 --> 00:37:40,476 that we know this is just a variable. 923 00:37:40,476 --> 00:37:41,416 This is just a variable. 924 00:37:41,636 --> 00:37:42,586 This is just a variable. 925 00:37:42,806 --> 00:37:44,816 What's the role of all these dots? 926 00:37:45,146 --> 00:37:45,566 Did we say? 927 00:37:45,566 --> 00:37:45,633 >>[inaudible]. 928 00:37:45,633 --> 00:37:46,286 >>What's that? 929 00:37:47,456 --> 00:37:48,506 >>Put the strings together... 930 00:37:49,186 --> 00:37:50,286 >>Yeah, put the strings together. 931 00:37:50,286 --> 00:37:52,486 This is the so called concatenation operator. 932 00:37:52,486 --> 00:37:54,276 So this means put this string, then this string, 933 00:37:54,276 --> 00:37:56,626 then this string and make one big string out of them. 934 00:37:56,866 --> 00:37:58,856 I could have just written the whole thing on one line, 935 00:37:58,856 --> 00:38:01,496 but a lot of people would argue stylistically this is a little 936 00:38:01,496 --> 00:38:02,146 more readable. 937 00:38:02,376 --> 00:38:03,786 And so I've done that here. 938 00:38:04,126 --> 00:38:09,266 Notice, too, in PHP, it is necessary to use double quotes 939 00:38:09,266 --> 00:38:12,726 around things like backslash end just as we necessary 940 00:38:12,726 --> 00:38:15,516 in C. Here I'm using a firm address 941 00:38:15,516 --> 00:38:16,966 of malan at CS50 dot net. 942 00:38:16,966 --> 00:38:18,156 Here I'm calling the mail function. 943 00:38:18,156 --> 00:38:20,646 And so ideally the result of filling 944 00:38:20,646 --> 00:38:22,996 out this form correctly should be an email sent 945 00:38:22,996 --> 00:38:23,836 to me at that address. 946 00:38:23,836 --> 00:38:25,336 Otherwise, we're going to go ahead 947 00:38:25,336 --> 00:38:26,896 and just readdress the user. 948 00:38:27,196 --> 00:38:29,386 But let's step up a little further from here. 949 00:38:29,476 --> 00:38:34,126 Let's go to froshims4 and now we can make this a little 950 00:38:34,126 --> 00:38:35,066 more interesting. 951 00:38:35,066 --> 00:38:41,266 So notice here that froshims4 actually submits to itself. 952 00:38:41,266 --> 00:38:43,116 So this actually is going to lend itself 953 00:38:43,116 --> 00:38:44,366 to a more elegant solution. 954 00:38:44,366 --> 00:38:46,806 There's sort of a bad user interface decision I made 955 00:38:46,806 --> 00:38:49,426 in the previous examples in that I fill out the form. 956 00:38:49,586 --> 00:38:50,416 I submit the form. 957 00:38:50,416 --> 00:38:53,796 I go to a new page -- register1, register2, register3 dot php. 958 00:38:53,796 --> 00:38:57,016 And if there's any error, yes I can redirect the user back, 959 00:38:57,016 --> 00:38:59,356 but there was no explanation as to why they ended 960 00:38:59,356 --> 00:39:00,646 up back at the original page. 961 00:39:00,936 --> 00:39:03,376 And also I'm telling them the error message 962 00:39:03,376 --> 00:39:05,736 in the more recent versions and then they have to hit back. 963 00:39:06,006 --> 00:39:07,546 Right? That's just a bad design. 964 00:39:07,546 --> 00:39:09,806 Why not just provide the user with immediate feedback 965 00:39:09,846 --> 00:39:12,116 on the same screen so that they can then proceed 966 00:39:12,116 --> 00:39:14,026 to fix whatever problem they created. 967 00:39:14,186 --> 00:39:15,346 Right. You might remember websites, 968 00:39:15,346 --> 00:39:16,306 they still exists today, 969 00:39:16,306 --> 00:39:19,936 where not only do they make you see the error message then 970 00:39:19,936 --> 00:39:20,406 click back. 971 00:39:20,686 --> 00:39:24,436 What sometimes happens when you do hit the back button? 972 00:39:24,586 --> 00:39:26,616 The whole form has been emptied. 973 00:39:26,616 --> 00:39:28,236 That's just horrible design. 974 00:39:28,236 --> 00:39:29,846 And this is somewhat browser dependent, 975 00:39:29,846 --> 00:39:30,956 somewhat language dependent. 976 00:39:30,956 --> 00:39:33,736 Let's at least try to avoid these ridiculous designs. 977 00:39:34,066 --> 00:39:38,626 So as a result of this more friendly user interface my file 978 00:39:38,626 --> 00:39:40,236 is going to be a little more complex. 979 00:39:40,236 --> 00:39:41,966 So let's actually see what's going on here. 980 00:39:42,426 --> 00:39:46,116 So in the top of froshims4, I again have some comments. 981 00:39:46,476 --> 00:39:48,796 And now I'm going to have a special check here. 982 00:39:49,206 --> 00:39:52,246 So it turns out you can check -- you can ask a question, 983 00:39:52,466 --> 00:39:54,506 'Was this field even submitted?' 984 00:39:54,506 --> 00:39:57,396 Was it set, so to speak by some html form? 985 00:39:57,676 --> 00:40:01,346 And dollar sign underscore post 'action' means I must have 986 00:40:01,346 --> 00:40:04,686 defined an html form element whose name is action. 987 00:40:04,986 --> 00:40:05,886 This is arbitrary. 988 00:40:05,886 --> 00:40:07,156 We could do this in different ways, 989 00:40:07,156 --> 00:40:09,366 but I chose to go as follows. 990 00:40:09,536 --> 00:40:11,996 If you scroll down and scroll down and scroll down, 991 00:40:12,616 --> 00:40:16,166 notice that this time even though my input button is 992 00:40:16,166 --> 00:40:19,066 of type submit, notice I also gave it a name. 993 00:40:19,156 --> 00:40:20,196 What's the result here? 994 00:40:20,366 --> 00:40:22,836 Well when I click that button, because it has a name, 995 00:40:22,996 --> 00:40:24,816 it's going to get submitted to the server. 996 00:40:25,116 --> 00:40:29,006 So now even if the user does not fill out any of the fields, 997 00:40:29,276 --> 00:40:30,986 they did at least submit the form 998 00:40:30,986 --> 00:40:32,686 by clicking it or by hitting enter. 999 00:40:32,896 --> 00:40:34,816 So no matter what in this scenario, 1000 00:40:34,816 --> 00:40:38,546 at least one parameter is going to be sent to the server, 1001 00:40:38,786 --> 00:40:40,496 in this case called arbitrarily 'action'. 1002 00:40:40,816 --> 00:40:42,666 So I now, the programmer, 1003 00:40:42,666 --> 00:40:46,056 can at least check was the form actually submitted 1004 00:40:46,056 --> 00:40:49,746 or did the user just pull up the URL without filling out a form. 1005 00:40:49,746 --> 00:40:51,146 In other words, I want to distinguish 1006 00:40:51,146 --> 00:40:53,796 between a POST submission and a simple GET. 1007 00:40:53,796 --> 00:40:56,186 Where a GET is just the result of opening 1008 00:40:56,186 --> 00:40:57,456 up this URL on a page. 1009 00:40:57,456 --> 00:41:02,216 In other words, if I go to my browser and I go to froshims4 1010 00:41:02,546 --> 00:41:07,816 and just click it and open this up here. 1011 00:41:07,816 --> 00:41:11,926 Let me -- let me cheat really fast. 1012 00:41:13,356 --> 00:41:15,786 Don't pay attention to what I'm doing here. 1013 00:41:17,726 --> 00:41:21,176 We disabled this in PSet7 for this reason. 1014 00:41:22,086 --> 00:41:24,596 And notice. 1015 00:41:25,136 --> 00:41:27,596 Stand by. 1016 00:41:28,516 --> 00:41:32,886 [ Pause ] 1017 00:41:33,386 --> 00:41:34,316 >>Dammit. Okay. 1018 00:41:34,676 --> 00:41:35,316 One second. 1019 00:41:35,966 --> 00:41:37,966 This is getting awkward. 1020 00:41:38,266 --> 00:41:41,386 Alrighty. Error reporting. 1021 00:41:42,276 --> 00:41:46,996 All right, let's do the -- oh, typo. 1022 00:41:47,596 --> 00:41:49,486 You need to know this. 1023 00:41:51,436 --> 00:41:54,776 All right, do this. 1024 00:41:54,776 --> 00:41:55,156 Oh, dammit. 1025 00:41:55,156 --> 00:41:55,406 All right. 1026 00:41:55,476 --> 00:41:57,946 David is doing something stupid. 1027 00:41:59,356 --> 00:42:03,186 All right, mm-hm. 1028 00:42:03,416 --> 00:42:08,486 Error reporting e-all, e- notice... 1029 00:42:09,516 --> 00:42:12,896 [Laughter] 1030 00:42:13,396 --> 00:42:14,236 >>Fixed, okay. 1031 00:42:15,166 --> 00:42:16,726 So, thank you. 1032 00:42:17,516 --> 00:42:19,946 [Applause] 1033 00:42:20,446 --> 00:42:22,656 >>So PHP is really easy though, really. 1034 00:42:22,736 --> 00:42:26,046 So as an aside, let me explain this 1035 00:42:26,046 --> 00:42:27,696 so that it's not completely lost on us. 1036 00:42:27,696 --> 00:42:30,916 So PHP, long story short, has different levels of errors. 1037 00:42:30,916 --> 00:42:32,196 There's something called an error. 1038 00:42:32,196 --> 00:42:33,346 There's something called a warning. 1039 00:42:33,566 --> 00:42:34,876 There's something called a notice. 1040 00:42:34,876 --> 00:42:37,076 And those are in descending order of severity. 1041 00:42:37,106 --> 00:42:40,166 In C, we made any possible mistake you made just called 1042 00:42:40,166 --> 00:42:40,696 an error. 1043 00:42:40,696 --> 00:42:42,476 And that's why you couldn't even compile your code 1044 00:42:42,476 --> 00:42:43,986 in C sometimes if you had an error. 1045 00:42:43,986 --> 00:42:47,516 PHP has even more layers of severity. 1046 00:42:47,756 --> 00:42:49,156 And so what we typically do 1047 00:42:49,156 --> 00:42:51,406 in the appliance is we disable notices 1048 00:42:51,406 --> 00:42:53,576 because notices aren't really errors, 1049 00:42:53,576 --> 00:42:56,996 but they aren't necessarily perfect lines of code. 1050 00:42:57,296 --> 00:43:00,816 So in this case I cut a corner which meant, 1051 00:43:00,816 --> 00:43:02,486 you really shouldn't do that, 1052 00:43:02,576 --> 00:43:04,636 but the web server yelled at me as a result. 1053 00:43:04,636 --> 00:43:06,556 I've just told the web server, 'Don't yell at me 1054 00:43:06,556 --> 00:43:08,096 and I will fix this properly later.' 1055 00:43:08,356 --> 00:43:15,406 PSet7 you will see in the file called common dot php -- 1056 00:43:15,406 --> 00:43:18,786 you will see that we did exactly the same disabling there. 1057 00:43:19,126 --> 00:43:19,596 All right. 1058 00:43:19,596 --> 00:43:21,426 So what's going to happen in this version? 1059 00:43:21,426 --> 00:43:23,876 I'm going to go ahead to register as David, as captain, 1060 00:43:23,876 --> 00:43:26,286 male from Matthews and click -- 1061 00:43:26,286 --> 00:43:28,496 actually let's leave one of these unfilled. 1062 00:43:28,996 --> 00:43:33,716 Register. Ah, so now still very simple webpage of course, 1063 00:43:33,786 --> 00:43:36,286 but at least now this is a little more dynamic. 1064 00:43:36,286 --> 00:43:39,736 It's still kind of sucky in that I haven't repopulated the form 1065 00:43:39,736 --> 00:43:42,426 fields but at least I've given some immediate feedback. 1066 00:43:42,766 --> 00:43:44,016 So how did this happen? 1067 00:43:44,016 --> 00:43:47,326 Well apparently this form, as we saw in the source code, 1068 00:43:47,326 --> 00:43:51,226 submits not to register something but rather to itself. 1069 00:43:51,506 --> 00:43:53,876 So the same PHP file submits to itself. 1070 00:43:54,106 --> 00:43:55,756 So this is why we need to distinguish 1071 00:43:55,756 --> 00:43:58,896 between was this a GET request or was this a POST request. 1072 00:43:58,896 --> 00:44:01,326 In other words, did the user just type this URL manually 1073 00:44:01,496 --> 00:44:03,436 and end up here in which case there is no error 1074 00:44:03,436 --> 00:44:04,796 because they literally just got here. 1075 00:44:05,156 --> 00:44:06,926 Or did they click the submit button 1076 00:44:06,926 --> 00:44:10,026 in which case they got here by way of a form submission 1077 00:44:10,066 --> 00:44:11,916 in which case we should yell at them. 1078 00:44:12,126 --> 00:44:14,696 So now everything is self contained, hence the need 1079 00:44:14,696 --> 00:44:15,896 for this condition up top. 1080 00:44:15,896 --> 00:44:18,726 So if we now go to froshims4 dot php -- 1081 00:44:18,726 --> 00:44:20,806 you can ignore this notice line up here -- 1082 00:44:21,156 --> 00:44:22,946 let's see what's actually going on. 1083 00:44:22,946 --> 00:44:24,636 So if the form was submitted -- 1084 00:44:25,126 --> 00:44:26,816 so if post action was submitted -- 1085 00:44:27,106 --> 00:44:31,936 and if name is empty or gender is empty or dorm is empty, 1086 00:44:32,216 --> 00:44:33,236 notice that I'm doing this. 1087 00:44:33,576 --> 00:44:37,296 I'm setting a variable called dollar sign error equal to true. 1088 00:44:37,506 --> 00:44:40,166 And just for good measure, I'm going to go ahead and do this. 1089 00:44:40,166 --> 00:44:43,126 I'm going to go ahead and say error by default is false. 1090 00:44:43,636 --> 00:44:45,216 So we do have the notion of Booleans 1091 00:44:45,216 --> 00:44:47,416 and PHP even though we don't say the keyword Bool. 1092 00:44:47,646 --> 00:44:49,906 But if the user screws up in this way, then I'm going 1093 00:44:49,906 --> 00:44:51,896 to ahead and say error gets true. 1094 00:44:52,206 --> 00:44:53,806 So now let's scroll down here. 1095 00:44:54,076 --> 00:44:56,556 And here is where that red text is coming from. 1096 00:44:56,556 --> 00:44:59,206 So the rest of this form is as it's always been. 1097 00:44:59,416 --> 00:45:03,266 But at the very top of my file, I've decided to say quickly 1098 00:45:03,376 --> 00:45:08,116 in PHP, if error is true, then -- thanks to this colon -- 1099 00:45:08,316 --> 00:45:10,126 go ahead and output something called a div, 1100 00:45:10,126 --> 00:45:12,696 whose text color is going to be red according 1101 00:45:12,766 --> 00:45:13,826 to the CSS property here. 1102 00:45:13,826 --> 00:45:16,246 And then just yell at the user, 'You must fill out the form.' 1103 00:45:16,486 --> 00:45:18,496 And then open bracket slash div. 1104 00:45:18,816 --> 00:45:21,396 But notice down here that none of these elements 1105 00:45:21,396 --> 00:45:24,256 as the moment have any kind of default value. 1106 00:45:24,586 --> 00:45:28,456 The reason that this form has not been refilled out for me is 1107 00:45:28,456 --> 00:45:31,516 because I literally have not said give this field a value, 1108 00:45:31,516 --> 00:45:34,376 give that field a value, give something else a value. 1109 00:45:34,376 --> 00:45:37,556 So we might actually need to fix this ourselves. 1110 00:45:37,856 --> 00:45:41,056 So let me go ahead this time and open up froshims5. 1111 00:45:41,326 --> 00:45:44,346 And this one is going to do a little something different. 1112 00:45:44,526 --> 00:45:47,176 Let me go ahead and just paste this in so 1113 00:45:47,176 --> 00:45:49,566 that we can ignore one of those errors for a moment. 1114 00:45:50,006 --> 00:45:51,476 And let me scroll down here. 1115 00:45:52,386 --> 00:45:53,946 Notice that this form also submits 1116 00:45:53,946 --> 00:45:55,736 to froshims5, so to itself. 1117 00:45:56,056 --> 00:45:58,756 Notice that I'm yelling at the user if error is true. 1118 00:45:58,756 --> 00:46:00,046 So that story is identical. 1119 00:46:00,296 --> 00:46:02,426 But now notice what I'm dong that's a little bit different. 1120 00:46:02,426 --> 00:46:03,806 And the font's going to wrap a little bit. 1121 00:46:03,806 --> 00:46:04,546 So let me zoom out. 1122 00:46:05,026 --> 00:46:07,666 Notice now my input tag is almost the same. 1123 00:46:07,666 --> 00:46:09,456 Name is name, coincidentally. 1124 00:46:09,686 --> 00:46:10,516 Type is text. 1125 00:46:10,796 --> 00:46:13,156 But this time I've added an attribute value. 1126 00:46:13,416 --> 00:46:15,296 And notice this little PHP trick here. 1127 00:46:15,296 --> 00:46:17,576 So this is PHP code. 1128 00:46:17,886 --> 00:46:22,536 Inside of this html attribute's value is a bit of PHP code 1129 00:46:22,536 --> 00:46:26,106 which very quickly says to the web server, 'interpret this.' 1130 00:46:26,386 --> 00:46:27,796 Well what is being interpreted? 1131 00:46:27,946 --> 00:46:31,586 Well html special chars is a special escape function 1132 00:46:31,886 --> 00:46:35,226 so that whatever the user has typed, you're going to escape. 1133 00:46:35,226 --> 00:46:37,916 Just as in the way we've escaped certain characters in C, 1134 00:46:38,186 --> 00:46:41,036 html special chars is a function that says if the user typed 1135 00:46:41,036 --> 00:46:44,136 in something crazy, make sure it displays literally 1136 00:46:44,136 --> 00:46:46,576 as what they typed and doesn't mess with the webpage. 1137 00:46:46,576 --> 00:46:49,886 And we'll see what not doing that would create in a moment. 1138 00:46:50,186 --> 00:46:51,346 So what am I printing out? 1139 00:46:51,656 --> 00:46:53,396 Well go ahead and print out the result 1140 00:46:53,396 --> 00:46:55,926 of whatever the user typed into the name field. 1141 00:46:56,306 --> 00:46:57,126 Close quote. 1142 00:46:57,356 --> 00:47:00,026 So in other words, when the user types in their name, 1143 00:47:00,306 --> 00:47:03,076 but maybe skips the dorm or gender and clicks submit, 1144 00:47:03,376 --> 00:47:06,186 we can at least when the form is reloaded, 1145 00:47:06,346 --> 00:47:09,266 prepopulate this value this time as follows. 1146 00:47:09,266 --> 00:47:10,366 So let me go ahead and zoom out. 1147 00:47:10,796 --> 00:47:15,936 Let me go ahead and fill in for froshims5 dot php. 1148 00:47:15,936 --> 00:47:17,876 Let me go ahead and fill out name. 1149 00:47:18,136 --> 00:47:21,156 But I'm going to skip all the other fills and click register. 1150 00:47:21,156 --> 00:47:23,006 And notice I got yelled at, 1151 00:47:23,006 --> 00:47:26,446 but notice this time the form did get filled out for me. 1152 00:47:26,446 --> 00:47:28,936 Let's go ahead and right click or control click on the browser. 1153 00:47:28,936 --> 00:47:31,196 And if I scroll down, notice here, to be clear, 1154 00:47:31,196 --> 00:47:32,866 the browser never sees PHP. 1155 00:47:32,866 --> 00:47:36,676 PHP is executed server side, not client side. 1156 00:47:36,926 --> 00:47:39,436 So all of this is the output of PHP 1157 00:47:39,436 --> 00:47:41,206 or the raw html that I wrote. 1158 00:47:41,406 --> 00:47:42,166 Here's that div. 1159 00:47:42,166 --> 00:47:44,166 And notice it's kind of weirdly indented 1160 00:47:44,166 --> 00:47:46,776 because even though my PHP code was nice and pretty, 1161 00:47:47,136 --> 00:47:49,256 that white space is also sent to the browser. 1162 00:47:49,256 --> 00:47:50,476 So it's kind of throwing things off. 1163 00:47:50,476 --> 00:47:51,136 But that's fine. 1164 00:47:51,136 --> 00:47:53,026 We don't care about pretty printing or html, 1165 00:47:53,026 --> 00:47:54,936 just your actual PHP code. 1166 00:47:55,236 --> 00:47:57,366 Let's scroll down here and here's the difference. 1167 00:47:57,866 --> 00:48:02,416 Now this is time there's a value field that has spit out 'David' 1168 00:48:02,666 --> 00:48:05,406 because I had that additional line of PHP code. 1169 00:48:05,406 --> 00:48:10,196 And notice here if I scroll down these guys are not 1170 00:48:10,266 --> 00:48:12,656 yet prepopulated because I didn't fill them out. 1171 00:48:13,186 --> 00:48:15,276 So let's see what the opposite of this is. 1172 00:48:15,326 --> 00:48:18,556 So I actually did use best practice there whereby I did use 1173 00:48:18,556 --> 00:48:20,286 this function html special chars. 1174 00:48:20,556 --> 00:48:22,626 But let's see if I can do something a little hackish. 1175 00:48:22,626 --> 00:48:26,136 Let me get rid of this and let me just say, 1176 00:48:26,136 --> 00:48:29,096 'put inside of these quotes whatever the user typed 1177 00:48:29,096 --> 00:48:30,026 into the name field'. 1178 00:48:30,376 --> 00:48:32,216 And now notice one new piece of syntax. 1179 00:48:32,216 --> 00:48:33,406 Notice this trick here. 1180 00:48:33,696 --> 00:48:36,096 This means, because the equal sign is right next 1181 00:48:36,096 --> 00:48:38,236 to the dollar sign, put this value here. 1182 00:48:38,456 --> 00:48:40,876 This is equivalent to saying something like this 1183 00:48:41,386 --> 00:48:46,256 or even saying like this with parenthesis and so forth. 1184 00:48:46,316 --> 00:48:48,446 So this is just nice sort of shorthand notation. 1185 00:48:48,446 --> 00:48:49,626 So let me go back to the original. 1186 00:48:50,066 --> 00:48:52,276 And just this says, put my name here. 1187 00:48:52,276 --> 00:48:53,226 Let me zoom out. 1188 00:48:53,896 --> 00:48:56,826 And now let's see if a malicious user can maybe break my website. 1189 00:48:56,886 --> 00:49:00,306 So I am now the user who's just trying to be difficult. 1190 00:49:00,306 --> 00:49:02,636 I'm some bad guy trying to compromise this website. 1191 00:49:02,636 --> 00:49:04,536 And if I kind of suspect that the person 1192 00:49:04,536 --> 00:49:06,446 who implemented this site was not very good 1193 00:49:06,446 --> 00:49:09,476 and not security conscious, what if I can trick this page 1194 00:49:09,476 --> 00:49:12,116 into outputting html that wasn't intended. 1195 00:49:12,276 --> 00:49:14,426 Well typing in David still works. 1196 00:49:14,686 --> 00:49:16,286 It still populates that field. 1197 00:49:16,556 --> 00:49:18,356 But notice what we could do here. 1198 00:49:18,546 --> 00:49:21,426 If I view the page source again and I scroll to the David part, 1199 00:49:21,736 --> 00:49:24,056 notice that I've just been cooperative as the user. 1200 00:49:24,096 --> 00:49:25,806 I typed in D-A-V-I-D. 1201 00:49:26,116 --> 00:49:28,506 But I feel like I could type some crazy stuff here too. 1202 00:49:28,506 --> 00:49:31,626 What if I instead typed into this form, 1203 00:49:32,056 --> 00:49:36,856 quote close, V, ha ha ha. 1204 00:49:37,336 --> 00:49:40,076 Register. Interesting. 1205 00:49:40,826 --> 00:49:44,556 The only one I'm sort of damaging here is myself, right. 1206 00:49:44,556 --> 00:49:46,206 Because I'm not actually attacking the website. 1207 00:49:46,416 --> 00:49:47,576 But this was not intended. 1208 00:49:47,576 --> 00:49:50,146 And in fact, this is representative of a sort 1209 00:49:50,146 --> 00:49:51,336 of attack that's possible. 1210 00:49:51,336 --> 00:49:53,916 Long story short, there's this other language called JavaScript 1211 00:49:54,176 --> 00:49:57,306 which is executed client side. 1212 00:49:57,586 --> 00:49:59,726 And so what a lot of bad guys typically do, 1213 00:49:59,726 --> 00:50:01,086 especially in phishing emails, 1214 00:50:01,316 --> 00:50:03,866 is if they've realized some website, even something silly 1215 00:50:03,866 --> 00:50:08,896 like a froshim site has not escaped user's input properly, 1216 00:50:08,896 --> 00:50:11,206 what they'll do is try to trick you 1217 00:50:11,396 --> 00:50:14,086 into sending some JavaScript code to this form so as 1218 00:50:14,086 --> 00:50:16,626 to steal your cookie -- some cookie from the website. 1219 00:50:16,626 --> 00:50:18,926 And we'll see in awhile that stealing cookies means 1220 00:50:18,926 --> 00:50:19,886 that your shopping cart -- 1221 00:50:19,886 --> 00:50:21,766 your dollar sign underscore session variable -- 1222 00:50:22,006 --> 00:50:22,926 can be compromised. 1223 00:50:22,926 --> 00:50:25,056 And anything that you've put in there can be taken 1224 00:50:25,056 --> 00:50:27,236 over by someone else including, for instance, 1225 00:50:27,236 --> 00:50:28,146 your Facebook account. 1226 00:50:28,366 --> 00:50:30,876 Now if we go back here and I change this back 1227 00:50:30,916 --> 00:50:33,746 to the right way, where I'm actually escaping these inputs 1228 00:50:33,746 --> 00:50:36,246 with this annoying long function name, 1229 00:50:36,356 --> 00:50:39,086 but still nonetheless useful, html special chars, 1230 00:50:39,376 --> 00:50:41,906 and now I resubmit this form as I did before. 1231 00:50:41,906 --> 00:50:42,606 Let's start over. 1232 00:50:43,026 --> 00:50:44,996 So I'm going to go ahead and type close quotes, 1233 00:50:44,996 --> 00:50:47,656 close bracket, ha ha ha ha ha. 1234 00:50:48,276 --> 00:50:52,486 Register. Now I literally see that again in the form. 1235 00:50:52,666 --> 00:50:55,576 Because what the server has done for me -- 1236 00:50:55,576 --> 00:50:57,136 what PHP has done for me -- is this. 1237 00:50:57,706 --> 00:50:59,336 Notice that there are things 1238 00:50:59,406 --> 00:51:02,086 with ampersands and semicolons now. 1239 00:51:02,356 --> 00:51:06,556 So it turns out that html has these things called entities. 1240 00:51:06,836 --> 00:51:09,516 And these are entities in that they represent special 1241 00:51:09,516 --> 00:51:11,286 characters that normally would break html. 1242 00:51:11,286 --> 00:51:13,586 And it's a little cryptic, some of them, 1243 00:51:13,586 --> 00:51:18,836 but ampersand GT semicolon means the greater than sign. 1244 00:51:18,836 --> 00:51:21,736 Ampersand LT semicolon is the less than sign. 1245 00:51:21,966 --> 00:51:26,386 Ampersand QUOT semicolon is the quotation mark. 1246 00:51:26,386 --> 00:51:30,676 So there are a few of these well known entities that PHP can spit 1247 00:51:30,676 --> 00:51:33,186 out so that even if the user is being difficult, 1248 00:51:33,376 --> 00:51:36,676 you can at least protect the site against being tricked 1249 00:51:36,676 --> 00:51:38,536 into executing something that wasn't intended. 1250 00:51:38,536 --> 00:51:40,236 And even though the source code looks like this, 1251 00:51:40,606 --> 00:51:43,916 obviously as we just saw those entities are converted back 1252 00:51:43,956 --> 00:51:47,766 to their original characters before being shown to the user. 1253 00:51:48,076 --> 00:51:49,986 Now the one thing we haven't yet done here 1254 00:51:49,986 --> 00:51:51,766 and really has made this site useful -- 1255 00:51:51,766 --> 00:51:54,296 we have no capability thus far to actually remember 1256 00:51:54,296 --> 00:51:56,626 that users are stored or have registered. 1257 00:51:56,806 --> 00:51:58,226 For that we're going to need a database. 1258 00:51:58,516 --> 00:52:00,096 But before that, we're going to need a break. 1259 00:52:00,376 --> 00:52:01,976 So why don't we resume here in five. 1260 00:52:02,516 --> 00:52:04,756 [Pause] 1261 00:52:05,256 --> 00:52:06,376 >>All right. 1262 00:52:06,566 --> 00:52:07,246 So we are back. 1263 00:52:07,376 --> 00:52:09,456 And I thought it would be a disappointment 1264 00:52:09,456 --> 00:52:11,536 if we didn't actually demonstrate how you can send 1265 00:52:11,536 --> 00:52:13,996 programmatically emails with this third example 1266 00:52:13,996 --> 00:52:15,486 that we glanced at last Wednesday. 1267 00:52:15,486 --> 00:52:17,986 And today this recall is froshims3 dot php. 1268 00:52:17,986 --> 00:52:21,506 And recall that this was the implementation 1269 00:52:21,506 --> 00:52:24,246 that underneath the hood had these lines 1270 00:52:24,246 --> 00:52:28,616 of code using the mail function which has a bunch of parameters 1271 00:52:28,616 --> 00:52:30,186 to subject, body, and headers, 1272 00:52:30,186 --> 00:52:31,776 which ideally would send an email 1273 00:52:32,236 --> 00:52:34,806 to say the proctor who's running froshims 1274 00:52:34,806 --> 00:52:37,066 or in this jharvard at CS50 dot net. 1275 00:52:37,276 --> 00:52:39,426 So that when we check that guy's email account, 1276 00:52:39,426 --> 00:52:42,596 John Harvard should have some registration information waiting 1277 00:52:42,596 --> 00:52:43,096 for him. 1278 00:52:43,096 --> 00:52:46,946 So if I go over here to my browser again, I go ahead 1279 00:52:46,946 --> 00:52:50,186 and fill this out with complete fields so that it actually does 1280 00:52:50,186 --> 00:52:53,956 like my input, click register and then turn my attention 1281 00:52:54,006 --> 00:52:56,226 to my Gmail accounts here. 1282 00:52:57,146 --> 00:52:58,546 This is -- we're actually going to get a second one 1283 00:52:58,546 --> 00:52:59,466 because I was just testing. 1284 00:52:59,546 --> 00:53:03,136 In my Gmail inbox is a very simple email like this. 1285 00:53:03,366 --> 00:53:06,576 So it was sent from malan at cs50 dot net. 1286 00:53:06,776 --> 00:53:10,696 I logged into our email server as jharvard at cs50 dot net. 1287 00:53:10,986 --> 00:53:12,136 And this is of course not all 1288 00:53:12,136 --> 00:53:14,716 that interesting as it's written here. 1289 00:53:14,806 --> 00:53:17,836 But I do know that this person's name is David. 1290 00:53:18,556 --> 00:53:21,516 The checkbox was on, male, and Matthews. 1291 00:53:21,516 --> 00:53:24,266 And if we wanted, we could certainly format these emails a 1292 00:53:24,266 --> 00:53:25,216 little more cleanly. 1293 00:53:25,426 --> 00:53:27,216 Of course this doesn't scale very well. 1294 00:53:27,216 --> 00:53:29,976 And even if we implemented the froshims website for the proctor 1295 00:53:30,326 --> 00:53:33,166 by sending him or her emails, then this person has 1296 00:53:33,216 --> 00:53:35,706 to start organizing these emails into folders 1297 00:53:35,706 --> 00:53:36,846 and figuring out who's registered. 1298 00:53:36,846 --> 00:53:40,426 It would be much nicer if we could somehow create a database 1299 00:53:40,426 --> 00:53:43,616 for all of these registrants or create an Excel file even 1300 00:53:43,616 --> 00:53:45,766 so that the proctor could manage the volume 1301 00:53:45,766 --> 00:53:47,456 of registrants a little more cleanly. 1302 00:53:47,696 --> 00:53:49,106 So for this we actually need 1303 00:53:49,106 --> 00:53:52,026 to introduce a little something called MySQL. 1304 00:53:52,466 --> 00:53:55,326 So MySQL is a free database server. 1305 00:53:55,576 --> 00:53:57,896 A database server is something that allows you 1306 00:53:57,896 --> 00:54:00,016 to store your data in tables 1307 00:54:00,016 --> 00:54:03,066 or more specifically a relational database server is 1308 00:54:03,066 --> 00:54:05,076 something that allows you to store data in tables. 1309 00:54:05,076 --> 00:54:06,326 And what do we mean by tables? 1310 00:54:06,526 --> 00:54:08,306 Well think again to Excel spreadsheets. 1311 00:54:08,306 --> 00:54:09,856 These things have rows and columns. 1312 00:54:10,076 --> 00:54:12,826 That is a sort of a very simple database 1313 00:54:12,826 --> 00:54:15,286 where you can have columns that mean something like name 1314 00:54:15,286 --> 00:54:16,756 and email address and phone number 1315 00:54:16,906 --> 00:54:21,126 and every row represents an entry in that database or in 1316 00:54:21,126 --> 00:54:22,336 that Excel spreadsheet. 1317 00:54:22,576 --> 00:54:25,096 So this is a screenshot of a tool that we are about to see 1318 00:54:25,196 --> 00:54:27,046 and use called phpMyAdmin. 1319 00:54:27,336 --> 00:54:29,886 The fact that this tool is called PHP something is 1320 00:54:29,886 --> 00:54:30,516 a coincidence. 1321 00:54:30,546 --> 00:54:33,416 The tool happens to be written in PHP, but we're using it 1322 00:54:33,416 --> 00:54:37,486 because it's a useful with which to manage tables on a server. 1323 00:54:37,666 --> 00:54:39,476 MySQL is that server. 1324 00:54:39,476 --> 00:54:40,706 It's, again, free software. 1325 00:54:40,706 --> 00:54:41,866 It's very high performing. 1326 00:54:41,866 --> 00:54:44,776 And to this day, much of Facebook is implemented 1327 00:54:44,776 --> 00:54:47,056 with MySQL underneath the hood. 1328 00:54:47,516 --> 00:54:50,306 This is -- it can be scaled up to many, many, 1329 00:54:50,306 --> 00:54:51,326 many possible servers. 1330 00:54:51,326 --> 00:54:52,386 We, in the case of the appliance, 1331 00:54:52,386 --> 00:54:54,706 of course are just using one server -- our own. 1332 00:54:54,946 --> 00:54:57,426 So this is a screenshot specifically of a table 1333 00:54:57,666 --> 00:55:00,456 that you're getting or have gotten with Problem Set 7 1334 00:55:00,456 --> 00:55:02,006 that we precreated for you. 1335 00:55:02,006 --> 00:55:03,716 And we give you a little text file with which 1336 00:55:03,716 --> 00:55:05,846 to create this structure in your own appliance. 1337 00:55:06,086 --> 00:55:08,046 And even though there's a bunch of icons on the left, 1338 00:55:08,046 --> 00:55:09,636 this table is actually even simpler. 1339 00:55:09,636 --> 00:55:11,736 There's only three columns, an ID column, 1340 00:55:12,016 --> 00:55:14,306 a username column, and a hash column. 1341 00:55:14,526 --> 00:55:17,786 And this table collectively will be called the user's table. 1342 00:55:17,786 --> 00:55:20,856 And the idea here is that when you download PSet7 1343 00:55:20,856 --> 00:55:23,996 for the first time, what you have is a slightly 1344 00:55:23,996 --> 00:55:25,456 functional product. 1345 00:55:25,456 --> 00:55:28,796 You have a product that looks a little something like this. 1346 00:55:28,796 --> 00:55:30,746 If I go to the staff's own implementation 1347 00:55:30,746 --> 00:55:32,576 as CS50 dot net slash finance, 1348 00:55:32,856 --> 00:55:34,606 you'll see a user interface a little like this, 1349 00:55:34,606 --> 00:55:36,536 but you won't have the big yellow banner there saying 1350 00:55:36,536 --> 00:55:37,876 that this is the staff solution. 1351 00:55:38,136 --> 00:55:41,676 But what you do have by default is a bunch of temporary users -- 1352 00:55:41,676 --> 00:55:44,886 a jharvard user, a [inaudible] user, a Malan or a boden, 1353 00:55:44,946 --> 00:55:47,626 a max account and others -- 1354 00:55:47,856 --> 00:55:50,526 so that you at least have some sample data with which to work. 1355 00:55:50,526 --> 00:55:53,016 And so the format of that table is as follows. 1356 00:55:53,336 --> 00:55:55,916 We apparently have an integer representing their ID. 1357 00:55:56,146 --> 00:55:59,116 Their username is whatever they chose upon registering. 1358 00:55:59,316 --> 00:56:02,056 And the hash over there is supposed 1359 00:56:02,056 --> 00:56:04,146 to be their password, but it's not really. 1360 00:56:04,216 --> 00:56:07,116 So if you think way back to Problem Set 2 when we talked 1361 00:56:07,116 --> 00:56:08,186 about photography, some 1362 00:56:08,186 --> 00:56:09,916 of you might have bit off the hacker edition 1363 00:56:10,186 --> 00:56:13,346 of the crypto PSet, which actually had you crack passwords 1364 00:56:13,346 --> 00:56:14,836 that weren't quite encrypted like this, 1365 00:56:15,176 --> 00:56:17,416 but were in some similar fashion. 1366 00:56:17,716 --> 00:56:20,676 Why, apparently, are we proposing in our database 1367 00:56:20,756 --> 00:56:22,546 to not remember users' passwords, 1368 00:56:22,786 --> 00:56:25,236 but instead remember their hashes thereof, 1369 00:56:25,266 --> 00:56:26,016 whatever that is? 1370 00:56:26,846 --> 00:56:30,116 What was a hash of a password or a hash in general? 1371 00:56:31,566 --> 00:56:33,796 This also relates actually to PSet6. 1372 00:56:34,576 --> 00:56:34,666 Yeah. 1373 00:56:35,236 --> 00:56:41,036 >>To make it more [inaudible]. 1374 00:56:41,246 --> 00:56:41,816 >>Okay, perfect. 1375 00:56:41,816 --> 00:56:43,456 So the point of hash is generally -- 1376 00:56:43,456 --> 00:56:46,646 is to make it harder for a bad guy who steals, for instance, 1377 00:56:46,646 --> 00:56:48,926 this database or breaks into my web server 1378 00:56:49,126 --> 00:56:51,696 and somehow gains access to all of my user data. 1379 00:56:51,926 --> 00:56:55,606 It's a really bad situation if they not only get my user data 1380 00:56:55,826 --> 00:56:58,026 but also get my users' passwords. 1381 00:56:58,026 --> 00:57:00,256 Right? Because there is probably a nontrivial number of you 1382 00:57:00,256 --> 00:57:03,866 in this room who are using the same password for your email, 1383 00:57:04,126 --> 00:57:06,756 for your pin account, frankly 1384 00:57:06,756 --> 00:57:09,606 for your fake CS50 Finance account most likely. 1385 00:57:09,826 --> 00:57:12,346 And if that data is not encrypted or not hashed, 1386 00:57:12,556 --> 00:57:14,636 what that means is that all these websites you've been 1387 00:57:14,636 --> 00:57:16,516 logging into for the past couple of years, 1388 00:57:16,516 --> 00:57:18,856 if you're using the same password and the people 1389 00:57:18,856 --> 00:57:21,176 who implemented those sites are not particularly security 1390 00:57:21,176 --> 00:57:24,416 conscious or savvy, you might be telling half the world 1391 00:57:24,416 --> 00:57:26,876 who runs these servers what your favorite password is. 1392 00:57:27,216 --> 00:57:30,706 Because if you don't actually encrypt it or again hash it, 1393 00:57:30,706 --> 00:57:32,966 much like we created a hash function in PSet6 -- 1394 00:57:33,196 --> 00:57:35,596 if you don't somehow scramble the input and then save 1395 00:57:35,596 --> 00:57:37,666 that input, the alternative is the worse, 1396 00:57:37,736 --> 00:57:39,866 which is just storing the actual password. 1397 00:57:40,076 --> 00:57:41,766 So long story short, you will see 1398 00:57:41,766 --> 00:57:43,436 in PSet7's distribution code, 1399 00:57:43,646 --> 00:57:45,576 the use of a special function called crypt 1400 00:57:45,836 --> 00:57:48,926 which is essentially a hash function that given a password 1401 00:57:48,926 --> 00:57:53,026 like 12345 will create nonsense that looks like this. 1402 00:57:53,526 --> 00:57:56,586 But the key feature of this crypt function is 1403 00:57:56,586 --> 00:58:00,206 that if you call it again in the future and give it again 12345, 1404 00:58:00,206 --> 00:58:03,396 it will return exactly the same cryptic value. 1405 00:58:03,636 --> 00:58:05,436 So the idea is when you check passwords, 1406 00:58:05,616 --> 00:58:07,066 you don't check what the user typed 1407 00:58:07,066 --> 00:58:08,616 in against what's in the database. 1408 00:58:08,916 --> 00:58:11,706 You check what the user typed in after it's been passed 1409 00:58:12,146 --> 00:58:15,126 to the crypt function again, against what's in your database. 1410 00:58:15,126 --> 00:58:16,906 And statistically it should be very, 1411 00:58:16,906 --> 00:58:20,266 very hard to convert these cryptic hashes back 1412 00:58:20,476 --> 00:58:21,776 to the original inputs. 1413 00:58:22,016 --> 00:58:24,116 And for the curious and for those struggling to actually log 1414 00:58:24,116 --> 00:58:26,626 into CS50 Finance, these were the answers 1415 00:58:26,626 --> 00:58:28,476 to the hacker edition of Problem Set 2. 1416 00:58:28,476 --> 00:58:30,686 And all of the passwords that we gave to the hackers 1417 00:58:30,686 --> 00:58:35,456 in the class ranged from the simplest for [inaudible]. 1418 00:58:35,456 --> 00:58:36,386 Rob's was noob. 1419 00:58:36,386 --> 00:58:37,036 Matt's was [inaudible]. 1420 00:58:37,276 --> 00:58:39,516 And mine I daresay was the hardest, 1421 00:58:39,516 --> 00:58:41,946 which I think this year no one got, 1422 00:58:41,946 --> 00:58:44,596 but these are the same passwords that we've given you just 1423 00:58:44,596 --> 00:58:47,346 as sample users for Problem Set 7. 1424 00:58:47,516 --> 00:58:50,856 So how do we actually use MySQL and use these tables? 1425 00:58:51,056 --> 00:58:54,256 Well know first that SQL is the language we're now 1426 00:58:54,256 --> 00:58:55,086 about to start using. 1427 00:58:55,246 --> 00:58:57,806 So SQL -- structured query language -- 1428 00:58:57,806 --> 00:58:59,776 is not so much a programming language 1429 00:58:59,776 --> 00:59:03,046 as it is a database language -- a query language, per its name, 1430 00:59:03,306 --> 00:59:06,026 that allows you to select data from a database, 1431 00:59:06,026 --> 00:59:09,336 insert data into a database, delete from it, update it. 1432 00:59:09,566 --> 00:59:11,886 So in short, all these things we take for granted 1433 00:59:11,886 --> 00:59:15,566 when using Excel like double clicking on a row and typing 1434 00:59:15,566 --> 00:59:18,606 and deleting a column and so forth, those can be summed 1435 00:59:18,606 --> 00:59:21,116 up as deletions and inserts and updates and select. 1436 00:59:21,416 --> 00:59:24,386 Where select is one of the most useful, that's the search, 1437 00:59:24,386 --> 00:59:26,176 like give me something from this spreadsheet; 1438 00:59:26,176 --> 00:59:27,606 give me something from this table. 1439 00:59:27,846 --> 00:59:29,746 So we're about to start constructing queries 1440 00:59:29,746 --> 00:59:31,906 that allow us to grab data in this fashion. 1441 00:59:32,196 --> 00:59:36,326 And we'll use phpMyAdmin as a specific tool with which 1442 00:59:36,326 --> 00:59:38,526 to actually configure those things 1443 00:59:38,526 --> 00:59:40,746 so that we can implement a little something like this. 1444 00:59:41,046 --> 00:59:42,406 So let me go back to the appliance. 1445 00:59:42,406 --> 00:59:44,516 And I'm going to go ahead and open up Firefox. 1446 00:59:44,606 --> 00:59:47,436 And I'm going to go not just to local host this time, 1447 00:59:47,436 --> 00:59:49,226 which recall is my actual web server. 1448 00:59:49,446 --> 00:59:53,276 I'm actually going to go to slash phpMyAdmin. 1449 00:59:53,826 --> 00:59:56,136 And when you go here, you'll be prompted to login 1450 00:59:56,256 --> 00:59:58,546 with jharvard and crimson. 1451 00:59:58,886 --> 01:00:02,656 So to be clear, phpMyAdmin is an administrative tool 1452 01:00:02,656 --> 01:00:04,546 on the web server, aka the appliance. 1453 01:00:04,856 --> 01:00:06,906 You should not be trying to login to phpMyAdmin 1454 01:00:06,906 --> 01:00:09,276 as [inaudible] or as Matt or as Rob, 1455 01:00:09,276 --> 01:00:11,296 but rather as you, John Harvard. 1456 01:00:11,476 --> 01:00:14,856 Because John Harvard in this case, aka you, is the webmaster. 1457 01:00:15,086 --> 01:00:16,746 So when you login to phpMyAdmin, 1458 01:00:16,746 --> 01:00:18,486 frankly its UI is kind of a train wreck. 1459 01:00:18,486 --> 01:00:21,076 There's way too much going onto be compelling. 1460 01:00:21,376 --> 01:00:23,466 But there are some very handy features 1461 01:00:23,466 --> 01:00:26,256 that are much more user friendly than the alternative 1462 01:00:26,516 --> 01:00:27,576 which would be a command line. 1463 01:00:27,806 --> 01:00:30,686 So notice the top left tier that I've followed some instruction 1464 01:00:30,686 --> 01:00:33,616 in Problem Set 7 that said, 'Import this database'. 1465 01:00:33,666 --> 01:00:34,266 How do you do that? 1466 01:00:34,606 --> 01:00:36,266 We literally give you a big text file. 1467 01:00:36,266 --> 01:00:38,146 It's called PSet7 dot sql. 1468 01:00:38,406 --> 01:00:41,306 You essentially highlight it and copy its contents 1469 01:00:41,396 --> 01:00:44,246 into this big SQL window here. 1470 01:00:44,476 --> 01:00:46,876 Click run and voila, you know have a database. 1471 01:00:46,876 --> 01:00:49,386 So for now you're seeing the end result of that process 1472 01:00:49,386 --> 01:00:50,786 that the spec will walk you through. 1473 01:00:51,056 --> 01:00:53,186 When I click users, now we see the webpage 1474 01:00:53,186 --> 01:00:54,986 that I took a screenshot of a moment ago. 1475 01:00:55,276 --> 01:00:57,646 And again, I have an ID field, a username field 1476 01:00:57,646 --> 01:00:59,456 and a hash field for their password. 1477 01:00:59,606 --> 01:01:02,326 But let's start this from scratch with regard to froshims. 1478 01:01:02,326 --> 01:01:03,966 Let me go ahead and do the following. 1479 01:01:03,966 --> 01:01:06,816 I'm going to go over to the homepage again. 1480 01:01:07,186 --> 01:01:08,416 I'm going to click databases. 1481 01:01:08,416 --> 01:01:10,096 And I'm going to create a new database. 1482 01:01:10,126 --> 01:01:12,366 Let's call it jharvard Week 9. 1483 01:01:12,636 --> 01:01:15,316 As an aside, John Harvard has the privileges 1484 01:01:15,316 --> 01:01:17,816 to create any database so long as its name starts 1485 01:01:17,816 --> 01:01:19,566 with jharvard underscore. 1486 01:01:19,566 --> 01:01:21,196 This is a typical MySQL convention. 1487 01:01:21,196 --> 01:01:22,396 I'm going to click create. 1488 01:01:22,646 --> 01:01:25,406 And now notice it executed this. 1489 01:01:25,636 --> 01:01:27,326 So this is what phpMyAdmin does. 1490 01:01:27,416 --> 01:01:30,126 It simply simplifies the execution 1491 01:01:30,466 --> 01:01:32,776 of slightly more arcane commands. 1492 01:01:32,776 --> 01:01:34,346 Again, I could type in a blinking prompt. 1493 01:01:34,396 --> 01:01:35,736 For instance, to create a database, 1494 01:01:35,946 --> 01:01:38,156 you could literally type at the right command prompt, 1495 01:01:38,156 --> 01:01:40,486 'Create database jharvard underscore Week9'. 1496 01:01:40,806 --> 01:01:44,096 This gooey based tool just makes it a little easier to do so. 1497 01:01:44,426 --> 01:01:46,426 Now if I scroll down here, it's telling me, 1498 01:01:46,426 --> 01:01:47,896 'No tables found in database.' 1499 01:01:48,326 --> 01:01:51,976 So you can think of a table like and Excel worksheet specifically 1500 01:01:52,206 --> 01:01:54,146 and an Excel file as a database 1501 01:01:54,216 --> 01:01:56,986 that can have multiple worksheets or multiple tables. 1502 01:01:57,256 --> 01:01:59,956 In this case, I want to go ahead, for froshims, 1503 01:02:00,046 --> 01:02:02,556 and create like a registrant's table -- 1504 01:02:02,556 --> 01:02:05,076 the kids who have registered for some froshims4. 1505 01:02:05,386 --> 01:02:06,476 And how many columns? 1506 01:02:06,476 --> 01:02:08,036 Well I've got four, right? 1507 01:02:08,036 --> 01:02:11,756 Name, gender, captain, or dorm -- so four fields in that case. 1508 01:02:12,216 --> 01:02:13,356 So let me go ahead and hit enter. 1509 01:02:13,356 --> 01:02:15,436 And now I'm going to get this form here. 1510 01:02:15,716 --> 01:02:17,896 Again, this is not the most user friendly design in that you have 1511 01:02:17,896 --> 01:02:19,176 to scroll all the way to the right, 1512 01:02:19,426 --> 01:02:21,676 but let's at least tease apart what these fields are. 1513 01:02:21,746 --> 01:02:24,586 So first in column, I'm going to name these fields. 1514 01:02:24,586 --> 01:02:28,886 Name, captain, this is going to be gender, 1515 01:02:28,886 --> 01:02:30,386 this is going to be dorm. 1516 01:02:30,716 --> 01:02:33,226 And now what types do I want to give these? 1517 01:02:33,226 --> 01:02:35,736 Well notice that MySQL is different 1518 01:02:35,736 --> 01:02:37,106 from C. It's different from PHP. 1519 01:02:37,106 --> 01:02:40,556 It comes with a whole bunch of data types, frankly almost all 1520 01:02:40,556 --> 01:02:43,796 of which are self explanatory, especially like float and double 1521 01:02:43,796 --> 01:02:45,366 and int because we've seen those before. 1522 01:02:45,916 --> 01:02:49,026 Int we used for an ID, but for name I need something 1523 01:02:49,026 --> 01:02:49,826 like a string. 1524 01:02:49,826 --> 01:02:51,316 And here's the string related ones. 1525 01:02:51,596 --> 01:02:54,146 And the two that are more interesting now are char 1526 01:02:54,146 --> 01:02:54,796 and varchar. 1527 01:02:55,046 --> 01:02:58,006 Long story short, if I choose char, that's actually more 1528 01:02:58,006 --> 01:03:00,556 than a single char because I can say everyone's name 1529 01:03:00,556 --> 01:03:03,886 in this database is going to be no more than say 64 characters. 1530 01:03:04,236 --> 01:03:07,616 And by typing 64 in that box means MySQL's going 1531 01:03:07,696 --> 01:03:10,256 to create a column that's just wide enough 1532 01:03:10,406 --> 01:03:12,156 for 64 character strings. 1533 01:03:12,456 --> 01:03:14,446 Now the downside of this is that like in C 1534 01:03:14,446 --> 01:03:17,766 if I allocate 64 characters, every name is going to take 1535 01:03:17,766 --> 01:03:20,516 up 64 bytes, which is probably excessive 1536 01:03:20,516 --> 01:03:21,536 for a lot of our names. 1537 01:03:21,876 --> 01:03:24,616 So there's instead a data type called varchar -- 1538 01:03:24,616 --> 01:03:28,226 variable char -- where you can say 64 is the maximum length, 1539 01:03:28,226 --> 01:03:29,796 but be smart about this. 1540 01:03:29,796 --> 01:03:33,186 Only use as many bytes as are necessary 1541 01:03:33,186 --> 01:03:36,576 to store the D-A-V-I-D space M-A-L-A-N. 1542 01:03:36,576 --> 01:03:39,926 Right. That's only 11 -- maybe a [inaudible] character -- 1543 01:03:39,926 --> 01:03:41,256 so 11 or 12. 1544 01:03:41,256 --> 01:03:44,656 That's much more efficient than using a char itself. 1545 01:03:44,936 --> 01:03:47,426 So quick sort of thought question. 1546 01:03:47,426 --> 01:03:49,656 Even though we know nothing really about MySQL 1547 01:03:49,656 --> 01:03:51,356 or how databases are implemented, 1548 01:03:52,716 --> 01:03:56,976 what price are we probably paying if I'm not using a char 1549 01:03:56,976 --> 01:03:59,836 but instead using a varchar which seems like a win? 1550 01:04:00,246 --> 01:04:04,026 I'm using less space because I'm only using as much as I need. 1551 01:04:04,356 --> 01:04:06,066 But what's the hidden cost probably 1552 01:04:06,066 --> 01:04:08,086 as has been a theme in the class? 1553 01:04:08,956 --> 01:04:09,276 >>Performance. 1554 01:04:09,276 --> 01:04:10,616 >>Yeah, the performance, right. 1555 01:04:10,616 --> 01:04:13,506 So it turns out -- so speed, performance. 1556 01:04:13,506 --> 01:04:16,236 Whenever we talk about these tradeoffs it's almost always 1557 01:04:16,366 --> 01:04:17,186 time or space. 1558 01:04:17,286 --> 01:04:18,676 In this case we win on space. 1559 01:04:18,956 --> 01:04:19,906 We lose on time. 1560 01:04:20,106 --> 01:04:22,586 Now this is not worrisome for small databases. 1561 01:04:22,586 --> 01:04:25,266 But again, for large websites with hundreds or thousands 1562 01:04:25,266 --> 01:04:27,816 or tens of thousands of users, there's an advantage 1563 01:04:27,816 --> 01:04:30,906 to having every username 64 characters even if most 1564 01:04:30,906 --> 01:04:32,436 of those are just blank characters. 1565 01:04:32,436 --> 01:04:35,376 Why? Because just like an array, you can go from here to here 1566 01:04:35,376 --> 01:04:38,346 to here by just doing plus 64, plus 64, plus 64. 1567 01:04:38,616 --> 01:04:42,076 If you instead use variable length strings how do you find 1568 01:04:42,076 --> 01:04:42,816 someone's name? 1569 01:04:43,126 --> 01:04:45,526 Well you kind of have to scan the whole list in the worst case 1570 01:04:45,526 --> 01:04:47,416 because you can't jump from name to name 1571 01:04:47,616 --> 01:04:49,246 because they're not all in the same boundary. 1572 01:04:49,246 --> 01:04:51,646 In other words, you have ragged edges in your column. 1573 01:04:51,646 --> 01:04:53,216 They're not straight like this in Excel. 1574 01:04:53,466 --> 01:04:55,286 They're kind of different lengths all around. 1575 01:04:55,356 --> 01:04:56,986 So that does not lend itself to performance. 1576 01:04:56,986 --> 01:04:58,246 So that's something to keep in mind. 1577 01:04:58,506 --> 01:05:01,136 So for now, varchar is almost always fine unless you're 1578 01:05:01,136 --> 01:05:02,926 really, really worried about performance. 1579 01:05:03,186 --> 01:05:05,756 64 might even be -- 64 is pretty generous, 1580 01:05:05,756 --> 01:05:07,226 but we can even make this 128 1581 01:05:07,226 --> 01:05:08,536 since we're using variable chars. 1582 01:05:08,536 --> 01:05:09,566 But you do have to decide. 1583 01:05:09,566 --> 01:05:12,646 Captain is going to be something like a yes or a no. 1584 01:05:12,646 --> 01:05:14,916 So I'm actually going to use the Boolean field. 1585 01:05:15,036 --> 01:05:16,846 So that can just be a zero or a one. 1586 01:05:17,276 --> 01:05:18,976 Gender I actually have a few options. 1587 01:05:18,976 --> 01:05:21,046 I could do something binary with Boolean. 1588 01:05:21,046 --> 01:05:22,276 I could use a string. 1589 01:05:22,276 --> 01:05:23,366 I could use a number. 1590 01:05:23,646 --> 01:05:24,986 So we could actually go a few ways here. 1591 01:05:24,986 --> 01:05:26,326 For simplicity, I'm going to go ahead 1592 01:05:26,326 --> 01:05:29,916 and choose let's say a char. 1593 01:05:30,116 --> 01:05:31,346 Let's say -- where'd it go? 1594 01:05:31,346 --> 01:05:36,746 Let's do char because my form is hardcoded right now as M or F. 1595 01:05:36,856 --> 01:05:38,976 So if I'm only going to restrict to those two choices, 1596 01:05:38,976 --> 01:05:40,976 let's just use one single char and not worry 1597 01:05:40,976 --> 01:05:42,026 about Booleans and such. 1598 01:05:42,236 --> 01:05:46,426 And then lastly, dorm, this could be a char or a varchar. 1599 01:05:46,516 --> 01:05:52,196 No dorm name is greater than like -- 128 is -- whoops. 1600 01:05:52,356 --> 01:05:54,536 Sorry. This we made char. 1601 01:05:54,696 --> 01:05:56,676 I'm not even sure what that would mean. 1602 01:05:57,526 --> 01:06:01,936 Okay, varchar, all right 1, gender 1. 1603 01:06:02,026 --> 01:06:02,846 Okay, there we go. 1604 01:06:02,846 --> 01:06:05,346 Captain, oh I'm all over the place. 1605 01:06:05,416 --> 01:06:06,246 All right. 1606 01:06:06,866 --> 01:06:08,636 Varchar, let's say 128. 1607 01:06:08,636 --> 01:06:09,676 Why? Just because. 1608 01:06:09,676 --> 01:06:10,226 It's the same. 1609 01:06:10,226 --> 01:06:11,446 You have to make a decision. 1610 01:06:11,446 --> 01:06:13,746 So you might as well pick something consistent 1611 01:06:13,746 --> 01:06:14,246 in this case. 1612 01:06:14,516 --> 01:06:16,926 So there's a bunch of other fields we can choose here. 1613 01:06:16,926 --> 01:06:18,116 And let me just point them out, 1614 01:06:18,116 --> 01:06:20,026 but they'll be more germane to Problem Set 7. 1615 01:06:20,276 --> 01:06:22,246 So notice we could specify default value. 1616 01:06:22,246 --> 01:06:24,716 So this is handy because if you don't want to deal 1617 01:06:24,716 --> 01:06:27,476 with inserting default values you can actually have your 1618 01:06:27,476 --> 01:06:28,946 database do that for you. 1619 01:06:29,236 --> 01:06:31,836 We can also scroll down over here to attributes. 1620 01:06:31,836 --> 01:06:34,316 And none of these are actually valid just yet. 1621 01:06:34,376 --> 01:06:36,936 But notice in PSet7 we actually will take advantage 1622 01:06:36,936 --> 01:06:40,466 of unsigned integers so that we don't waste bits using negative 1623 01:06:40,466 --> 01:06:41,146 numbers for ID's. 1624 01:06:41,146 --> 01:06:44,966 We can also scroll over here and specify indices. 1625 01:06:44,966 --> 01:06:46,996 And this is a fundamental database concept. 1626 01:06:47,226 --> 01:06:51,476 When you have users in a database or data in a database, 1627 01:06:51,506 --> 01:06:53,436 you very often want to search that date. 1628 01:06:53,526 --> 01:06:56,346 For instance, you might want to search by username or search 1629 01:06:56,346 --> 01:06:59,376 by ID, search by stock ticker symbol, 1630 01:06:59,376 --> 01:07:01,796 search by friend ID or the like. 1631 01:07:02,156 --> 01:07:06,486 So to do that by default just as in Excel if you want 1632 01:07:06,486 --> 01:07:09,326 to search something, well you can use linear search, right? 1633 01:07:09,326 --> 01:07:11,576 Because your database isn't necessarily going to be sorted 1634 01:07:11,576 --> 01:07:14,256 if you have people registering or signing up for your website 1635 01:07:14,256 --> 01:07:16,436 in some random order because they're on the internet. 1636 01:07:16,806 --> 01:07:18,626 But you can tell your database, 'You know what? 1637 01:07:18,936 --> 01:07:20,756 I know that I'm going to be doing a lot 1638 01:07:20,756 --> 01:07:23,806 of searches called selects on this particular field, 1639 01:07:23,806 --> 01:07:25,996 like name or ID or username.' 1640 01:07:26,326 --> 01:07:28,586 So you know what, you can tell the database, 1641 01:07:28,586 --> 01:07:31,816 assume that you should index this field. 1642 01:07:31,816 --> 01:07:36,476 To index a database fields means to use data structures 1643 01:07:36,476 --> 01:07:38,516 from last week and two weeks ago in CS50 -- 1644 01:07:38,586 --> 01:07:41,806 use some treelike structure underneath the hood so that 1645 01:07:41,806 --> 01:07:44,776 in the future when I ask you a question, 'Has David registered, 1646 01:07:44,906 --> 01:07:48,456 you can answer like this instead of much more slowly 1647 01:07:48,456 --> 01:07:51,636 in linear time by searching the whole database table. 1648 01:07:51,746 --> 01:07:54,866 So we'll see more of those on Problem Set 7. 1649 01:07:55,056 --> 01:07:56,666 And null just allows me to specify, 1650 01:07:56,666 --> 01:07:58,886 you know what this field can be null. 1651 01:07:58,886 --> 01:08:00,086 Captain could be null 1652 01:08:00,086 --> 01:08:01,866 for instance is it weren't a Boolean. 1653 01:08:01,866 --> 01:08:03,916 But for now we'll just leave that thing unchecked. 1654 01:08:04,296 --> 01:08:08,336 And if I now go over here all the way to the bottom and left 1655 01:08:08,336 --> 01:08:11,786 or right and click save, what I will see is this. 1656 01:08:12,266 --> 01:08:14,256 And this again is what this tool simplifies. 1657 01:08:14,526 --> 01:08:17,606 So what I've highlighted there just a moment ago is a whole 1658 01:08:17,606 --> 01:08:18,576 bunch of SQL code -- 1659 01:08:18,576 --> 01:08:21,736 create table and name and captain and gender and dorm. 1660 01:08:22,006 --> 01:08:24,106 And all of that I could have typed manually 1661 01:08:24,106 --> 01:08:27,126 at a blinking prompt but instead this tool has created this table 1662 01:08:27,126 --> 01:08:27,606 for me. 1663 01:08:27,896 --> 01:08:29,516 So that now if I go back to the left, 1664 01:08:29,836 --> 01:08:32,816 notice that under my jharvard Week9 database, 1665 01:08:33,216 --> 01:08:34,266 I have this table. 1666 01:08:34,576 --> 01:08:37,256 Notice that under this table I have a little reminder 1667 01:08:37,476 --> 01:08:38,876 of what I actually did. 1668 01:08:39,116 --> 01:08:42,386 Not to fear, the collation here is all somehow related 1669 01:08:42,386 --> 01:08:42,856 to Swedish. 1670 01:08:42,886 --> 01:08:44,246 That's just because the people 1671 01:08:44,246 --> 01:08:47,226 who implemented MySQL originally were Swedish. 1672 01:08:47,456 --> 01:08:50,636 But thankfully Swedish characters overlap 1673 01:08:50,636 --> 01:08:51,686 with English characters. 1674 01:08:51,686 --> 01:08:52,866 So that simply is the default. 1675 01:08:53,236 --> 01:08:57,226 And what we have here now is a four field database. 1676 01:08:57,576 --> 01:08:58,876 Let me see who's in this database. 1677 01:08:59,346 --> 01:09:02,956 Browse. Okay, no one's in this database at this point in time 1678 01:09:02,956 --> 01:09:04,446 because I haven't inserted anyone. 1679 01:09:04,676 --> 01:09:05,846 So let's do just that. 1680 01:09:05,846 --> 01:09:08,806 Let me go back to my code here and let me open 1681 01:09:08,806 --> 01:09:13,026 up say register8 dot php. 1682 01:09:13,546 --> 01:09:15,086 So assume that this is the file 1683 01:09:15,086 --> 01:09:18,106 of that same form we've been playing with today submits to. 1684 01:09:18,356 --> 01:09:20,186 Notice I have a few sanity checks at the top. 1685 01:09:20,186 --> 01:09:22,076 If you didn't give me a name, if you didn't me a gender, 1686 01:09:22,076 --> 01:09:23,526 if you didn't give me a dorm, go away. 1687 01:09:23,606 --> 01:09:24,706 Go back to this other URL. 1688 01:09:25,346 --> 01:09:27,316 Other wise, connect to the database. 1689 01:09:27,646 --> 01:09:29,516 So this is a new PHP function. 1690 01:09:29,516 --> 01:09:31,956 PHP plays very nicely with MySQL. 1691 01:09:31,956 --> 01:09:33,656 It has a lot of built-in support for it. 1692 01:09:33,936 --> 01:09:37,556 This line of code here says connect to the local host -- 1693 01:09:37,556 --> 01:09:39,406 that is my server, my appliance -- 1694 01:09:39,686 --> 01:09:42,056 using this username and this password. 1695 01:09:42,056 --> 01:09:44,856 We have precreated a jharvard and crimson account 1696 01:09:45,106 --> 01:09:47,216 for your database in the appliance by default. 1697 01:09:47,546 --> 01:09:48,946 What database do I want to use? 1698 01:09:48,946 --> 01:09:52,246 Well I want to select the database called jharvard Week9. 1699 01:09:52,496 --> 01:09:54,086 That's the one I just created. 1700 01:09:54,296 --> 01:09:57,226 And now I have to do a couple things for security's sake. 1701 01:09:57,466 --> 01:09:59,196 We'll talk more about this before long. 1702 01:09:59,196 --> 01:10:01,736 But for now know that there's this idiotically named 1703 01:10:02,016 --> 01:10:04,376 MySQL-Real-Escape-String function -- 1704 01:10:04,606 --> 01:10:06,976 so do as we say not as other people do -- 1705 01:10:07,206 --> 01:10:11,136 whose purpose in life similar to html special chars is 1706 01:10:11,136 --> 01:10:14,116 to somehow scrub the user's input. 1707 01:10:14,116 --> 01:10:15,216 What do we mean by that? 1708 01:10:15,396 --> 01:10:19,386 If they typed in anything crazy like apostrophes or backslashes 1709 01:10:19,386 --> 01:10:23,526 or worse -- keywords like delete or update or insert 1710 01:10:23,596 --> 01:10:27,146 that we might otherwise risk accidentally passing 1711 01:10:27,146 --> 01:10:28,396 to our database directly -- 1712 01:10:28,696 --> 01:10:30,446 calling this crazy long function, 1713 01:10:30,446 --> 01:10:33,686 MySQL-Real-Escape-String, ensures that even 1714 01:10:33,686 --> 01:10:36,336 if they type something crazy dangerous like delete, 1715 01:10:36,746 --> 01:10:38,736 I am not going to treat that as a command. 1716 01:10:38,736 --> 01:10:40,856 I'm going to treat that as a string from the user. 1717 01:10:41,126 --> 01:10:43,116 So notice I'm declaring a variable called dollar 1718 01:10:43,116 --> 01:10:43,706 sign name. 1719 01:10:43,936 --> 01:10:45,546 I'm storing it at the return value 1720 01:10:45,546 --> 01:10:47,086 of this function that's taking 1721 01:10:47,086 --> 01:10:49,306 as input literally what the user typed. 1722 01:10:49,606 --> 01:10:52,926 And now notice -- recall that captain is either the word on 1723 01:10:52,926 --> 01:10:54,826 or it's just not even present at all. 1724 01:10:54,826 --> 01:10:58,106 So in this case I have to create a variable called captain that's 1725 01:10:58,106 --> 01:11:01,376 either the number one for true or zero for false. 1726 01:11:01,746 --> 01:11:05,406 Then I'm going to similarly scrub gender and dorm 1727 01:11:05,406 --> 01:11:07,526 with that same MySQL Real Escape function. 1728 01:11:07,796 --> 01:11:10,656 And now notice how you actually insert into a database. 1729 01:11:11,216 --> 01:11:13,436 MySQL is running on the same server -- 1730 01:11:13,436 --> 01:11:14,606 on the same local host. 1731 01:11:14,886 --> 01:11:17,486 So if I want to insert data into it, I essentially need 1732 01:11:17,486 --> 01:11:18,536 to speak its language. 1733 01:11:18,536 --> 01:11:19,726 PHP is not its language. 1734 01:11:19,726 --> 01:11:20,856 HTML is not its language. 1735 01:11:20,856 --> 01:11:22,136 SQL is its language. 1736 01:11:22,456 --> 01:11:26,336 So all I have to do in PHP is create a string using double 1737 01:11:26,336 --> 01:11:30,206 quotes that matches the server's expectations 1738 01:11:30,206 --> 01:11:31,786 for how to insert data. 1739 01:11:31,786 --> 01:11:35,736 And it turns out to insert data into a database, you can say, 1740 01:11:35,996 --> 01:11:38,436 insert into the name of the table. 1741 01:11:38,846 --> 01:11:41,746 Then in parentheses you specify a comma separated list 1742 01:11:41,746 --> 01:11:43,926 of the fields that you want to insert values into. 1743 01:11:44,306 --> 01:11:46,676 Then, it's on the new line but this could all be one line, 1744 01:11:46,866 --> 01:11:48,046 you literally say values. 1745 01:11:48,046 --> 01:11:50,066 And then another set of open parentheses. 1746 01:11:50,406 --> 01:11:53,096 And then inside of this second set of parentheses, 1747 01:11:53,096 --> 01:11:54,786 you put another comma separated list, 1748 01:11:55,006 --> 01:11:56,546 this time of course with the values. 1749 01:11:56,866 --> 01:11:58,946 And notice one key important detail here. 1750 01:11:59,166 --> 01:12:02,386 I'm using single quotes around each of these variables' names 1751 01:12:02,736 --> 01:12:04,846 because they are strings. 1752 01:12:05,256 --> 01:12:06,776 They themselves have to be quoted. 1753 01:12:06,996 --> 01:12:09,516 I can't use double quotes really because I've already used them. 1754 01:12:09,826 --> 01:12:12,356 So the simplest approach is to use single quotes there. 1755 01:12:12,576 --> 01:12:15,596 And now this is one thing we could not do in C. In C we had 1756 01:12:15,596 --> 01:12:17,466 to do things like printf and sprintf. 1757 01:12:17,816 --> 01:12:21,226 With PHP, if you want to insert a variable here in a string, 1758 01:12:21,426 --> 01:12:23,966 you literally just write that variable's name. 1759 01:12:24,036 --> 01:12:26,776 It will be interpolated inside of the double quotes. 1760 01:12:27,146 --> 01:12:32,186 This last line here, MySQL query, dollar sign SQL, 1761 01:12:32,746 --> 01:12:37,806 will actually execute that query for us so that if I go 1762 01:12:38,086 --> 01:12:46,056 to froshims8 dot PHP and if I type in David and captain 1763 01:12:46,156 --> 01:12:49,916 and male and Matthews and click register, 1764 01:12:50,276 --> 01:12:51,526 it says I'm registered, 1765 01:12:51,526 --> 01:12:53,236 which it's been saying frankly all week. 1766 01:12:53,236 --> 01:12:56,146 But if I now go to my database and click browse, 1767 01:12:56,476 --> 01:12:58,356 oh my God, it actually worked. 1768 01:12:58,576 --> 01:13:00,516 I have now registered for froshims. 1769 01:13:01,026 --> 01:13:01,946 Happy Halloween. 1770 01:13:02,006 --> 01:13:02,976 We will see you on Wednesday. 1771 01:13:03,516 --> 01:13:11,540 [ Applause ]