[ 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.
What's your name?
>> Hiro Pang [assumed spelling].
>> Hiro?
>> 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.
>> 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.
>> 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?
"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.
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.
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.
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.
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.
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.
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 ]