[ Silence ] All right. So welcome back to S-75. This is Lecture 2, PHP, Continued. We're actually on break on Wednesday, so this is an abbreviated week but we'll do is get you mentally prepared for the first of the projects, which for syllabus goes out the door on Monday. And also on Monday we'll continue our discussion of PHP, and also a topic of XML and exactly what you can with it and why you might use it as an alternative, for instance, to something like MySQL or Oracle or the like, when you actually want to read and/or write data with relatively small quantities of it. And then we'll actually come full circle later in the semester looking at XML again in the context of AJAX. This technique whereby webpages can go back and back and back to the server for additional data, in order to update interfaces dynamically, something like Facebook, something like Google Maps, and the like. So you'll see us come full circle with that particular topic. But for today, let's take a quick look back at where we left off last time. So last time, we introduced the very beginnings of PHP. And we made this distinction that PHP is an interpreted language. What is that mean in layman's terms? What is an interpreted language? Yeah? Well, it's read line by line and it's not compiled. Good. So, it's a programming language that something called an interpreter, which is just a program, reads top to bottom, left to right, and every time it encounters a line of code it interprets it and performs whatever operation is specified. So if that statement is print, the interpreter is going to literally print out whatever is between the parentheses for that function call. So it's not compiled. So not compiled means you don't actually run it manually through a compiler like GCC or Visual Studio, the output of which is generally something called object code, you instead just run it. And even though we'll see PHP both at the command line whereby you can use it to write things called shell scripts, right, little programs at the command line, at your blinking prompt. It's predominantly used in the web context to generate dynamic websites. And so that's, will be ultimately our focus. So what is an advantage of PHP or any interpreted language of being interpreted as supposed to compile? Why is this even an interesting distinction? What do you got? If it's interpreted, it doesn't have to be [inaudible] to be edited as this and it can be interpreted I guess on flyers something along those lines? OK, good. So because it's interpreted and you skip this middle step of compiling it, it just speeds up development time a little bit. You can make a change, test it, make a change, test it, without just that middle step. And certainly for large projects, if you did had a compile whole program, you know, in the worst of case, very large CL software projects that can take few seconds, even a couple of minutes. Yeah? And you'll be thinking you're running different operating systems and they don't have to allow different versions. Excellent. So one of the key realities of a compiled language is that when you compile it down to object code, that is 0s and 1s, those 0s and 1s are laid out in a pattern that's specific to a particular CPU, and it's a companied by 0s and 1s that are specific to a particular operating system typically. So, if you compile a program in C or C++ or the like on your Mac, odds are it is not going to run on your PC, at least not without some effort. And if you run it to compile it on a new-- the latest and greatest Mac which is, let call it, 64-bit and then try to run it on an older Mac, even that might not work because the size of the numbers you're using in that program on a 64-bit machine are twice as big as they would be on an older machine. So in short, there're some pluses and minuses in both directions. And the minus in the interpreted direction is that you can pay a bit of a performance penalty. If you're not actually doing this upfront expenditure of converting something from source code to object code, you're going to have to do that again, and again, and again, effectively when the program is interpreter. You're going to have to incur some costs then. However, as we'll talk about toward the end of the semester when we talk about scalability, there are tools that you can install on a server to mitigate this that will actually cache the results of the interpreter's first execution so that second and third times are actually much faster. So, we also talked last week about PHP: The language, on Wednesday. And we talked about some of its basic features and for now know that it's synthetically very similar to languages like JavaScript, C, C++, Java, and the like. And it has for loops and while loops. And all the things you would expect in what's generally called the procedural or imperative language. But it also has, particularly for the sake of the web, some special superglobal variables. Now, superglobal variable, an example of one was what, from Wednesday? Yeah? Well, session, post,-- Good. -- get. Session, post, get, cookie. There's a few other but those are four of the biggies, almost of which we'll actually look tonight, maybe in fact, all of them. And these superglobals are available to your program, whatever file the user has visited with the web browser so that you can access the parameters that they passed in via the URL, the parameters that they posted via form cookies that you have planted on their computer previously, and session-- well, did session refer to? Yeah? There was superglobal that was president in the entire session. So if you have, for example, PHP vowels, you can start the same session on both of them, and then you can pass variables between them. OK. Both user's usernames, but you can use that. Excellent. So this $_sessionsuperglobal, is like this container that you get for each one of the users that visits your website. And if you put something in there like the user's username, you are essentially guaranteed to be able to get that value back the next time the user visits your webpage, whether it's a split second later or maybe even an hour later, and the only gotcha is that if the session has an expiration, which is usually as long as the browser is running or that window is open, or maybe even shorter if you specify that there should be only be a legitimate for like five minutes, you will always get back to those same values. So the session object as we'll see firsthand today with some code, is a great way of remembering things like this user has already logged in. Show them their private information, otherwise show them the login screens, so we'll be able to do some basic checks like that. All right. So let's dive in with an example. So, I'm here in Linux environment and I happen to be running the CS50 Appliance on Monday when the specification for the first project goes out we'll provide you with instructions for downloading the version of the appliance that you need and navigating your way around as well as in section on Monday, we'll provide some guidance with the project in particular. So realize that there's good deal of support structure on the horizon for you. And for tonight's purposes, we'll dive into some of the concepts that you'll need to understand and to give you the mental model with which to dive into what will be realized a fairly large projects starting Monday. So recall from the very first lecture, each of the projects is intended to take some 30-plus hours. You have about nine days for each of them so just realize setting aside that time is going to be crucial. These are not projects that you can do the night before. So just be mindful of such. All right. So, I've got a bunch of prefabricated code here for the sake of discussion. And I'm going to go into this directory, Frosh IMs, which for those unfamiliar, Frosh IMs at Harvard at least refers to freshman intramural sports. So, kind of a true story, back when I was an undergraduate students would sign up for intramural sports, really the old fashion way. If you wanted to play soccer some semester, you would literally write your name on a piece of paper, you would walk halfway across the campus in Harvard yard, and then you would slide this piece of paper under the door of a resident adviser who would actually physically sign you up for that sport, and then finally start emailing you. So I think I was sophomore or so at the time and this was sort of an opportunity ripe for digitization, so we could actually put this online. And so the problem at hand I had, one of the very times I myself started doing web programming was, I really just want to convert this piece of paper form to an online web form so that the information would be stored either on a database or maybe mailed to that resident adviser so that he or she could actually know that I've expressed an interest. So, I, at the time, did not learn PHP. It hadn't really come in to its own, I instead did this in Perl but the story is ultimately the same. And in fact, it's much, much easier to do what I did now than it was some years ago in a different language, because indeed PHP like some of its cousins these days, Python and Ruby have been made all the more friendly when it comes to web development. So let's see how we might recreate this piece of paper. So, here I have some HTML. I'm going to go into example number zero and just, again, for reference, anytime we would do code in class I'll make to post the actual code in a PDF online so that afterward you can play around if would like. So here's a very simple form. I mean, this is truly like 1990-style quality of webpages. But that's OK, because we have some basic form mechanisms that we're going to use to get input from the user. Now, ultimately, the goal is to do something with this data like save it to a file or put it in a database, or create a spreadsheet or email it even to the RA. Anything that gets this information to the array is the goal. So, what-- how have I probably laid this out? Well, let's take a quick look at the code. I'm going to go ahead and view source here. And we should see some fairly familiar stuff. I'm going to zoom in. And this isn't all that interesting. Again, HTML, we'll assume everyone's comfortable with. So we've got some divs and H1s and BRs, the form is where things get interesting. Form action register0.php. So, what does it mean when it says register0.php as the action? What is the action of a form? Someone from this half or-- oh, we've not hear from you yet. Submit to register0.php. Submit to register0.php. What's your name? Hiro Pang [assumed spelling]. Hiro? Hiro Pang. Hiro Pang. Yeah. OK. I'm going to try to get better at knowing names now. So, don't be uncomfortable if I'm asking your name. I'll do my best to remember. So, action means that because the value is register0.php, when I click Submit on this form, it's going to go to that file. Now, Monday of last week, completely cheated. It means that had the action line originally be google.com and we just sent a GET request to Google. So now we're going to start sending things to our own server, and the fact that there's no HTTP or domain name there means that register0.php lives where? Yeah? The same directory as that file. Exactly. In the same server and the same directory as the file we're looking at. So it's a relative URL, so to speak. All right, method equals post. Quick sanity check, why do we-- why would you want to send things via POST versus GET? Someone from over here? If this were a quiz show, these guys would be winning. Yeah? [ Inaudible Remark ] Good. Excellent. So one of the key characteristics of GET request is that they're parameters, the key value pairs separated with ampersands, recall, end up in the URL. Now, maybe for boring information like your name and dorm, not such a big deal but if there's anything slightly private or anything large like files, anything sensitive like passwords, credit card numbers, definitely belongs via POST as supposed to GET. So it doesn't end up in the browser's cache and then the autocomplete. So now, what's next here? I just used the simple table to lay out some form fields but the interesting parts for us tonight are the inputs of which I've given a name of name to the first one. It's typed text. Captain is of type checkbox, signifying, do you want to be captain for some team, for instance? If I scroll down further, gender is going to be a radio button, either F or M. Dorm meanwhile is going to be a select menu. And so we have a nice little sampling of the various HTML form types here. And that's interesting because we'll see now server side how those form fields get translated to variables inside of those superglobals called POST or GET depending on the mechanism that we used to submit. So let's go ahead and fill up this form. Let me zoom back up. Close the source code, and go ahead and just type in David. I'll say I'm a captain, male. From the dropdown here, from the dropdown here-- oops, let me zoom out. From the dropdown here, we'll choose Mathews. Register. Interesting. So, this is not a useful registration tool but it's interesting diagnostically. And we did something very similar briefly. I think on Wednesday we're going to just look at what was being sent to the server with a function recall called print_r, print recursive. So this is not sort of production code. So just taking a look inside of what variable do you think? What did I just print recursively? POST. POST. $_POST. The superglobal that should contain all of this stuff. And again, to be clear with something like PHP, what's nice about this superglobals is you hand it everything the user passed in including files, $_FILES is another superglobal that would contain uploaded files which is super convenient. So what did I get? Name David, Captain on. So it's interesting that it's O-N, it's some non-null value, so it's not 1 or 0. It's on in this case. Gender is male, dorm is Mathews. All right. So, interesting perhaps, but let's see what I did on the server. If I go into this actual file, let me go into my public_html directory, which recall is typically where files are stored in a user's account. We'll see other techniques before long. I'm going to go into, let's say, froshims1-- rather register1.php. And here we have the contents of this file-- oops, sorry, I cheated. Not register1, gedit frosh-- register0, there we go. So what is inside of this file? Well, not all that much. I have some HTML, head tag, title tag, et cetera. And then I have a pre-tag and I recursively print POST. So this is not a dynamic website per se, it's really just a stepping stone. So any questions, though, before we forge ahead on the mechanics of how form gets to server? Yeah. When you separate this text here that's all hidden, that serves that right. If you hit view source [inaudible]. Exactly. So key distinction, because PHP is an interpreted language and because the CS50 Appliance, which in this case just think of as web server then I will keep calling it an appliance. Just a web server that supports PHP. Interpreted language like PHP will indeed get interpreted on the server side. And what happens is when a request comes in from a user whether GET or POST, and it's for a file, in this case called register0.php, the web server Apache notices "Oh, you're requesting a dot PHP file. Let me not just send that to you, let me instead interpret it for you and then send the results of that interpretation. With PHP's interpreter which is literally a program on the computer called like php.exe or something equivalent, literally reads this file, top to bottom, left to right. And anytime it sees open bracket question mark, or open bracket question mark php, which is the more verbose origin, it enters PHP mode, so to speak, and then starts executing PHP instructions line by line. Now in this file, totally uninteresting up there, why? What's the blue text? Easy question. Yeah? The comments. Just comments, right? Meaningless stuffs. So nothing actually happens there. Then we close the tag there, question mark, close bracket. And then after that, what do we encounter? Well, it looks like it's just some HTML, HTML, HTML, oh, PHP mode again executes this line, printing recursively that variable. So what happens then is anything that's not PHP, just gets dumped to the browser raw, without being mutated at all. Anything that's inside of this open bracket question mark tags will instead be interpreted. So, to be clear and directly answer, here's what we see on the server. If I, instead, go back here on the client and view source in chrome, what I see on the browser is everything except what was once before in between open bracket question mark. Yeah? So, in that case, I guess the other thing I was wondering, for example, say it just plain text you added, something important, let say, like a password. OK. -- in PHP code, is that safe or [inaudible]? Good question. What if you have something sensitive like a password in your PHP code, is it safe? The short answer, no. If you put a password in this file and this file is in your public_html directory, that is bad, because-- actually, normally it's fine, right? Because if the file is interpreted and the PHP code, as we just said, is not actually sensitive to the server, no one in the in world is going to see your password, unless you screw up, or PHP breaks when you do a system update, or some random corner case that might happen 1% at a time, but that's 1% of that time when PHP or your web server are misbehaving and a user visits register0.php and "wallah" sees your password, that's all it takes to be compromised. So instead, what would become and we'll see this before long is anything, like password, you can still put in PHP files, but you would them, for instance, in the parent directory, anywhere other than public_html or anywhere other than a special director generally called document root. In other words, you do not put sensitive stuff inside of any folder that's accessible on the web. Because by contrast, in your PHP code, you can have file reference like dot-dot slash dot-dot slash. You can go up in the directory, but users on the web cannot do that by adding dots in the URL. And this is because of web server configuration details that we'll look at in more detail. So what is the difference between the doc root and HTML-- or public_html? Really good question. What's the difference between document root which was a variable of sorts that we saw briefly in that configuration file called httpd.conf, which was Apache's default config file? Document root is where the contents of the main web server go. So, if you go food.com slash, that is the so-called document root, and it's usually a directory somewhere else in the hard drive. If, however, you go to food.com/ tilde David, that refers not to document root, but to David's personal public_html directory. So in this sense, users on a computer server, if you have a thousand users on your server, all of them have their own public_html directories, so you can kind of think that as a thousand different document roots, but the official document root is when there's no tilde involved in the URL, when you're just that slash. So the document-- the content and the document of root-- I mean, document.root, usable to every user, right? Every user on the web. Yes. Yes. But under the public_html is only used-- only usable for a particular user? Correct. Public_html is per user. And I can make this more explicit. Right now, again in the appliance, we just so happen to have a username called jharvard for everyone to use, just so that there's a user account without you have to creating your own accounts manually, and we're inside of jharvard's public_html directory. Let me temporarily become root, which is the administrative account. And I'm going to go into a directory called etc/httpd/conf. And then, I'm going to open a file gedit, which is text editor, httpd.conf. And now we get our little text editor program. This is that same file we discussed last week, httpd.conf. And if I scroll down, scroll down, scroll down, scroll down, scroll down and search for document root, here we have on line 294, it's good that I didn't keep scrolling, of this config file, a variable of sorts and Apache directive that says, "The document root for the server is in /var/www/htlm. So what does that mean? Well, let's take a quick look. Let me go to Chrome, my browser. Let me go just to httpd://localhost, which again refers to my local server, enter, and this is what I see by default, and we saw this last week, briefly. But now, let me go back to my terminal window. And again, for those unfamiliar in section, we'll play more over this and you'll have a chance on the project to get your hands dirtier with the command line. I'm going to go into var/www.html. I'm going to do LS for list, and notice there's nothing there. That's why we saw that default test message. Let me do something like this, gedit index.html, and I'm just going to say something random that's not even HTML, "Hello World." OK. Save it. Let me go back to my terminal window. And now, notice it is already readable by everyone, by default. So, now notice if I go back to my browser and reload here that is document root. So, documentary root is when you're actually a web master for a website and you don't have want this silly tildes in the username-- in the URLs, which is only used by like universities or companies when you want personal home pages, document root really refers to the root of the web server, food.com/, no tildes involved. So why use the jharvard in public_html? We won't use it for projects per se. It is just when you just want to play around with codes. It's the quickest place to put some code in the users account, so that the user can play with files on the web. All right. So Frosh IMs feel like we can do better here. So let me go back to register my websites here. And let's go to, say, version 1 of this, froshims1. So this time, I'm going to ahead and type in David. But I'm one of those users who doesn't like to cooperate, I'm going to skip the rest of the form fields and I'm just going to click Register. What happens? Well, it feels like it just deleted the form field. So, not the best user experience. I'm a little confused as to what went on. But this suggests that the server has, somehow, validated the user's input. Did the user fill out the whole form? Well, let's see how this question was answered. Let me go back to my source code. This time, I want to look at the public_html directories, froshims1.php. And this file is a little different from before. Notice that-- oops, not froshims1. That's just what we looked at. Let me go to register1, which is this file here. So, what line number-- in what line number do we check if the user provided all the form fields we care about? Yeah? 13. Yeah, so 13. So line 13 has if empty name or empty gender or empty dorm, what do we do? That's a little arcane, but I'm calling a header function passing in this very long URL, and then exiting. Now, there are cleaner ways to do this, but I want it to do as explicitly as possible for now. So take a guess, in layman's term, what is line 15 doing? Yeah? Sending back? Perfect. It's sending the user back to the previous URL. Now, I say this is overly verbose, because you shouldn't-- I shouldn't have to hard code the whole URL like this. This is clearly going to break as soon as I move it to another server with a different name, but I just want to be super clear as to what was going on. And I call exit specifically, so that no more code happens. I want the user to be bounced right away. Now, what does it mean to say location colon? Where have we seen that before? Yeah? It's seen in the headers or packet. Good, the headers of a packet, the headers of an HTTP request and response, specifically. So let's actually take a look. Chrome again is a handy little tool to see things going on, and you can do the same with similar tools in IE and Firefox. Let me go ahead and open up Inspect Elements here. This is the developer toolbar. I'm going to the network tab here. And let me try that again. So I'm going to say David but nothing else. Register. Now, notice what happens down here. I've a couple of rows. This first row means a request was made to register1.php. The second row means a second request was made to froshims1.php. That is consistent with the story you just proposed, whereby we're getting redirected. Well, let's see what's happening. If I click on this first row and look at the headers, notice what status code came back when I request the register1.php, 302. Now, in my code, there's no mention of 302, and that's just because PHP's header function is a little smart. If it sees that you have said literally location colon, as the string you're passing to the function, it realizes, "Oh, you want to redirect the user." It will infer for you 302-- 301 is the other option but it does 302 by default, and then it sends where-- where should I see the location header? Do I have-- want to scroll up or down here? Actually, I'll just scroll down. Response. We want the response. I didn't remember where it was either. So, location, that's how this magic just happened. OK. So that's all. We tied it now together to the lecture zero. Let's go back to the code here and look at how this line 13 is executing. So you can probably guess what the empty function does. There's a bunch of function with which you can check the validity of strings here. But $_POST angle bracket quote and quote name, is doing what? Can someone translate that into less technical English? Well, the POST is an array so it looks for the key name inside the array and the empty function probably checks if it's empty. Excellent. So POST, again is an array. It's not a numeric array with which you might be most familiar. It's an associative array, which is conceptually similar except your keys are no longer numbers, like 0, 1, and 2. They're instead anything you want, like strings, foo, bar, and baz, or in this case name. So, if there is not-- if there is-- this is checking. If the value of the name key in the POST superglobal array is empty, and empty just means nothing is there to quote and quote, it's nothing interesting, then that evaluates to true. And because we're doing or, or, again like you would syntactically with two vertical bars, like in many languages, we're just saying if anyone of these things is empty, redirect the user. Now, not very user-friendly and I'm not even telling the user what he or she did wrong, but it's at least the steppingstone toward that. What comes next? Then, I've just got my HTML at the bottom. So there are different ways to do this in PHP, but notice the paradigm we've adopted for now. We're putting our logic at the top of the file. We're doing whatever kind of ifs or elses that we want up there and then when we're ready to show the users something, we dump it and we dump the raw HTML at the bottom of the file, and that's it. So, if I scroll down further, there's nothing really of interest down there anymore because it's just going to say, "You are registered. Well, not really." Let's see that. How do I get a web page that literally-- that really says, "You are registered. Well, not really?" How do I get to this point if my form, again, is this? What fields do I have to fill out? All of them. Close. Yeah. Gender is true, but one more. Dorm. And dorm. All right. So it's not technically all of them, because I don't require that someone be what? A captain, just because that would be a little weird to require that check box, but I've check for these three. So now I'll click Register and "wallah" you are registered. Well, not really. Well, not really because I haven't done anything with the data. All I've did was done-- just tells the user you're registered, but I haven't told resident advisor or anything like that. So, let's see if we can improve upon this a little more. So, let me go into froshims2 this time. Let me pull up the source code and my editor. So this will be froshims2 in here. And in this version, notice that my form is pretty much the same. It is the same actually, but it submitting instead to register2. So that then begs the question what is register2. Let's do that, register2. And now what is this doing, this is doing a similar check, but where is it going to-- how is it going to handle the error differently this time? It's not going to redirect the user. It's going to do what? Well, if one of those required fields was empty it's going to go dump-- it's not going to echo but it's going to dump some raw HTML and say you must provide your name, genre, and dorm. Excellent. Otherwise it's going to dump if you're registered. Excellent. So last time, it was kind of lame attempted error checking to just redirect the user back to the original form without giving them any kind of feedback, so I'm doing exactly that. Now, I'm using the same logic, if empty, if empty, if empty. But this time, rather than redirect, I'm going to conditionally output some text. So notice some slightly different syntax. They'll have my open bracket question mark, some PHP code, but notice what's over here, the colon then the close PHP tag. So this means, if that expression is true, proceed to-- dump whatever it follows that colon, until you see an endif. So, it's a little strange here, but it's kind of a nice one-line way of laying things out. So, if any of those three fields is empty, it's going to say, "You must provide your name, gender, and dorm." Oh, and this is nice, a little hyperlink back to the previous files, slightly user friendly, else colon, "You are registered. Well, not really." So still, not ready for prime time, but a step in the right direction. So let's try this. Let me go to my browser and type in David, and that's it. I'll be a difficult user again. Register. And now notice here-- oops, I'm still on the previous one. We want froshims2. Looks the same, but I've typed David and register. And now, I have a parse error. So, this is good teaching moment. Line 20, what's wrong here? Let's take a look. Let's go back to my text editor. Line 20. And what am I missing here? Oh, this is subtle. This is good. David screwed up. Yeah. [ Inaudible Remark ] No. So the colon is actually necessary. I am missing something. Good opportunity for error? Yeah. Yeah. I think you're missing an extra parenthesis. Yeah. I accidentally left off a parenthesis. It's all right. So a stupid newbie mistake. Let's assume this was deliberate for the sake of teaching. So, I'm missing a parenthesis, right? This is just sort of CS101 stuff. There was one over here. I need one on the end. So let's me save this and reload. And notice here, we talked about this last week. I've just reloaded the page but it was a POST not a GET. So users with some browsers will warn you when resubmitting a form in this fashion. So that's what we're seeing here. And now-- Uh-oh, we're getting that warning message. Yeah, Connor [assumed spelling] [ Inaudible Remark ] It does not. You do not need a colon after the endif, because think of this as continuing a sentence, "If this is true then," so think of the colon as then. Else then-- and an endif is just-- that's it. There's no more part of the story. So, just so you've seen another approach, even though it's a little weirder, you can avoid using the colons. You can, instead, use an open curly brace with which you might be more familiar. But if you do that, you then need to close it there and open another one here, and then close it here. So this is perfectly legitimate, syntactically. If you prefer it this way, that's fine, just realize it's a little strange maybe, to have these curly braces sort of a no man's land there. Just a style decision. Just go with whatever you prefer, but be consistent. All right. So, what about version 3? Can we take this a little closer to something even cleaner? So, this version, register3-- froshims3 is going to submit to register3. So, again, I've just copied and pasted the same Frosh IMs file, just so that they redirect elsewhere-- submit elsewhere, so that we can demonstrate them one at a time. So register3, now it's getting kind of fancy. What does this version apparently do based on the PHP code up here? Yeah. Yeah, so this one sends an email. So, finally, we have something that not only is useful for the users, it's finally useful for the RA, because he or she is finally going to get an email. Now, not as good as a database, but my God, it's better at least than nothing. So, how does this work? Well, again, I'm doing the empty checks, but this time backwards. Notice, I've switched my logic around. So, if name is not empty and gender is not empty and the dorm is not empty, then do the following. And I have a few new pieces of syntax here. There's different ways of doing this, but notice that $to is just a local variable. Recall that, Wednesday, we said that all variables start with dollar signs in PHP, "malan@cs50.net", which is one of course email addresses. It's just a string followed by a semicolon. Subject is registration, body is this backslash N, recall is a new line character. Take a guess as to what the dot character is. What's the dot symbol mean? [ Inaudible Remark ] Not end of line per se. If you have two [inaudible] you want to combine them. Good. Also strings so you can a variable dot and then something. Perfect. So it combines two strings. And the buzz word for this is the something, something operator. [ Inaudible Remark ] Concatenation operator. So the concatenation operator, in this case, is dot. In some languages, like JavaScript, it's plus. Java it's plus. Some languages don't even have it. But this is just building up a string. Why did I do with this way? Well, it's just because I want to format things a little more user friendly on the screen. So, I wanted to put things on separate lines, rather than having a crazy long line of code. Now, notice how I'm doing these two. I have dot, POST, "name" POST-- "captain" followed by new lines. So in short, I essentially want the array to get an email, where it says name, colon, gender-- captain colon, gender colon, dorm colon. So, it's a quick and dirty email that just shows him or her, what the user submitted. And then, this line is necessary. And I know this just from reading the documentation. The headers line needs to have my from address. It has to have a backslash R backslash N, which is a carriage return new line, sort of a windows thing, but also used in other context as well, like mail here. And then the mail function that comes with PHP is as simple as to, the subject line, body, and headers, so we have a new PHP function there. So, I got you. This mail function doesn't often work, because it totally depends on your own local network. Many ISPs, like Comcast and Verizon and the like, do not let you run your own mail server, much like ISPs tend not to let you run your own web server on port 80. So what many ISPs do is they actually block inbound port 80 traffic as we discussed last week. They also blocked outbound port 25 traffic, which is for SMTP, simple mail transfer protocol, which is used for outgoing mail. The reason being they assumed, that if your personally computer is sending mail directly out of the internet, you're probably inspected with some botnet or something like that, that's spamming people from your machine. By contrast, when you set up your mail-- a mail client behind-- in your home using an ISP, you're typically told use smtp.comcast.net, use smtp.verizon.com or something like that, so that all mail is going through their server. So I mentioned this because even though sending mail is in theory, as simple as this one line of code, ultimately, it will often not work from your own machine or in this case the appliance, because your ISP will block it. So, typically, something like this will work on campus here at Harvard, but not as soon as you get home. So, for more robust environments, you typically need to use a different function, in fact the different library of code that lets you talk to an SMTP server, like Comcast or Verizon or the like. So, just FYI for now, that this will not always work. It really depends on your network. What happens if the user does not actually give us all three of those fields? Same stuff as before. We redirect them. But if we do get down here, we tell them that they are registered, really. So notice the logic here. Under what circumstance am I exiting and redirecting the user, just to be clear? Yeah? If all the required fields aren't completely filled in. Good. If all the required fields aren't completely filled in, then we get to this line of code. And because of the exit, we never get down here. By contrast, we will get down here after we send the mail, because there is no exit line after mail in this case. What's your name? Axel [assumed spelling]. Axel. OK. All right. Any questions? Yeah. What would happen if you left the header blank? What would happen if you left the header blank? "Nothing." It's a good question. Let us try. So, register3. Let me go to froshims3 here. Let's type in David but nothing else, so that we get that. This happens. So, just kind of errors out, and let's see what's comes back. Register3, it got sent David in the response headers, where-- so it just sends nothing back in this case. So it's like sending an empty header, and then exiting. Good question. All right. So, let's take things one step further. Let me go ahead and close this, which was version 3. And let's open up version 4 here. So, let's start cleaning up our code a little bit. So, now, notice this is not accompanied by another register file. This is register-- froshims4. And what is the action value of this file? Yeah. Me? Sure, Axel. Froshims4. Froshims4. So that's interesting. This PHP file is going to render a form on the page, and that form is going to be submitted back to itself. So, this is kind of interesting. And what problem are we solving here? Well-- Yeah, go ahead. Now you're able to do stuff directly on the page when someone does something wrong. Exactly. When someone does something wrong, because we're submitting to this very same file and in that file is the original form, we now have the opportunity to not kind of cut corners and say, "Oh, something happened. Hit your back button," rather we can show them the form again and maybe yell at them on that same page. We just have to have some conditional logic in this file that says, if an error happened, show the error and the form, else just the form, right? Because what's one of the most frustrating things about really poorly done websites, whereby you see an error message on the page, and then you do have to hit the back button. Worst case, what happens? Everything goes worse. The whole form goes-- everything goes away. The whole form gets erased because the browser hasn't cached your answers. And so, it's just a pain in the neck for the user, not a good user experience. So showing them the error messages on the same page is definitely ideal. So, let's see what's going on in this file. Let me scroll up to the very top, and we'll see that if isset POST action. So many different ways to do this, but I chose a fairly explicit way, if a key called action isset in POST. So this is just another way of asking the empty check, but sort of in the opposite direction. So if it isset, that means that a form is submitter. Why is that? Well, if we scroll down below in my actual HTML form, what is the-- what type of value is action? Rather, what type of input is the action parameter? Yeah? It's the submit button. Yeah. Yeah, when you submit it, you're going to have action. So I chose this word, somewhat arbitrarily, action. I could've literally written foo. The only point is that, when the user submits this form by hitting Enter or clicking the Submit button, I want to make sure that there is at least one HTTP parameter that gets sent to the server that I can check whether it isset or not, because if it isset what is the implication logically? That they submitted the form because no user, unless they're crazy, is going to manually type in the URL, question, action equals true, or something like that. So in other words, we can infer with pretty high probability that if that parameter is there, it means the user submitted the form. And that's all I need, a way of distinguishing form from no-form submission. So now let's scroll back up to the top, because almost all the HTML is boring and identical to before. So, if that value isset, then I'm going to do my same boring check, if it's empty or empty or empty, this time now I'm going to set a variable, error equals true. Now here is one of the messy things about PHP, scope, kind of goes up to window in a file. If you declare a variable anywhere, everyone else in the file can see it. So, whereas in some languages like C or Java, if you declare effectively a variable inside of curly braces, the scope of that variable is only on those curly braces. You can't use it or see it outside of the curly braces, not true in PHP. Not the best design but that's the way we have it here. So, if error isset to true, that variable now exist for the rest of the file. There's an exception. If you declare your own function as we'll eventually do, and that function is in this file, even if it's [inaudible] around lower in the file, when you're inside of that function, you can't access error. So, variables are global in the sense but not quite global, because when you're inside of a function, you can't see the variable. There's a way around that, but this is kind of another nuance of PHP's design. OK. So, now we've done our error-checking. Let's see what's different later on in the HTML. Can someone explain and insert in English, how I'm now using this variable. What's going on here? Yeah? [ Inaudible Remark ] Exactly. So when I get to the very top of this webpage, the H1 tag gets spit out. But then I have a quick little PHP check, if error. So if it's true, if it's said, if it's non-null, go ahead and add this other div in red, you must fill up the form. So, it's a way of just yelling at the user in the same page and then everything else here is the same. So let's take a look at this behavior. This is version 4. So let me go back to my browser and go to froshims4. I'm going to type in, oops, undefined variable error-- sorry. I was tinkering right before class. Let's see. Froshims4, line 28. OK. So, what we're seeing here is the following. So this two is a web server feature. This is a notice. In PHP, there's different levels of error reporting. There's notices which is like a slap on the wrist, like, you kind of did something stupid but not a big deal we're going to forge ahead anyway. There's warnings, which means you really did something wrong. It's not a deal breaker. I'm going to let the rest of the code execute but you really should fix that. So that's like a harder slap on the wrist. Errors means you get punched in then face, like the code will stop executing if you have an error. And that's if you really do something stupid, like your password is wrong for the database and so it just doesn't work, or there's a syntax error and it just doesn't work. And you can actually change things in such a way that PHP will show you notices or not, show you warnings or not, errors you kind of have to know about eventually, even if it's just in the logs. So there's this different levels. Now, what's this notice all about? Well, in the previous example, I was very careful to say, if isset is empty. But this time I kind of cut a corner. And how did I check if error was true? What did I do? [ Inaudible Remark ] Exactly. So because I only set error to true, if there's actually an error, there are circumstances in which error has no value at all. Under what circumstances does this error value not even get assigned value? Well, if there is no-- if you filled out all the forms, it's never going to pass through-- it's never going to define error so it's just going to be nothing. It's not going to be true or false. Exactly. So if we have-- actually, if haven't filled out the form or I've submitted it entirely correctly, I'm not going to set that variable. I only set it if there's an error. So in other words, I'm kind of de-referencing here, a variable that doesn't exist. So there a couple ways I could fix this. I could go back up to the top of my code and make sure that error is initialized for instance to false, and then only set to true inside of those if conditions, or I can do something else that we've seen. You can see if error exists [inaudible]. Exactly. So I could just do if error isset, which is the way I did this earlier. Then, the only circumstances in which I said it, as we've seen logically, is when there's an error. So this would now make PHP happier. So, this sort of-- this is the right way to do it. But you will see-- even occasionally in lecture examples, because I've tend to be in this habit but I've gotten better to not being in this habit or in various open source libraries that you might choose. Sometimes users will just check parenthetically for Boolean values like I did there, but it's not the best practice. And that's because PHP is a little loose when it comes to declaring variables that can be set or not set depending on your logic. So, what I've just done here is in fact better and the recommended approach. There is one other way, just so you've seen it, but this is "do as I say, not as I do." You can suppress notices and warnings by doing this. So, if you put "at" symbol before a line of code or variable that you think might not be perfectly correct the "at" sign will suppress the notice. However, this is not good practice because this really just like sweeping under the rug, you're failing as a programer. All right, you should really be fixing this the right way but realize that there are some cases-- and this is not ideal. But if you're using someone else's function and it might trigger a notice because they weren't the best programmer or warning and you don't necessarily want to go and try to correct their code, if you know it's OK to suppress that notice, you can do it with this particular mechanism. But don't get into this habit, in general. Certainly not for your own code where you have the power to fix it properly, as we did with isset. All right. So this form, so let's go back to this. Let me go back to isset. And now let me pull up the page and let's see that red box up here. So let me close the inspector and do just David. Register. OK, so pretty slick. It moves everything down, gives me the red div and yells at me, but kind of annoys me as a user because we did not do what? You typed in David. Exactly. I typed in David. David was fine. That was not an invalid value, why did they get rid of it. So I need some way of putting it back there. So, OK, I'm going to kind of be a little silly here. I'm going to say, "OK. Well, we can fix that, value equals "David", right? That's an HTML form. Go back here. Reload the form. David. Fixed, but obviously not. Why? Yeah? [ Inaudible Remark ] OK, good. So I've hard-coded David, which is just can of idiotic. So, it only works now for a subset of humans named David. So, we've-- but we can infer from this, how to generalize this. Really, we want to put something there, just not the AVID. What do we want to put there instead? So, if you have the PHP isset, sets that value for name exists, put a value for name [inaudible]. Good. So we can put the user's actual name there. So, that they have submitted via the forms. So let's take a look at how we might this logically. I'll stay on version 4 here. And let me go ahead and do this. And tell me what's good or bad about this. Open bracket question mark, then I'm going to say, echo$_POST"name" close quote semi colon close PHP mode. So, good or bad, this approach? Yeah. You said before that you will probably want to check if it's set also. Good. Why though? What's going to happens if I don't check? [ Inaudible Remark ] Yeah, actually we saw it before, that notice massage. Like if try to access a variable that's not actually in existence, I'm going to get a notice. Now whether or not I see, depends on the server's configuration. But in this case, name is not going to exist when you first visit the form and haven't clicked the Submit button, right, because it only exists if you click the Submit button. So I feel like I broken my code now right out of the gate. So I can add conditional check there. It's a little messy and that this line is going to get a bit long, but I could do something like this, if isset POST name. Then go ahead and say, echo POST name. So that's a little better, semicolon. So, does this ameliorate our concerns? The coloring is a little weird because the text editor is not smart enough to understand this syntax but it looks OK. Still flawed. Find further fault in my code. Someone over here? No? OK? There are no brackets [inaudible]. There are no-- that's OK. We don't need the curly brace if it's just one line of code, but a good thought. This is like C in Java where you can skip on the curly braces for single lines. What's your name? Isaac. Isaac. OK. So good thought but not necessarily. Endif Endif, good thought. Endif is not necessary here. Endif is only necessary when we that colon type syntax, to get in and out of PHP mode. It's not a syntax book. This is more of a design failure on my part. And I made the same mistake on Wednesday, if that helps. What was the sort of hacker attack I waged on myself on Wednesday? Oh, well, now that I tell you, yeah, OK. You would want to do HTML special chars or strip tags to get rid of any additional-- Exactly. So stupidly named function, HTML special chars is probably the better of the two in this case but that is a function that makes sure that if the user is trying to mess with you by typing an open bracket or any characters that have special meaning in HTML like ampersands, they will be shown literally as open brackets or ampersands and not misinterpreted as HTML tags. So what I really need to do here is not just echo the variable's value, I instead want to do something like HTML special chars and pass that value to the function thereby not trusting what the user has given me. Do I need to call HTML special chars on the value when it's in the parenthesis in the condition? No? Why not? Yeah. Because you're just testing in its existence not its value. Exactly. We're just type-- well, we're testing its existence and we're not displaying its value. So we don't need to escape it. And what's your name? I'm Jack [assumed spelling]. Jack? Jack. Jack. OK. So good. So we need to-- that again, the rule of thumb from Wednesday, always, always, always, escape user's input when showing it back to them using this function here. As you mentioned, there is an alternative strip tags which does exactly that, it strips HTML tags from a string. But you-- the user might not in this case, but in general, the user might want to input HTML like tags for instance if it's discussion forum post but you wanted to display it literally. So stripping tags probably isn't best but escaping it is indeed the better approach. All right. So good, that's some progress here. So that will now display my output. So let's try this again. Let's do Chris so that it's obvious that it's not just me. And now it's submitted, and Chris stays the same. So it gets a little trickier for the other form fields and I will leave this as sort of a at-home project exercise, potentially. But something like this for captain, for a checkbox, how do you make a checkbox checked by default? Yeah? You type checked=checked. Good. So and actually in HTML5, you're allowed to regress and go back to just the atomic model of this. In XHTML, you would say, checked= checked. But in HTML5, it is OK these days to do this, which is a little more succinct. But now, I've, of course, just hard-coded checked so now the captain box is always checked. But what if I only want to check it if the user has checked the box to begin with? They've just screwed up elsewhere? I want to conditionally output this. So how could I go about doing this? Jack? We go through the same sets of steps before doing an isset for captain and then if it is then put check in that. Exactly. So same kind of checked if isset then echo checked, else don't echo anything would be one approach. I have a question. Would isset work because if we post a non-checked version, wouldn't that just be off? The variable would still be set, right, just set to off? Good-- yes, good refinement. So we don't want to just check if isset, this time we should be probably use empty or some other function that actually checks not just the presence of a value but what the value is because indeed when you submit the form, if it is checked, it will be set-- actually in this case, this case, there's actually-- there's a way out of this discussion because most browsers, if you don't check a checkbox, won't send that HDB parameter. But that's not necessarily a safe reliance so your approach is better. Actually checking for "on" or whether or not it's empty or not. So frankly, this starts to get a little messy. If I take-- there's an allegiance arguably to the fact that inside of my value-- next to my value, I have the quote unquote. And then I have my PHP code inside of the quote unquote. But what's the analogue here? I could kind of copy and paste code like that and smack it in the middle of the input tag. But this just start rubbing you the wrong way stylistically if nothing else, right, like all of a sudden, you're in the middle of an HTML tag then you jump into PHP mode just to spit out a word. There's probably a better way to do this. And in fact, there's many different ways we can do this. But arguably a slightly cleaner approach just to get you thinking about design options might be first, let me just clean up the statics there. And why I don't do something like this? So if empty$_POST "captain":. So if that s empty, go ahead and spit this out. And you can probably guess where this is going. Else, spit this out. And then what do I need down here? This is where I need the endif because I'm using that colon approach. So it's a little-- oops, it's a little redundant but I'd argue this is so much more readable than putting-- clapping a big line of PHP code in the middle of an HTML tag. So this is probably a little bit better. However, before long, we'll get past even this. And you'll find that in PHP, there's actually libraries and frameworks that actually makes this much simpler. There are libraries that will actually regenerate your forms for you based on what the user typed in, because frankly once you start making your second dynamic website, 3rd, 4th, 10th, this kind of stuff, this error checking, this repopulation of form fields, it just gets very tedious. So realize right now, we're doing things fairly hands on, very manual, very deliberately but realize there do exist libraries for PHP and other languages that just take what will become am-notness about this process out of it for you. So just realize that. But they're really just doing something like this underneath the hood. All right. But let me open up version 5 here and see where we can take this a little better, actually not 5, we just implemented 5 ourselves by changing 4. So this is an improvement too. Notice at this time, for the dorms, I decided it's kind of lame that I'm hard-coding all of the dormitories at Harvard in Harvard Yard in this big select menu. It feels like those should come from a database or something like that. Now, I'm not going to introduce databases yet tonight but I can still mimic the idea by at least putting them in a global variable so that maybe the list of dorms is saved on a server somewhere in a configuration file, a separate dot PHP file that this one includes somehow an access us. But then, I can simplify my options to just a single one. So notice in line 76 here, I have a new construct and you might see this similar in other languages. This is what's called-- generally called fast enumeration whereby for each dorms as dorm. So let's infer from this, what is $dorms apparently? Yeah? The array of all your dorms. It's apparently the array of all dorms. Haven't really seen it unless you look really quickly before I scrolled. But there's probably an array somewhere in this file called DORMS, all caps, that's kind of acting like our global constant array. But it's not technically constant. As dorms. So $dorm, lower case, this is effectively local variable for this loop whereby it will be assigned to the value of every dorm in succession in that array so that you can then use it in line 77 where I say option value equals dorm, and then another instance of dorm and then option. What's the difference between these two? Why did I put it in two places, both here and here? Yeah? One is the value that you'll be selecting and one is the value that it ends up sending. Exactly. So what get sent is the actual value attribute. What the human sees is out here. And what was the significance from last Wednesday of open bracket question mark equal sign? Yeah? That's a quick way of printing or-- Exactly. Quick way of doing echo. Quick way of doing echo. Do I need HTML special chars here? Jack? No, they're all your-- you've hard-coded all the stuff in yourself so you don't need special chars. Good. Only if I screwed up and actually put like weird HTML tags in my dorm list. If I can trust myself then I don't need to bother calling HTML special chars here because the data is coming from me not from the user. Now, notice I am not in this version apparently doing what? If the user fails to submit the form properly. There's no if. There's no else here. So apparently, I am not going to preselect this select menu's option if the user fills part of the form but not all of it. But you can imagine somewhere inside of this loop probably having a condition check saying if the current value in the array is equal-equal to what the user submitted in POST, the superglobal, then add what attribute to this option element. For those-- if you recall from HTML, selected so you just say selected and that's the one that will be highlighted by default in the menu. But I'll wave my hands at that as a sort of fun project exercise potentially. So at the top, where is the logic here? So here is my array. So frankly, it's kind of ugly syntax the PHP has for this. You have to actually call the array function to make an array. But this is how I've done it, $DORMS=array. So this means a comma separated list of the things I want to put in the array, close parenthesis, semicolon. Now, I have my array. And I called it, all caps, DORMS, just to send the message that this is sort of like a global constant even though if I goof, I could technically accidentally change this array. And then the rest of the files pretty much copy and paste from before. All right. So I think we're running out of ways of improving this but let me propose just two final ideas, one of which answers the shortcoming of the last. What is this doing based on your inference in line 76 and their about? Yeah, Jack? [ Inaudible Remark ] Good. And there's one mistake in my code. I'm again assuming that notices are disabled which is kind of lazy of me, because what will this code do erroneously sometimes? Yeah? [ Inaudible Remark ] Exactly. So if the user did not actually submit the form yet, and I'm iterating over this, I'm accessing POST dorm even though it's not technically there yet. Yeah. Question on line 80, when you do value equals dorm [inaudible]. Really good question. Let's come back there, to this question of dots in just a second. So there's a couple ways to fix this, the cheating way is kind a just do this and suppress it. However, I would sometimes argue that this is kind of reasonable here because the alternative is if isset$_POST dorm and, so that would fix it. But what do you dislike about this, perhaps? It takes some space. OK, take some space, but most anything we write will take up some space. But that's kind of fair. Be a little more compelling than that. What's bad about putting that check there? What's two lines earlier? Oh yeah. You wouldn't want to-- you would want to check before actually [inaudible]. Exactly. So, this kind a stupid that I'm doing this in a loop because I'm asking literally, the same question again, and again, and again for every dorm even though I should technically only have to check if that variable set once and then proceed to loop over the results. But, frankly, if I've moved the if-- if I move that check outside of the loop, then I have to have another case where I spit out the list by default. So in short I'm going to actually wave my hands at this because this is actually an interesting design problem for something like a project where you put those kinds of checks. But for now, realize the take away is that if I do put it here, it's good. And frankly, it's probably not such a big deal because this is a very short list. The computer is like a gigahertz, 2 gigahertz, 3 gigahertz. We're going to fly through this list anyway, but realize that we are wasting some CPU cycles to check isset, isset, isset, again and again. Yeah. How come you just put it on the outside and then create some sort of variable for [inaudible] make it true or false whether or not it's-- So, absolutely, we could lessen the computational cost here by storing the results of isset in a Boolean variable. And I said Boolean but it's just a variable because there's no data types you explicitly associate with variables, and then we just check the value of that variable. We're still wasting a CPU cycle or more checking that Boolean value. But function calls like this tend to be more expensive than actually checking variables. With that said, it's not necessarily the case that there's much overhead for isset since it's a native part of the language so it could actually be implemented pretty efficiently, so you could re-factor this. But really, there's many different ways you could address this and one of them might just be it's fine the way is it, and in general for the project realized that when it comes time to make decisions, if you realize you're kind of struggling to decide on something or you're very comfortable with your conclusion but you think a reasonable person like a teaching fellow might disagree with your perspective. What we'll do always, is encourage you explain and comments what your design decision was. So, if were to prefix this loop saying, we're checking again and again but it simplifies the code, it improves the readability, you know, that is a reasonable measurement of quality. If it's more readable, if it's more succinct, less code. That's actually not such a bad thing. But justify it, because again, all roles as the teaching staff will push back on you and say, you know, maybe this is OK but if you didn't think about it and then conclude consciously that his OK, then really, we haven't done our job for not pointing that out. All right, so that's a fix for that. Let's do one last improvement here. And it this case, what's going to be different here? This time we're submitting notice to register8. So let's take a look at what's ever so slightly new here, register8. So this is a little sneak preview of something we won't do just yet. But notice, as a sneak preview, how could we store this in a database and more on this in a week or so? We will soon see a technique whereby you can call function like MySQL connect, and MySQL select, and MYSQL real escape string and we'll see cleaner alternatives to this. We don't need to use these very verbose versions that are tied fundamentally to MySQL. But notice, down below is a little teaser of another language. Anyone know what language is being used in line 33 here? Yeah, Axel? That's my 33-- yeah, that's MySQL. Good. And more generally, SQL, so structured query language-- MySQL is the specific database but the language in question is just SQL here. So this will be a language we'll use in about a week or two whereby we'll be able to query databases for the information and also write information into databases using a language like that that tends to play pretty nicely with PHP. So a sneak preview of what's to come. And I offer this now as a teaser because it's probably better rather than emailing the resident advisor, all of the submissions so that he or she then has to go through their inbox finding the registrants putting in a database, so that he or she can just pull up a webpage with everyone, is probably a nice endgame and definitely more consistent with a truly the dynamic website. Any questions? Yeah. What are some of the difference between MySQL like [inaudible]? It's a good question and kind of a loaded big question. So we'll come back to this if that's OK when we actually talk databases. But MYSQL and Oracle and Microsoft Access and PostgreSQL and a bunch of others are relational databases which mean-- and they are SQL databases, which means they store information generally in tables. And the table-- a table is something with rows and columns like in Excel spreadsheet. And as we'll see, this is nice because if you submitting like registrations for sports you can think of a nice spreadsheet as being row by row by row by row of all the students who were registered. But things get a little messier if you realize, "Wait a minute. I'm storing Matthews, Matthews, Matthews, Matthews, the dormitory for all of these students again and again and again, and I'm spending M-A-T-T-H-E-W-S, 8 bites at least to store Matthews again and again and again. It feels like I should be able to factor that out, maybe give Matthews the dormitory a unique number like 3 and the associate only the number 3 with all of the students to save on space and improve efficiency. So then I have a second table. And if you continue that logic for larger projects, you get more and more tables and more and more complexity. And you start to lose the object-oriented nature f some entities. So you can think of a student as being an object or a student has a name, student has an ID, student has an address. The problem were, A, arguable problem with relational databases is that you essentially have flatten objects like students into very flat things like rows. And this tends to get annoying if nothing, if nothing else. And it can also be subpar for performance in some context. So all the [inaudible] these days is this NoSQL momentum, which generally refers to other types of database more on-- generally known as document stores or object-oriented databases, where if you have a objects in the Java sense or in the Java script sense, you just store the objects in the database and you don't worry about the somewhat arbitrary world of serializing things to rows and columns. So let me live that as our teaser for now, of what's to come when we get there, but we will focus in this class, mostly on relational databases and mostly on MySQL the particular incarnation thereof. All right, so tonight so that we can equip you fully for the first project which again we'll be going g out the door on Monday. We'll probably will use the full class time, so we'll probably take a couple of breaks tonight before section just to set your expectations. But why don't we go and have a five minute break now, and we'll regroup with another tour with PHP. All right. We are back. So, what is this? Yes? Facebook login. OK, good. So, probably looks familiar to many of you. So this is Facebook's login screen, representing a typical login form, whereby you have username field of some sort, password field of some sort, a log in button, and then generally this little chec box that somehow keeps you logged in. So what we've done thus far with our PHP examples is we've started to take user input in terms of forms but it's been fairly stateless. As soon as the user submits the form, if it is all correct, it gets dumped to some database as we most recently saw or it gets emailed or nothing happens to it altogether. But that's it, there's no recollection that the user have filled out this form or remembering, really, who they are at all. So now let's take a difference scenario, a very common one that of authentication, and actually enabling users to log in to a website so that they can access content that's somehow restricted to certain people based on their username. And to do this, now, we have to implement and code that notion of the hand stamp that we talked about last week, whereby once I log in I need you on every subsequent page that I visit to remember that I'm not logged in, so that there's not some annoying repetition of asking me username and password, username and password, every time I tried to click a subsequent page. So how is this sort of virtual hand stamp implemented could we say? What's the secret sauce for this feature? Jack? Session Yeah. So session, but what does that mean? Something that you can tell whether or not the browser has already gone through this and the user has already put in their username and password-- Good. Good. So in general, a session in the context of early web development irrespective of language has to do with some state that is associated with the current user and that state is unique to that user are not shared across all users. And PHP as we've seen from that list on Wednesday has a superglobal called session-- $_session in which we can store mechanically any variables and values that we want. Axel? I was just thinking, I think session in PHP stores session [inaudible]. OK. Not quite. So we'll actually pull the layer back off of the session object in just a moment. So let's first see how we do it in code at a high level and then [inaudible] back that later and see how the session superglobal, itself, is actually implemented. And we even try sniffing some additional code to see what's going on underneath the hood. So let me go ahead and open up a file, no longer in my Frosh IMs directory but instead in log in directory. All these codes available online. And I have this little cheat sheet here just for notice. And let's fix this error first. So I've gotten a lazy here in this file. This homepage is just meant to give me hyperlinks to the four version of log in demo that I put together. What have I done wrong and where is that error? Let's get into the habit of reading these error messages now. It's a little small. The font, I can zoom in if that will help. Tell me exactly what to do. We've seen this before. Yeah, Jack. Authenticating is not defined to be any value. OK. And what must authenticated be? Some sort of value. Some sort of variable that-- Good. Yeah, so we saw this before with my error variable. This time it's apparently called authenticated. And that kind of make sense, right, if the whole goal as I've just promised is to implement the notion of logging and make sense that there might be a variable called authenticated, which is true or false base on whether or not I have logged in. And it apparently is on line 24 of home.php. So, what's the fix for this probably going to be? Isset? Isset. So let's do that. Let me open up my log in directory, home.php line 24 and-- there it is. I got a little lazy. Well, let me just point out a couple of other techniques for dealing with this kind of issue. So one, realize that this big loud orange error message is not the default behavior for PHP. We have installed in the appliance, and this freely available on other servers as well, a tool called Xdebug, which is a tool that makes PHP's errors more verbose for diagnostic purposes. And it's not that interesting here because we have very little code, but it also gives you what's called a call-- a trace of all of the functions that have been executed to get as to the point of this error. In this case is not interesting because only one function was called to get us here and it's even an explicit function, it's just main, the sort of default file that we're in, but it does identify the file as being home.php in the orange message, home is closer on where the error message is. So just realize, you don't get this on all servers unless it's enabled. But for us, pedagogically, it's definitely useful because you see a bit more. So I can fix this in a couple of ways. Let me go in to home.php and I'm going kind of do this, suppress NOTICEs. And I'm going to do, error reporting and I'm going to say E_ALL X or E_ NOTICE. So let me see if I got this right. Here we go. So gone, problem solved. Well, not really. This is what I meant earlier about sort of sweeping thing under rug. What have I done? I've told PHP to no longer tell me about notices. Now, this is sometimes done on server, but again, it tends to hide shortcoming in your own code. But where is the setting coming form in the first place? Well, let me go back to my terminal window and recall that I can become the super-user, the administrative user, by doing sudo, SU. And now I'm going go into ETC, and then I'm going to open up a file called php.ini, which stands for initialization. And that's going to open up a big config file, this one for PHP. And I'm going to search for error reporting. And on line 112, there's some documentation for whatever reason PHP use semicolons for their comments' character, so all these blue texts is comments, so let's keep looking, oops, error reporting, is this. So notice in line 513, this php.ini file has the following line, error_reporting equals E_ALL and not E deprecated. So in other words, this is PHP's config line that's saying show me all messages except those related to deprecated functions. That's just the default. They came with this installation but that is why notices are displayed, E_notice, E_warning, E_error, are all separate constants that you can manipulate. And this is beyond the scope of the class for the most part but the single ampersand operator for those familiar, is what operator? Bitwise and-- the tilde is the bitwise not operator in invert bits. And the caret symbol is XOR. If unfamiliar with bitwise operators, realize that there's a whole horizon of computer science and programing ahead of you but for now we won't dwell too much on those details, but it has to do with manipulating low level bits double bits, which is an efficient way of setting flags, so that speak, setting values for configuration. But for now, realize that this is a possible approach but the not the right solution here. Instead, what should we do on line 24 to fix this problem more properly? [ Inaudible Remark ] Yeah. So let's go back isset. So, if it's set then you are logged in, presumably. All right. So, let's take a look now what Home is doing. If authenticated isset in the session superglobal just tell the user you are logged in and to tell them you are not logged in. And what else am I doing? I'm also providing them with a handy little log out link if they are in fact logged in. So let's now go back to the browser just to see this again in context, and indeed the result of this webpage looks like this. You are not logged in and if I look at the source in Chrome, should I see any PHP code? No, better not otherwise something is wrong with my server. Now, as an aside to one of the axis along which we grade projects is this thing of style, how pretty is your code, how well indented, is it variables and so fort. Realize that when we do evaluate style we care about your PHP files, we do not care about the resulting HTLM files, because notice this looks great in my gedit, editor but it looks all misintended here, that's fine, so long it's readable in source version, we don't care what the resulting HTML is. And this is simply because of your indentation in your PHP file that this is getting a little messed up here. So just realize this is not a big deal here and the browser certainly does not care. So, let's look at version 1 of a log in demo, and let's go ahead and try to log in. I'm going to try to log in as jharvard with no password. Log in. OK. So it's not read but we seem to have a very similar mechanism to what we did earlier with registration. Let me try, jharvard, crimson as his password. Log in. That's pretty cool. Even Chrome realizes I logged in. So let me disable this Chrome thing just so we don't capture our passwords. Cancel that. So now, notice, this has changed in. Changed. You are logged in. Now, let's infer from what we saw on home.php, how log-ins work. Suppose jharvard and crimson were indeed my correct username and password, what must the PHP code to which my username and password were submitted, must have done in order for home.php to know that I am now logged in? It must have set the authenticated variable to true or to something. Exactly. So, the login1.php, as we'll soon see, set a variable called authenticated to true or to something and home.php is that now checking the value of that same variable. So, notice we have crosstalk essentially between two files here. We're not doing this on one huge file, so it is possible for different PHP files to intercommunicate so long as they each do one terribly important thing, and that is specifically this here. Notice in home.php, there was a line that I didn't draw our attention to earlier but at the very top, line 12, session_start. If you want to use $_session, you must, must, must call that function. And you must call that function at the very top of your code. You cannot spit out any HTML before calling that function. And the reason will become clear in the bit. It has to do with HTTP headers, and the fact that function actually generates some HTTP headers related to cookies. And just to be super annoying, realize that you can't' even screw up, if you accidentally have white space at the top of your file like that, I just try to Enter key, that will break session and cookies. Why? Again, we'll see in more detail in a moment but that's saying to the PHP interpreter, here's a line of white space, spit it out. But then later, on line 13, your calling session_start which is going to tell PHP, "Send these HTTP headers but you missed your change." Headers must come before all other output including white space, so a very common mistake in PHP is having a leading or trailing white space in the wrong places so get super nit-picky yourself about making sure you don't have those tiny stupid little mistakes at the top and the bottoms of your files, in particular. So, for now, just take on faith that you must call session_start both in home, hp if he's access the superglobal as well as in login1 which is the file that's apparently doing this magic. So, let's take a look at this file. So in login1.php, we start with some comments. I then enabled sessions with session_start. Now, I'm kind of cheating. I don't have a database yet because we haven't gone into that lecture. So for now, I'm just going to define some constants. This is the syntax in PHP for defining constants, by definition, their values cannot change. I use all caps by convention. And now notice I have some code that's kind of borrowed from the Frosh IMs example. If user isset in POST and pass isset in POST, that doesn't mean they're correct but it does mean what? Yeah? That the user actually typed their username and password in the form. Exactly. That the user typed their username and password in the form which is now enough of a starting point for us to check the validity of that username and password. By contrast with Frosh IMs, I kind of had this middleman an action parameter that I just used so that minimally, there was always one parameter that was submitted but in this case of a form with just two values, I don't need that action. I could just check for username and password because that's actually what I care about. There's no optionality here. So if-- here's the magic, if the user key equals-equals USER and the PASS key equals-equals PASS, those are our constants recall, then remember that the user's logged in. How well as Jack proposed, here's the secret line of codes, SESSION authenticated equals true which is not only setting it to true, it is just setting it in the first place, thereby making isset happy later. And I scroll down further, what I'm going to do? I'm going to redirect the user. Now, this is a little more complex than we've seen before. And it's adapted from actually PHP's documentation. There's other ways to do this. But what was stupid about my previous attempts of redirection? Yeah? They went through the entire path. Yeah, they have the entire path. It was hard-coded which means localhost, that's not even a real website like that will only work on my own machine or other people's virtual machines. It's not going to work on the internet and it's not a fun exercise to upload all your files to a server and then have to manually go through and change hard-coded URLs that you should have not hard-coded. So I'm generalizing now. And notice, these few lines of codes achieves the following. I first figured out what host I'm on. It turns out there's another superglobal. We mentioned it briefly on Wednesday, called server. And these have some juicy information like the user browser agents, the user agent string, Mozilla or IE or what not, has their IP address. And it also has the HTTP host that was in the host colon field in the HTTP request that we saw on Monday. So, this is just putting in a variable. It doesn't have to be there but it's nice and clean. And now, what's this? Dirname, what is the directory name of server PHP_SELF? So this is a little trick whereby PHP_SELF is another key in this superglobal that refers to yourself, that's all. The current strip, login1.php. Dirname, when passed that path gives you everything but your file name. So this is a way of figuring out programmatically what directory are you, login1.php in. Rtrim, just trim some white spaces needed reverse trim or rather not white space, it's optional. It's going to trim leading slashes as needed. So that's just a little syntactic trick. And the real interesting part is this last one. Header, location colon HTTP host path home.php. Now where did path come from? The previous line. Host came from the previous, previous line. And home.php is hard-coded because that's where I want to send the user. Now, as an aside, you will often see this in PHP code just redirect to the file. And it does usually work. And my God, that line is so much simpler than the story we just told, with all this other code. This is not technically correct. Technically, when you send location headers, they should be full URLs not relative URLs. So the reason for jumping through these hoops and borrowing this code from the manual is just to make sure that all browsers are happy by the location line that you're sending. So it's-- this is a perfect candidate for a function that you could write in PHP. And generalize these yourselves. So in fact, let me do a quick aside and this is not in the best location here but I'll just do it real fast. Let me do this. Let me say if I wanted to implement a function in PHP, we could do it like this. Function, let's say file, and then let's go down here. Let me paste in this code. And what I'm going to do here is return let's say, http://$host$path/$file. So now notice, I could simplify all of this for instance to-- actually let me go one step further rather than return this. Let me do header, location:exit. So in other words, this is a good candidate for factoring out that kind of functionality. So that up here, I could just say, redirect home.php. And it just simplifies my life so much. And I'll only write it once. So in other words, just like you would in most any other language. Once you find yourself doing something again and again, it's a prime candidate for factoring out to a function. And we'll soon see ways of including one file in another so I can literally have a file called functions.php, which has all of my helper functions. And I could paste what I just wrote down there into another file and then access it with one line of code that I've highlighted in blue there. You need to name your function redirect first. You're right, thanks. Very good point, useless as I wrote it, redirect. Thank you. That's what it has to look like. And many different ways to do this but same principles as you would see in some other language. All right, so let me just roll this effect back so that we're back where we started here. And now, recall that the behavior we saw before was this. So, here's just another approach, to checking whether or not a form was submitted or not. The line below body, if count POST greater than 0 echo INVALID LOGIN. Why am I doing that? We'll think back to the logic we just saw under, what circumstances will the PHP interpreter reach that line of code in this file? Under what circumstances will the interpreter reach this line here? [ Pause ] Yeah? Axel? If it's-- If the username and password was correct? Opposite. Oh, OK. Right? Because we're redirecting when. When correct. When correct. So those if conditions there said if they give us username and password and username is correct and password is correct, then go ahead and remember with authenticated equals true then redirect the user. So by the time we've redirected and called exit, the user is literally gone. They're at home.php. So the only circumstances in which we'll get down here is if they haven't submitted the form yet in which case that first check way up top where we checked is user set and pass set are going to be false so we're going to drop down to this part of the code. And then also, we will get here. If the user did submit the form but they screwed up somehow and username was not equal to username-- user or password was not right either, one or two of those mistakes. So, what am I doing here, if count of POST is greater than zero? So if I'm at this point in the code and there's something in POST, that must mean that the user submitted the form with a username and/or password. And it must mean that they weren't correct because otherwise, I would have exited earlier. So this is just another technique. Again, you can implement this kind of logic in any number of ways. This time I choose to do the count approach. And that's OK because even if there's nothing in it, POST will still be in array, a big associate of array that might contain keys but might not depending on what the user did. Now, here's another refinement. In my form line there, action equals PHP_SELF, it's also been a little short-sided of me to hard-code the name of my destinations into my HTML. Why? Why is it been arguably bad practice to say action equals "froshims4".php and so forth? Only if you want to rename the PHP file, you have to change it. Exactly. If you have to rename-- if you decide to reorganize your file system in your folders and what not, and you rename files, now your code is broken until you also open up your file and change the file names inside. So in the interest of, frankly, making your life easier long-term, hard-coding file names and paths and URLs and code, bad idea. You should minimally factor it out to like constants or variables that are used as configurations throughout your files, or just don't do it at all and figured out dynamically with for instance certain server variables and things like the server-- superglobal. All right, so that's pretty neat. So let's take this one step further to. Let me open up version 2 of this, login2.php. And what we did not do last time? What we didn't do for any repopulation so is this right or wrong? It feels like I've still made a little mistake here. Again, be super proper. Yeah? It doesn't check if user existed. Exactly. I made the same newbie mistake as before. I didn't check if that variable was set. So I have a couple of options. So I have a couple of options. I could put an at sign in front of the POST variable. I can do an isset in front of the-- I have to get rid of the-- well, I can do an if condition in there. I can do the check outside the scope of that HTML variable. The same story we told earlier in the context of Frosh IMs, same issue here. So beware, that kind of thing, otherwise we're going to trigger a notice. All right, but I think we can still clean this up a little bit more. And let me go ahead and open up not version 2 but version 3. And in this case here, notice that I'm setting one other thing. And now we get to have a slightly more technical discussion. What else is in here? What's new? Anyone else, this time? OK, soft ball question. What line of code is new? Yeah? Setcookie. OK, so setcookie. We haven't seen that before. And we have this line here that's saying setcookie and then a whole bunch of arguments. So, the comment kind of spoils the answer here. So save username and cookie for a week. Well, what's the point of this? Well, it's kind of nice in websites whereby even if you're logged out because you've waited too many days to return to the site or it just doesn't remember that you're logged in for very long. It's kind of nice if I don't have to type my username the next time but I do still have to type my password. Now thus far, we have pre-filled our forms by using what's in POST. Now obviously, if I visit a website for the first time today and I've not submitted a form, there's nothing in POST. But if you still want to remember the user, you might have the forethought to store on their computer, a cookie. And a cookie is just a little file stored in RAM or on the user's hard drive that can store key value pairs, maybe their name, maybe their email address, or really maybe just a big random numbers, generally best practice. So, in this case, I'm literally storing a key called user. And what's the value of that key apparently? Yeah? Well, it's whatever the user has posted as user. Whatever the user has posted as their username. So-- And then this, time returns the current time in seconds from January 1st, 1970, times 7 times 24 times 60 times 60. Why all that math? Well, we needed to be in seconds. So we go 7 days times 24 hours times 60 minutes times 60 seconds. And that gives us the appropriate third argument, to setcookie which means make this cookie live for a week in terms of the number of seconds that are appropriate there. The rest of this file is identical to before. So it's kind interesting now to see the cookies. So let's see if this thing actually works. Let me go to login3. And here we have-- oops, what did I do here? On the front user and up-- now I see what I did. Line 53, let's fix this real fast. Isset user. Down here, isset POST to user. Cheating. All right, quick fix. Do as I say not as I do. So, here we have our same form. So let's do jharvard. Lets' do crimson. Log in. OK, that's pretty cool. And now let me go back to version 3. Oh, that's convenient. So again, just because I've visited this page, I've not submitted a form. But I'd still somehow has pre-populated the username field with jharvard, so that must have come from a cookie. So let's actually see how this is working underneath the hood. So let me go ahead and first, clear all of my-- oops, let me go ahead here and clear all of my cookies. So let's see settings, history. Clear all the history, just so we have get rid of all the cookies involved. And now let me go ahead and open a new Chrome. Oops, let me open a new Chrome window. [ Pause ] Here we go. Let me open a new Chrome window here. And let me first open up the developer toolbar at the bottom and let me look at the network tab. And now I'm going to paste in this URL. So here we go. Enter. And notice that I've visited this page. Let's quickly look at the headers that just came across the wire. So, response headers, what has been sent from the server that we haven't really seen before? At least we didn't see last week. Response headers are down here. What's looks new to us today? And what's probably relevant? Axel? It could be setcookie session ID. Yeah, so that's interesting. Setcookie with PHPSESSID. There's this stupid line, X-Powered-By. So all these various web frameworks tend to tell the whole world what you're running. It's not the best practice because one, it's-- you're telling the world you use PHP and specifically, you're telling them to use php5.3.13. Why is this bad? Think paranoid. Jack? It would say there's a problem with 5.3.13 that specifically for bug 5.3.13, someone could come by and find websites that are running back version and break it. Exactly. Right, this is a newbie mistake whereby if you leave this information on, you are telling the whole world, not only what language you're using but what version you're using. And as Jack says, if there is a bug discovered in php5.3.13, you just told the whole world, I am vulnerable. And you've told anyone who's ever visited your site that. So as an aside and we leave this on to be clear for exactly that purpose. So we can have the conversation and it is a virtual machine. It's not only internet so it's not a big deal in this context. But let me go ahead and open that file again, php.ini. And let me search for the word expose. And the fact that that happens is all because of this silly line here, expose php=on, all you have to do is turn it to off and then restart the web server. So let's actually do that. Let me change this to off and then save it. Now it's not enough to reload the browser, I actually have to go back here to the-- I have to go back here to my window and say service httpd restart. So, service httpd restart. We'll literally do just that. It will restart the web server. It might take a second or so. And there it says OK. Now, let's go back over here. Let me go ahead and reload the page. And now, we have this here, response headers, notice what is now gone. Any mention of PHP. Now, there's still another problem. We're still telling the world what? Apache. Apache. So where are we going to fix that? In httpd.conf. It's not called expose there. It's a different variable but the same idea. So, may be good for development so you remember-- you know easily what versions you're running. But frankly, this is mostly marketing. And it's for the worst of everyone's security all around. All right. So, what is noticeably absent here is there's no setcookie this time. But there is if you look up higher. What header being sent from the browser to the server? Jack? There is already a cookie. Yeah. So there's cookie and I wager, I didn't pay too close last time but I'd wager that the value of PHPSESSID is the same as was in the setcookie header earlier. And this is indeed how cookies work. So how do you implement state in HTTP which itself is a stateless protocol? And by stateless, I mean, essentially this, you go to-- open a browser. And most of the browser these days have come some kind of spinning icon whenever you visit a webpage, whether it's a globe or a circle or some kind of progress bar even on mobile devices. But then as soon as the webpage stops loading and is done, that little spinning or whatever it is stops too. And the implication is that your network connection most likely has been closed, in other words, you are no longer using any internet traffic to and from that web server once the spinning has stopped. Now, that's a bit of an oversimplification, Gmail, Google Calendar, Facebook, and Twitter and all these websites that use AJAX could very well keep to be talking behind the scenes. But for normal websites that's not so fancy, the connection is closed. Now again, how do you remember that the user has logged in? Well, you have to tell them-- you have to stamp their hand so that earlier when we saw the setcookie header and it said setcookie PHPSESSID equals c5ujm8 whatever, that was like the guy at the carnival or the club or whatever, stamping your hand with a big random number. Now, the server meanwhile stores that same big random number somewhere in the database, in a file. But it somehow remembers that it has allocated a user out there, that big random number. Because you are a browser and you implement HTTP version 1.1, you have agreed by nature of agreeing to this protocol, to show that hand stamp every time you come back. So we talked on Monday about the simple idea of a protocol two humans meet each other, hello, how are you, you shake hands, totally human convention. Same idea with HTTP. When you have been set a cookie, you should then show cookie, cookie, cookie every time you go back to visit that same domain name. And that's exactly what Chrome has done here for me. So why is that relevant? Well, now, think about what the server is doing. It turns out in PHP what the server typically does is this. Let me go back to my terminal window. Let me go into a directory called temp. And notice that there's a couple files here on white. Do any of these look familiar? The top one. Yeah, the top one. You know, I didn't memorize the whole thing but I remember c5ujm8 whatever. That is a simple little file called SESS_ and then PHPSESSID. It's the same exact value is on the browser. So it's turns up by the default, PHP, to remember the contents of your session superglobal, simple stores them in this silly little file on disk. And every time, you, the programmer, add something to $_SESSION, it gets saved to disk there, so that the next time the user visits your web page and they show their hand stamp, by sending the cookie header, PHP on the server quickly opens that file in the temporary directory. Grabs all the key value pairs inside of it, puts them in the superglobal called session, and then gives you the developer access to those very same values. This is known, generally, as serialization. You're taking some in memory, key value pairs and serializing them to disk, which is a little expensive to go back and forth to disk, which tends to be a slow mechanism but it ensures that you will have access to those same values again and again and again. So let's see what actually gets stored. Let me go back to Chrome and let me actually log in as before jharvard crimson. Log in. And now, let's notice when I went to login3 here, what else was set? So notice at the top, request headers. Notice I set my hands stamp. I sent it, because I visited the domain again. Here's the form data, jharvard crimson. That's just the POST. And now down here is the response headers. Looks what's new this time. Jack? There's a setcookie. Yeah, another setcookie. This one is named user value which is jharvard. And when does it expire? Looks like about a week from now. So that's exactly what we send to the server. Now, the convention is not to send a big number of time stamp, it actually sends a date formatted in this fashion but we didn't have to do the math and figure all of that out. So now it's set this cookie, so that means subsequently not only will the server give me the program or access to the session superglobal. What was the other superglobal we knew was coming that's related to this stuff now? Not session, not get, not post, but cookie is yet another superglobal that contains all of the cookies that you have said. It doesn't contain PHPSESSID-- actually, maybe it does. It might also contain that but it also contains all of the cookies that you have set manually with a function called setcookie. So now what would be kind of interesting? What about that temporary file? Let me go over here to my terminal window. Let me copy the name because I'll never remember the whole thing. Let me do gedit which is my text editor. Paste that in. Enter. And this is what PHP stored on disk. And in this case, notice that-- what's in there? It's not really the cookie values, it's not jharvard because that was sent to the client. I stored authenticated true in my session object so this is how you apparently, serialize a Boolean value in PHP. Now normally you-- we humans would not look at this file. This is kind of implementation detail that only PHP should care about, but you can infer from this that apparently you serialize a Boolean by writing its name, a vertical bar, what is B probably mean? Boolean Boolean, colon, and then the value is 1 and then semicolon means that's the end of this value. If we had more values, they would just be appended again, and again, and again. So that's all that's going on here. And it's turns out you can move this to from disk to a database if you want. But, generally, sessions are implemented in exactly, that way. Any question on sessions or how that particular feature was achieved? [ Inaudible Remark ] Good question. Where is the information, jharvard and crimson stored? It is not stored in the session at all. All that the login file storing in session is what? Just this Boolean value, authenticated. So in this model, we have forgotten who has logged in but we have to remember that someone has logged in. So what is stored in the session? Only authenticated equals true, that's it. We could store jharvard's name. And in fact, why don't we do a little tweak here, just to make this more clear. So in login3 in my setcookie line, I'm going to go ahead and do-- near my setcookie line, I'm going to do this, SESSION user=$_POST"user". So let's add this line here. And then let me also open home.php and get really fancy and say You are logged,htmlspecialchars-- just for good measure, I don't want to do post here because it's not coming from there, it's going to come from session, user close quote, exclamation point. So now let's re-login. Let me go back here. Let me close this. Log out. Log in to version 3, jharvard crimson. And just to be clear, when I hit log in, it's going to be submitted to login3.php. What two session variable are about to be set when I hit Submit? Authenticated and user. Good. Authenticated and user. And those should be set to true and jharvard respectively. Log in. Nice. So notice now I have remembered more. So if I go back this text file on disk and notice what is looks like now, now we have two values. Starting to look a little more cryptic because this is not Boolean. But notice after the semicolon now, is user vertical bar S, which fully stands for string:8 which is the length of "jharvard". So that's what's now stored there. So, again, session is server side, cookie client side. So, why remember server side that the user's logged in? In this way, well, you want the server to be dictating whether or not a user can see a flat page like home.php. So, now, there is a security implication here. And we'll spend more time on time on this later in the semester, but the fact that cookies underlie my sessions, has kind of some non-trivial security implications that we talked about very briefly last week. What could a bad guy do with this cookie's potentially, yeah? They're sent forward and backwards [inaudible] server so if anybody would intercept that traffic, they would be able to-- they would be able to get to be on their computer and [inaudible] the same session. Exactly. These cookies as we've just seen, we sniffed my own traffic with Chromes' little developer toolbar, and we see that setcookie is sent in the clear, cookie is sent in the clear. And so that really is like walking back into a club or an amusement park just holding your hand stamp for the whole world to see and it all takes is someone to look over and write down whatever unique number is on your hand for him or her to then stamp their own hands and walk to the door as well as you. So, the fundamental problem here with sessions is that the server is remembering that the client is logged in, just by trusting the client to pass that same big random number. Now, odds are if I'm the bad guy, the odds that I'm going to guess a number like c5ugm8vk97, I mean, is very, very unlikely that I, the bad guy, going to guess what your sessions ID is. But my God, I can just sniff it by using my wireless laptop and special software to sniff all the bits that are flowing around the air right here on this room or Starbucks or in an airport. So, this is very dangerous. So what's the potential solution here, to this fundamental treat? Yeah? [ Inaudible Remark ] So, HTTPS. We talked briefly about that last week but HTTPS encrypts your request as well as the HTTP headers. And that alone is a huge leap forward. So we could still, just to be clear, even if we using HTTPS, we, the developer or the user, we could use Chrome and still sniff our own traffic but no one else between point A and B could do that because HTTPS would be involved. Now, even so, there are some attacks, you can wages on SSL of HTTPS. If you were curios, recall that on the lecture's page from last Wednesday. I did post a deck of slides from a fellow who give a presentation at the conference a couple years ago. It's actually quite fascinating to read and will completely make you distrust in the entire infrastructure that we have here on the internet but it's also very technically interesting as well. All right, any questions? All right, let's look at one last log in the example here. Version 4. Let me fix that real fast. We're using our same technique, but I won't bother boring you by asking again and again how we got it. All right. So, version 4, looks the same here. Login4, where is it? Well, actually, let's just look at the code here because there is-- this is a program we don't want to remember because it is actually quite bad. Here's another way of remembering that a user has logged in. Find fault with this fast. Let me reveal a little more on the screen. First of all, where am I checking user mane and password this time? Yes. From the cookie. From the cookie. OK, instead of from POST. And this is nice, right? This feels like a convenient. I come back to your website after a day or two of not being there. My cookies are valid for seven days. So how do I check that I've logged in again-- that I've already logged in? Well, we just store the username and password in cookies, called the user and pass, and then I'll have access to them server side in the cookie superglobal. But this is bad. Why? Yeah, Isaac. It's stored on your computer, so anyone-- But it's my computer. Who cares that my username and password are stored in my cookie on my computer? Someone gets to your computer, they can [inaudible] into whatever they want. Exactly. So it's-- actually, it's as simple as that. I mean, if your machine is compromised because you have noisy sibling or a roommate or whatnot and they just have to go poking around the files on your computer, because cookies are for-- when they're persistent for multiple days, they don't get stored in RAM, actually gets stored in disk, some file, some on your hard drive and it depends on what browser you're using, where it is, but it is somewhere on your home directory, somewhere buried in some seemingly innocuous directory, but there could be a lot of juicy stuff in there among which might now be your username and password. And what else here is a little worrisome? Anything else? Yeah. [ Inaudible Remark ] Exactly. If you're not doing over SSL, you're just reminding the whole world what your password were. It's bad enough if you sent it via post without any encryption. Now, you're sending it also via cookie. And there's another slightly more arcane attack. Recall last week when I did that cross-site scripting attack, which was a fancy way of saying I typed a script tag into-- Someone can edit their own username and password and you haven't changed something inside the website. Good thought. Someone can change their own username and password and have it edit something in the website, not necessarily. Because the server still knows what the correct username and password is, so I can't just change my username, unless I also change my password to be like Jack's username and password. But for that, I'd need to know your password. Now, again, I could sniff the traffic, but that's not a threat scenario here, it seems. This one's-- oh, yeah. Seven day expiration of the password isn't good. Oh, so the expiration of the password is here seven days, why is that not good? What happens when people change password-- OK. Good. So, if I change my password, I've got to remember now to reset this cookie because, although, it's going to be sending the wrong cookie and I'm going to be sort of blocked out for those six or seven days. So there, too, that suggests, "That's not stored in the cookie at all." And this one, we'll come back to toward the end of the semester when we focus one day on security. But recall last week that I did that silly little attack on myself, whereby I typed in a script tag into a form field, and then triggered "Hi" to appear on the screen, because I tricked my browser into rendering HTML that the user had provided. For now, let me say that that was a stupid demo because all I'm doing is like breaking the site for myself, but it's representative of the class of attacks that could put your username and password at risk. For now, consider this, you know that forms can be submitted via GET or POST. If they're submitted via GET, that's equivalent to putting the parameters in the URL. OK. So, now, we have a URL. And supposed that you are a spammer and you sent someone a spam, like some kind of a fishing attack that says, "Click here to confirm your PayPal account," something stupid like that, and you embed in that email spam that URL for the user to click. A bad guy, again we'll come back to this later in the semester, could trick you into clicking on that link that contains HTTP keys and values, parameters. Now, what if one of those values were an open bracket script tag and so forth, much like I manually typed in. I, the spammer, could trick you into not only visiting foo.com but also submitting form via GET on foo.com, and one of your inputs that you've been tricked into submitting could be a script tag. Inside of a script tag, you have access to all of the cookies in a website via JavaScript. There is indeed a global variable, kind of over simplification called document.cookie. So long story short, if you, the bad guy, can trick a user into effectively submitting a form that contains a script tag and that script tag contains some mention of cookies, you can trick a user into revealing all of their cookies to you, the bad guy. And if among the cookies is something, my God, like their password, you can steal their password with now even sniffing their wireless traffic. You can be halfway around the world having just sent them a fishing attack. Again, more on that in a few weeks. But for now, the takeaway is there are so many reasons not to do this, just don't do it. There is never a good reason to do this. And it's clearly not necessary because in the previous examples, we stored everything in session. And even then, I didn't store my username and password. I just stored authenticated equals true. I don't even need to store sensitive information. The only risk I still run relates to someone stealing my cookie, my php/id. But thankfully, encryption helps raised the bar to that attack significantly. All right. Any questions? Yeah. [ Inaudible Remark ] Yes. So is there any difference in storing variables in sessions and cookies? It boils down to session is stored on the server, cookies are stored on the client. So, you can store anything you want on the server and be reasonably comfortable that it's safe, although there are attacks that can be waged there. You should not store anything that's sensitive on the client in the cookie. Rather, it's reasonably for me to store jharvard because, frankly, it's kind of convenient to be able to pre-populate that field by saying jharvard. I should not store his password. And arguably even jharvard is not great. Because that means, if someone's in, like a computer lab on campus, they log in to my website, then they walk away, I've leaked some information, the fact that jharvard was the last using this computer even if you can't log in to his account without his password. So, it might just be a privacy thing. So this is why, and recall where we started the story, this is why many websites actually have a little field, like this here, that asks you to remember that you're logged in, and there's two versions of this generally, one, like Facebook, it actually keeps you logged in by setting the equivalent of authenticated equals true. Bank websites, though, typically and others will not remember that you are logged in, but they will, for convenience, remember what your user ID is, your username, just for convenience. But that's really a server side detail that they have decided to support or not support. And then, in the bank's case, the stakes are higher if someone logs in to your account, so that's why they make you type your password again and again. Facebook, nah, it's not nearly that sensitive as money. Yeah. Just a curious question. For underscore session, you just authenticated, you just mentioned authenticated. With that-- with the information, can we able to find out the user ID and password? In the cookie? Yeah. In the previous example? Yeah. So, yes. In the previous example, where I stored username and password in cookies? No. Oh. So, because then you didn't store the user ID and password, but you just mentioned like authenticated, just authenticated. OK. Will that cookie information can, I mean, the hacker can able to find out the-- Good question. And don't call cookie information here, it's more session information. In that case, no, because I have genericized remembering that the users logged in by just storing authenticated equals true. The bad guy probably cannot figure out who it is, in that case. They only know that someone has logged in. Now, that's not a common case. I did that for the sake of a simple demonstration. The version I did on the fly by also storing in session jharvard, so that we can then see it in that text file, that's probably a better version. But at that point, to be honest, if we are implementing something like Facebook, frankly, there's probably so much personal information going back and forth if you're not using SSL like you might say, David Malan, your profile, it might say, "Dear David," in the email I'm viewing. There are so many other ways the bad guy could infer your identity, your independent of cookies and sessions. Jack. So what exactly does the keep me logged in check box do? Good question. What that does is it stores on the server a remembrance that the person with php/id55512 whatever the big random number is, should not be asked for their password again. So, in other words, they effectively have something like this. Let me open up my text file and let me go back into login3. So, recall that we keep checking this, if user and pass are issets. What Facebook probably does is if isset session, remember me, or something like that, or the form is submitted, something like that, this would-- actually, sorry. Let's-- I put that in the wrong place. Let's do it like this, up top. So, if isset remember me, then I'm going to do the redirect to home.php. In other words, it's a separate check all together. If a cookie has been set, that represents the act of having clicked on that check box, the users are going to be automatically routed to home.php and Facebook knows that you're logged in because, also, in session is probably your user ID or your username, something like that. So, it's really as simple as that. And how does that mechanism work? Well, we keep seeing it, but I didn't explain precisely. PHP/id is the result of having called the function at the top of one of your-- of all of your files. What was that function that I made you promised to call? Yeah. Start underscore session? Close, session star, session_start. Remember that I said take on faith. You must call this first. What is that doing? It is what's handling for you, the act of sending the cookie called php/id to the browser, so that you have this illusion of statefulness between clients and server. Is there an opposite, like, end session? There is, session_destroy. It will kill the session altogether and there's actually a couple other functions you can call. And if you pull up the php.net documentation for session_destroy, they'll show you some common heuristics for blowing away everything in the session but session-- And that leads for some sort of log out? Exactly. That's exactly-- well, you can use that for the log out or, frankly, we could just go back and set authenticated to false but that quite-- won't quite work because false is also set, so if we do that, then we have to be careful about our use of isset and actually check truth values. Yeah. What if the bad guy get my cookies ID and if we can't hack his computer, [inaudible] that cookie with my cookie ID and just to saying that authentication equals true? Good question. So a bad guy could forge your cookie by guessing it or just sniffing it. He cannot change authenticated is true because that is stored on the server. So, the bad guy's best chance here is to guess or to sniff somehow the session-- php/id of someone who has already logged in and then send that cookie as his own, and this is exactly what's called a session hijacking attack and we'll come back to that, too, towards semester's end. OK. Let's go ahead and take a two-minute break here and then we'll come back, take a look at this cleaner approach to some of the code we've been talking about known as MVC. And then after that, we'll segue if you'd like into section as well. So let's take a couple minute break here. OK. So we are back and the goal now is to try to improve the quality of the design of our code and move away from having these individual files that have frankly a lot of code duplication, right? We have a lot of the session_start at the top of multiple files, which I just said you must do. But it would kind of be nice if we could factor that out and do it maybe one place and have everyone else do what that file says to do. It feels like I've got HTML tags all over the place. I've got body tags, head tags, there's such a lot of code duplication right now, and it feels like this process is just going to get messier and messier, the more complex your site gets. So indeed, let's introduce another paradigm altogether known as MVC, Model View Controller and we're only going to scratch to the surface of this tonight but we're going to take a step toward making things a little cleaner. This will be a very underwhelming drawing but it at least will give you a mental model here. So MVC is Model View Controller and the idea behind MVC is essentially this, whereby and this is where I get to kind of cheat and do some ASCII art. OK. That's all I wanted the iPad for, to draw this picture here. So MVC kind of has this triangular relationship among these three concepts known as model, view, and controller. So controller is actually a nice one to start with. So the controller does exactly that. A controller is the code that you write that really controls the flow of your entire application. Now thus far, we haven't really had a controller per se. We've had many controllers. Froshims1.php was a controller. Froshims2 was a controller. Register1 that was-- register1.php was a controller. Register2 was. In other words, all of these files we've written thus far are entirely self-contained and self-sufficient. They have their HTML tags that they need. They call session_start as needed. They have all the PHP logic at the top. Every-- they do everything. There is no sharing of code. Now, MVC, though, proposes that you keep your business logic, so to speak, the real intellectually-- some of the intellectually interesting parts of your application in your controller but you relegate all of the aesthetic stuff to things called views, separate files that contain your HTML. And in particular, it doesn't contain just static HTML. It usually contains placeholders for variables. So for instance, one of the things we copied and pasted ad nauseam today was the head tag and the title tag for all of our various web pages whether it was in register1 or register2 or froshims1, froshims2. It was all over the place, head tags, title tags, all of that again and again and again. Now, even though the title of my pages might have changed because I might be changing it everywhere. Wouldn't it be nice if I could just write open bracket head, open bracket title and then let's say dollar sign title and then close title close head in one file and then somehow dynamically change the value of dollar sign title when I spit out that HTML. In other words, can I factor out my HTML from my various PHP files. MVC is a mental paradigm that sort of urges you to do that and model which we won't talk so much about today but perhaps more in our database discussion is where you store your actual data. Now thus far, we don't have all that much data. The only data we really had today was like a user name and password, like jharvard and crimson. But once we need more sophisticated pieces of data, we can talk about the M in MVC. But for now, let's consider C and V and let's take a look at a simple demonstration. So let me go back into the appliance here and this is the website that I want to build. It's ever so complex. It's got a huge H1 tag or whatnot and a link to lectures and a link to the syllabus for the course. If I click on Lectures, I see this. If I click on Lecture 0, I see this. So what's the point of this? Well, one, it's super simple just so we don't get distracted by unnecessary details. But it's also super simple to send a message that there's redundancy, redundancy, redundancy, like every single page fundamentally looks the same. It's got a title and it's got unordered list. And even though the content changes, the fundamental markup that I've written, the HTML, it doesn't feel like it's changing all that much, just the data. So this feels like an opportunity to factor this out. But let's see my first attempt at this. Version 0 looks like this. So I have these several files on my directory, index.php, lectures.php, lecture0.php, and so forth, and they're practically copy paste of each other. Oops, let me open this in gedit index.php, looks like this. It's just HTML. It's called .php but recall from last Wednesday that just because you call it PHP it doesn't mean it is PHP. It's just it can be spit out raw HTML. So here, I've hard coded some of these tags here for HTML and there are those links I mentioned, lectures and syllabus. Now you can probably guess what lectures looks like. If I open that up here, I have now in MVC, in like number 0, let's pull up lectures. Oh my God, it's not interesting. It's pretty much copy paste as before. And you spoil lecture0, lecture 1, pretty much identical. So there's really an opportunity now to do some factoring out. What kinds of things can we factor out? Well, one, the title tags are the same, but the word inside of the title tag is different. So, I would love to be able to do something like this or equivalent, and it's not quite as simple as that. It might be more like this. But that could be a step in the right direction and that would be a value add of a dynamic language like PHP. This, I would like to change, too. And even these links, it would be nice if I had a for loop or something that put these kinds of things out. So there's a lot of opportunities to factor out, otherwise redundant code. So let's take a look at version 1 and see how we can start taking steps toward that. So that was version 0, let me go back now to version 1 and in version 1, we have the following structure. So in each of these sample folders and I'll have this online as well. There's a little read me, just to remind you how we laid things out. So in this read me, notice we have the following. It improves upon version 0 by factoring out pages' header and footer, so very low-hanging fruit here. Same head tag, same title tag, same stupid open bracket slash HTML tag everywhere plus open bracket slash body. We can factor this stuff out. So notice that the only difference now in this version 1 is we have the same four files as before, by name at least, and then footer.php and header.php. So let's now take a look at this design. I'm going to go into the one subdirectory and open up, let's say, index.php. Interesting. And you can kind of infer what I've done from this perhaps. This does not look like a valid web page anymore, but what must the implication be? So what does require probably do in PHP? It's a new function. It pulls up some of the PHP from another file. Exactly. It pulls in a PHP code from another file, in this case, header.php and it does the same at the bottom of the page and it does it in those locations. So where is my body tag probably? Yeah. In the header? Exactly. And the close body tag is probably in the footer. So now let's take a look at header.php. So in header.php, OK, there is a slightly familiar file, even though it's a little abbreviated. Notice that it's stops in line 20 once I say CSCI S-75, that's it. But that's OK because what's supposed to come next? The-- yeah. The list. The list of links, in this case, and there's no close tag, but that's OK because the close tag is in? The footer. The footer.php has close body and close HTML. So, it's not going to be very interesting, but let's just, for thoroughness, so that there's no magic, open up the footer.php, there is that file. I mean, my God, it's mostly common to not even code. So that's a step in the right direction. And let's look at lectures.php. This, too, is similarly simple, mostly comments this time, but require header, require footer. So this is nice. Now I've eliminated a lot of redundant code. If I decide tomorrow I want to change all the CSS for my site, I can just change the link element in the header tag or add a link element for a CSS file. I can add JavaScript code in one place. So this is a step toward separating aesthetics from our actual data that we want to display. It's not quite MVC yet but it's at least a step toward a cleaner design. Well let's take a one step further. Let me go into version 2 now, oops, version 2 has the following files. Wrapping header and footer with a parameterized function. OK. It sounds a little fancy. Can you infer from this description alone what's the next enhancement I'm about to propose do you think? Yeah? Axel? Again, this is just a guess but maybe you're-- maybe parameterized function means that you're changing some tags, for example the title-- Good. -- in the header. Yeah. Remember, I was kind of motivated to do this to like factor out the title but it still allow a custom title, but whereas I kind of cheated before. If you look closely, I had the same title for every page. Why? Because it was the same header.php. So it feels like one step forward and sort of another step back in that sense. But let's look at the code here for header, well, let's look at index first. OK. So index, this is interesting, slightly new syntax to absorb here but it's not all that fancy. So let's look at the footer first. Apparently, I have written a function called renderFooter. What does it do? Probably spits out the footer. Now that's pretty simple. RenderHeader looks a little more complex. What kind of argument does renderHeader apparently take even though it's a slightly new syntax? It's an array. It's an associative array which means it has keys and values. What is the syntax and php for allocating your own associative array? Well previously, we saw a dorms array which was numerically indexed. Now we're seeing an associative array that I have made myself and it works as follows. You write the array function name, open parenthesis and then you have the key, in this case, "title", and then this crazy syntax equal sign arrow and then the value of that key and then close parenthesis, close parenthesis. So that gives me something similarly structured to GET and POST and SESSION and COOKIE, all those superglobals which were also associative arrays. But this one is mine. I just made it on the fly. I didn't even give it a name but that's fine. I'm dynamically creating an array and passing it in as an argument to renderHeader. Why? Well, renderHeader as you can infer from the name is probably supposed to render the page's header and it probably takes one or more inputs. One of which is clearly title but the fact that I'm using an array allows me what future functionality? Yeah? Well, you can store all the things you wanted and you put the renderHeader in the same array? Exactly. I can store all the things I want to pass through renderHeader in the same array. It is a very common paradigm in Perl, with hashes, JavaScript objects. It would be a little short-sided of me to instead have a function called renderHeader that takes for instance as its first argument the title that you want to render because what about if tomorrow I decide like Axel proposes, I don't just want a title, I want like a JavaScript file to be included. So OK, my second argument is going to be the name of a JavaScript file. But then on Friday, I decide I want to support CSS too. So OK, I go back and change renderHeader and you give it a third argument which is a CSS file. But then next week, I realized I want C, this just gets very, very messy quickly. So by having an array from the outset, it doesn't matter what the order of your arguments are. Your only argument is in array, an associative array and you can put any key value pairs in there that you want and the order doesn't matter. In other words, if I wanted another one, I put a comma after the 75 and the close quote and I just do the same thing again with the arrow notation, and order does not matter. So this is a wonderfully common paradigm in both PHP and, as we'll see, JavaScript. Now at the top of my page, there is one price I need to pay. Why do I also apparently have this at the top? Yeah? The renderHeader and renderFooter must exist in helpers.php. Exactly, renderHeader and renderFooter must exist somewhere because they don't come with PHP, it turns out. So they must be in a file apparently that I called helpers.php. So I at least have to do that. Now, as an aside, there's ways of eliminating that copy paste because you might now hopefully be thinking, "Oh my God, now, I have to copy paste this and everyone of my PHP files." And you do for now. But it's at least better than all the other stuff you use to have to copy and paste in every file. So let's now look at helpers.php and see how it works. In helpers.php, we have this function here and this is a little fancy but it's kind of a nice clean way of doing this. So let's look at renderHeader first. RenderHeader takes an argument called data. And what does the equal sign array probably mean here even if you're new to PHP? It probably tells you that data is an array. Good and it tells you a little more than that. It tells you more than just that it is an array. How about renderFooter? Let's infer from renderFooter. What's interesting about renderFooter? It's identical in its signature, in its arguments. But how did I call renderFooter? Did I pass anything in? I didn't. So the fact that there's this equal sign in the declaration of the function, it means that data is optional. And if the user does not provide an argument, the value of data will be in empty array. So this is a slightly clever way of ensuring that if the user doesn't give me anything, I at least have an empty array. Why? I just then can avoid having endif condition later on to check if this is an array or is it not an array. Now, the extract function is the fancy feature here of PHP. Extract takes an associative array of key value pairs. And what it does for each key in that associative array, it creates a new local variable. So the facts that we pass in title arrow CSCI S-75, that will create a variable called title whose value is CSCI S-75. Now who cares? Well notice the next that I called, require footer.php or this one they'll be more interesting, require header.php. So at this point in the story, I have a variable called $title. Why? Because that is what the extract function does. Now if I look inside of header.php, this is where things get interesting finally. Notice what I did here. I have the top of my HTML and you were probably expecting that because it is the renderHeader function. But now, I have direct access to $title because I extracted it from the array that was passed in. So what have I really just done? This is sort of a homemade templating engine. So there's this notion in web programming of having templates where a template typically has a lot of static content like HTML, CSS, JavaScript and whatnot and then placeholders for values that you want to plug in. Now, that's exactly what I've done. My placeholder here is $title but again, I sort of was paying attention to my advice earlier and I'm using htmlspecialchars just so that the user even if it's me doesn't accidentally pass in some dangerous characters. My template is always going to escape the content here and here. And now, I have this very generic way of rendering the title of the page and the header of the page while still parameterizing in such a way that may page is going to have all distinct titles based on the argument I pass into renderHeader. Now, renderFooter, I'll open footer.php. It's a little disappointing because it still looks just like this but just for good measure, I still gave it the same signature. Just so that in the future, I can take arguments if I want for whatever reason. For instance, Google Analytics, if you're familiar is JavaScript code that generally belongs at the bottom of the file. And you might want to pass in a unique identifier for your Google Analytics account. You can think of a bunch of different reasons where your footers might want variable as well. So I just built out with that in mind even though I'm not using any of them here. So what's the key takeaway? What problems have we solved by introducing renderHeader and renderFooter just to be clear versus the previous version of my website? Yeah? We haven't really solved any problems but we've reflect the, what's the word, we made the website more effective by actually not typing all the HTML we need multiple times. OK. So we're no longer duplicating codes, so then frankly that's a problem solved because in the previous model, even though, we only have a web pages, if I wanted to change the aesthetics of my website, I'd have to go into every one of those files. If I want to change the structure, I have to go into every one of those files. You know, it's not a huge problem but it's arguably a poor design. So it's a problem waiting to be solved. And at least, we've done that. And we've given ourselves the flexibility to not have to sacrifice customization because we have this parameterization of renderHeader and renderFooter that lets us pass in arbitrary values for things like title and whatnot. And we've gone to the security links of at least escaping that input so that now that we've kind of hidden those details from the developer, myself included, at least I'm not going to forget and screw up and accidentally embed something that's a little dangerous. So let's take things a little further. In version 3 here and notice here, I'm going to readily generalize these templates. So let's see what this means. Let me go into header.php this time. And take a look here, actually that's OK. And let me open this one. So, helpers.php has now changed. So what have I apparently done? This is version 3. That was version 2 before. Version 2 has renderHeader, renderFooter. And what was interesting there was I kind of realized this was kind of stupid. I pretty much copied and pasted the same function, gave it two different names, and I just hard coded header.php in one and footer.php in the other. But what about-- let's take this to the next level. And again, this is a more sophisticated design. For the first project, realize, will walk you through different approaches here. But notice now I have a more generic render function that takes two arguments. One is the name of the template I want to use, "header" or "footer" for instance. And the second is apparently what? The key value pairs that you want to provide to that template. In other words, in the previous version, recall that renderHeader required header.php and renderFooter required footer.php. This just-- It feels like, oh my God, I could combine those and just change the word header and footer to a variable, a parameter instead and that's exactly what I've done here. And I've added a little bit of sanity checking. One, I first determine the path. So path is going to equal template .php. So what is this? Well, I just felt it would be silly to have to pass in the name of a template as "header.php", "footer.php". It just feels instinctively that my code will look cleaner. If I instead say "renderHeader" or "renderFooter", but I still need the file extension when I load the template. So that's all I'm doing here. I'm concatenating on to the name of my template .php, so that I can then check, wait a minute, does that file exist, in case I screwed up and made a typo, and only if it does extract the variables and require that template. So let's take a look then at what index.php looks like this time. It's almost the same but it's a little cleaner. Now notice I have this generic render function and I just pass in as the first argument now the name of the template that I want to render. And those templates now are identical. All I've done here is improved the design of my helpers functions. Any questions? All right. We're almost there. Let's take a look at just one or two others here. How about number four? OK. So this is going to be a little underwhelming but at least it's another step toward cleanliness. We can infer this actually from the read me alone. What have I done here? You know, I realized that header.php and footer.php, they're sort of fundamentally different from all my other files, lectures and lecture0.php and index.php. Those don't really belong conceptually in the same folder because they're different, right? Index.php, the user visits. Lectures.php, the user visits. Header.php, the user better not visit because it's just going to be the top of an HTML page and nothing else. So in terms of their role, these files are fundamentally different. So, you know, I'm going to propose that we move footer.php and header.php into a templates folder just to keep them distinct. And I'm going to move helpers.php into a includes directory because it, too, is sort of fundamentally different. Now, there's still a problem here and I alluded to this earlier. You should not put files in your public HTML directory or your document root if they contain information the user does not need direct access to, right? Connor proposed earlier the storage of passwords. So certainly should your PHP files that contain passwords not be in the same directory as index.php and the like. But this, too, isn't quite perfect. So let me actually open up version 5's README which again will reveal the file structure without really getting us bogged down into the-- in the actual details of the code which is largely the same. Here is an even better approach. Now, I'm proposing, no more public HTML directory. We'll see with the first project that you can actually have your own vhost or virtual host in the appliance and have your own document root so you don't need the silly tilde or any of that. And once we enable that feature of virtual hosting, I'm going to propose this, that our HTML files go in the HTML directory, PH, index dot-- sorry, not my HTML files. That my top level files that the user will actually visit, go in a directory called arbitrarily HTML because it's meant to be public-- user facing. But then in an includes directory, that's at the same level as the HTML directory. I'm going to say helpers go and then templates, the same. So we'll see this in more detail next week and with the first project but now, the document root of this website will be the HTML directory. And the implication of that is that anyone on the internet can access files in that document root directory but they cannot access anything in includes or templates because includes and templates are not inside what directory? Public web? The public web directory, the document roots, the HTML directory in this case. And now too, we have the V in VMC. Now, my HTML directory, I could really call, just to be clear, controllers and my templates can be called my views includes-- it doesn't really have a letter in the acronym. But in terms of MVC, controllers again refer to the code that you write that control the user's interaction with your website. And so it stands the reason that index.php is like the entry point to my site and it's controlling the user's experience by rendering this file, requiring this one and so forth. Whereas the templates, now I've called views, aren't really meant to be directly accessed by the user but they do relate directly to aesthetics, and so what we generally call templates are really more generically known as views. And so now we have the C and the V in MVC, we just don't really have a mental model yet for data, for storing things in a database but again, that will come on the horizon. So to sort of retell the story in just a few seconds, we started last week by piecing together all of these various PHP files, index.php today, froshims.php, register.php, and again if we continue that design process, things would kind of sprawl and get rather messy, hard to update, have to copy paste code all over the place. But now that we are sort of taking this approach, we have a cleaner design and it's just going to long-term make our live easier because we can change one detail in header.php and it affects all of my other pages without having to open up 10 or 5 or 20 different files, moreover I get some additional security controls, more of which we'll talk about in the future. So if you're new to web programming, at least try to appreciate the distinction in terms of design between where we started tonight and now where we seem to be ending in terms of the directory structure and the code design because those lessons will occur in the first project. Any questions on model-- on controllers or views or these refinements of our design practices. No? All right. Why don't we officially wrap up here? I'll stick around for questions and then Peter will be up in just a few minutes to dive into section. More on MVC from him and that will also be filmed for those following along at home. OK. And no class on Wednesday, July 4th. [ Silence ]