[ Silence ]
>> Hello and welcome to S75.
This is section the evening of July 9th.
We're going to be doing a walkthrough for project zero
and discussing some issues related to PHP, XML, and XPath.
So the spec is up for project zero.
If you go to S75 dot net you can see it's up on the main page.
Wait, let's see, cs75 dot net.
It's on the main page here.
Project zero specification and a few of the instructions
that I'm going to be doing tonight will be slightly
different than your configuration
because I haven't downloaded the latest version
of the appliance yet, but I'm sure
that we'll have an opportunity to confront some
of the differences between what I'm doing
and the current version of the appliance in future sections.
So first of all, you'll want to create a Bitbucket account.
So in the section labeled Bitbucket,
you can see that it asks you to go
to Bitbucket dot org slash plans.
And I actually don't have a Bitbucket account
so I'm going to sign up.
You want to sign up for the free account and it says to be sure
to use a dot edu address so that you're automatically upgraded
to an unlimited student plan.
And so I will use my name and click sign up.
It doesn't look like there's any errors on the page.
[ Background Sounds ]
So now I have an unconfirmed e-mail address so I'll go
to my e-mail account and will probably have an e-mail
from Bitbucket asking me to confirm.
There. Now I've been confirmed.
So if you go back to the Bitbucket instructions,
the first new thing is to create a new repository.
[ Background Sounds ]
Create repository.
And we want to put project zero under name
and we want a get repository and then we want both issue tracking
and wiki under project management if we like.
I'm actually not going to do that because I'm not going
to be using those features.
Under language, we'll select PHP.
And then we'll input a value for the description
and the website if you like.
I'll put project zero for cs75.
[ Silence ]
So we created a repository and then you should find yourself
at a page whose URL includes your username and project zero.
So I actually haven't finished creating this URL.
I'm not going to enter a website because this isn't going
to be live on the internet.
So here's my username and my project zero.
The first thing you want to do is set up ssh and so if you go
to your ssh directory, you can see I already have an id
underscore rsa dot pub key
and that is what you will create by doing ssh kegen.
So I already have this rsa pub key and in order to get
that pub key, you want to use geany.
[ Background Sounds ]
And then you'll go into your Bitbucket account
and then paste the key into the field called ssh keys.
[ Background Sounds ]
So in account, ssh keys.
[ Background Sounds ]
Here's my whole ssh key.
You want to copy the whole line with no new lines.
So don't copy the new line if you can.
And paste it in.
Add key. It looks a lot like GitHub,
this interface here is probably somehow related to GitHub.
So now we want to create our initial commit
into the repository.
So.
[ Background Sounds ]
So this is the part that will be slightly different for me
than for people running the appliance.
[ Background Sounds ]
So the equivalent of the v host's directory
for me is the public html directory which is the directory
where I will store all of my public facing html files.
If I go into public html, then I will,
let's see if they already you-- make a directory called public
or called project zero and you can see
that it doesn't have the right permissions.
I need at least seven eleven permissions in order to be able
to execute code in that directory and in order
to make it a little bit more friendly
to view online I'm going to give it a little bit more
generous permissions.
So I'm going to chmod 755 project zero.
[ Background Sounds ]
I have a project zero directory and this project zero shows up.
So now let's go back to the walkthrough.
I'm inside of the project zero directory inside
of the directory that will let you show your html
on your local host browser and these commands here are not,
it's not necessary for you to be in this directory,
at least for the config global, but I will do get git init
and it says initialized empty git repository
and then I will say git add hyphen hyphen all
and git commit dash m initial commit.
Okay, so you can see that it says one file changed
and one insertion and zero deletions.
So git is a source code manager.
I've talked about git in previous sections.
There are some resources about git in the project zero pdf.
One of my favorite git resources for beginners is if you go
to the s75 sections page where I store my code for on GitHub,
you'll see down here that there a lot of git resources and one
of my favorite videos is a YUI theater video
where it really runs you through the different workflows for git
and in general, I'll just give you the feel for it.
So we'll do--
[ Background Sounds ]
So you can see here that the project zero background is red
because I specified this attribute, bgcolor equals red,
and if I, let's say I want to work on a new feature,
then I can do git branch or git checkout b, let's start working
on the new feature called blue, and if I say git branch,
you can see now that there's a star next to blue indicating
that I now have the blue branch checked out
and each branch is literally a separate branch in your code
that can separate the different features that you're working
on at one time and then later on you can merge them together.
So now I can go into the index and change the background color
to blue and refresh it here and it will be blue and--
[ Background Sounds ]
If I do git add a, that's a synonym
for git add hyphen hyphen all like we did before.
If you git status it shows you
that the index dot PHP is modified and it's not staged
for commit so right now since there is nothing in this section
of the git status message,
nothing would actually be committed if I were
to make a commit right now.
In order to stage that modification,
I can do git add a index dot PHP.
Now if I do git status, you can see changes
to be committed includes the modifications
such as making this blue and then you can do a commit,
git commit finished blue feature.
This is my nice commit message.
And now I'll do git branch and I can see I'm still
in the blue branch if I do git checkout master.
Now it says switch to branch master
and you can see this directory is white,
or this background is white,
and if I do vim index dot PHP you can see
that that background color is not even present here.
But if I do git merge blue
and the refresh the page, now it's blue.
So basically what it did is it took the code
from the blue branch and it merged it in tracking
where all the insertions and deletions were
in each of the sub files.
So what this enables you to do is work on,
keep your master branch clean
as of your latest good-working version,
and then you do git checkout b, no-
[ Writing on Board ]
Dash b and then feature name and that will switch you
to a brand new branch called feature
and then you can continue working on that feature and then
at any time you can go back to the working version and get it.
And so now let's finish setting up Bitbucket
because you'll see the true value
of git once Bitbucket is set up.
So we've made an initial commit.
I'm going to make this nice and big.
And--
[ Background Sounds ]
You can see, this is the command we're going
to be working on right here.
git remote add origin git at Bitbucket dot org
and then you want a colon
and then do your username pnore slash project zero dot git
and that should be
[ Background Sounds ]
That should be this project, git, yeah, see,
git at Bitbucket dot org slash pnore slash project zero
dot git.
[ Background Sounds ]
And then git push u origin master.
The very first time you'll have to say yes I do want to commit
or I do want to acknowledge that that domain is trusted.
And now if we visit--
[ Background Sounds ]
Let's see.
Our source code will appear here.
[ Inaudible Comment ]
Oh yeah, you're right.
Here. So this should be--
[ Background Sounds ]
Okay. So now I've messed it up.
So basically your code will appear on Bitbucket
after you push if you don't misspell get g-e-t
at Bitbucket dot org and as long as you keep doing git commit
and then git push, then the most recent version
of your code will always be stored online and what
that will mean is that any time you can delete your entire
directory and then do git clone and then your Bitbucket URL
and you will be able to download the most recent version
of your code from online which will provide some insurance
in case your appliance goes corrupt or something.
So after you have git configured then you'll want
to start thinking about how to encode the menu in XML.
We've already talked a little bit about how to do XML in PHP,
specifically in last week's lecture we talked about how
to parse rss and David talked a little bit
about that in his lecture.
[ Background Sounds ]
If you were here last week and you saw the section
about working with model view controller in PHP,
we created a simple model of a blog using an rss XML
as a data storage mechanism and this is what that blog looked
like and it has only one controller element,
only one user interface element which is
that you can press next buttons until you get to the end
of the post and then grays out
and then you can press previous buttons until it gets to the end
of the post and then grays out and all of the information
from each of these blog posts and the blog title
and the blog subtitle is stored in an XML file.
And so you can see that the context
for this application divided up model view and controller
into three separate folders.
You can get a nice directory tree like this
in ASCII using the tree command in Linux.
[ Background Sounds ]
Which gives you a nice printout and so in mvc
in general how the flow of mvc goes
from one file that's the entry point to the controller,
the controller makes a request to the model
and the model interacts with the data storage mechanism
and then passes the data back to the controller
and the controller then does any final formatting that's
necessary and prepares the data to be sent off
to the appropriate view where the view
that the user sees is rendered
and in this case this is the order of execution.
So you can see that there's a separation
between the controller and the model and the controller
and the view and the controller.
The controller is kind of the cement
that binds it all together.
So if we go into the model, data dot XML, you will have
to invent your own XML schema for project zero.
I chose rss because it's already a well-known XML format
for doing blog things and the model in this case,
parse is this XML file and renders each
of these blog sections
and provides the information necessary to gray this
out if there are no previous blog posts.
If we go to--
[ Background Sounds ]
So the first point of entry is the controller which is up top
and the data structure here, I've created an array
of like queries basically to query the model with and each
of these is a variable that I want to be filled
in with some kind of data and when you're using mvc,
you want your model to be separate from your controller
and the idea is that a team that's halfway
across the country could be working on the model
and the could be coding all of the business logic
into the model and then you could be coding
on the controller and then at the end you'd be able
to hook it up together.
So it's important to have an interface that enables you
to keep a separation between the model and the controller
that just helps you write clean code.
In this case, these variable names are variable names
that I know that the model supports
and this is slightly different from the version
of the application that I presented last time
where I actually put queries right in the controller.
If you look at
[ Background Sounds ]
So here the controller is 65 lines long
and here it's only 31 lines long.
In general, if you find your controller inflating with logic,
like notice here I have to do an if call, you know,
if you have lots of logic inside of your controller in order
to just render the data necessary
for the view then you might have what's called a fat controller
which is a good sign that you need to move some
of that data back to the model.
And the model in this application uses XPath
which is an XML query language, as David mentioned,
in order to access each of the variables.
So for each of these variables like posts to display,
it gets passed into the model and down here I iterate
through each of the queries and if a function exists
with the query name, like each one
of these is an associate of array.
We have post number to display it goes to
and then a string of length zero.
If a function exists called post to display,
then I use the function call user func to call the function
with that name and with the parameters indicated here,
in this case no parameters or default parameters.
So for each of these queries down here,
as long as I create a function with the same name as the query
and then return the value that is supposed to enter in here,
then after the model is included then now the data variable will
actually include this same
or data array except the data will be filled in by the model.
So if I comment out the time lines that were in front
of this echo comment which is going
to print recursive the data variable,
you can see that it's filled in the post to display variable
with the appropriate data.
So the way that that has worked, [inaudible] stored a query here
in post to display that is an XPath query.
Here the query is, let me get the data open, app oh six--
[ Background Sounds ]
Yeah?
[inaudible comment]
Okay. Yeah.
That's fine.
Thank you.
Yeah.
[ Background Sounds ]
This particular query is the rss, it seeks the rss element,
and then it seeks the channel element
and then it seeks the item element
and then it applies a filter to that
where the position XPath method is equal to a digit
and the digit here defaults to one,
but here I find it really useful to look at the simple XML
or to the notes that I've put on XPath in readme,
so stylist studio's XPath reference this page here is
at the bottom of my s75 sections page, this reference
for stylist studio is a great reference
for the XPath functions that are available to you
and to just the general syntax of an XPath query.
So here they're showing you
that like this query would select the para children
that have an attribute of type equal to warning.
So when you're designing your XML structure, you want to think
about making a structure that's easy to query
with the XPath that you understand.
So let's get out and let's look at menu dot XML.
So this is a simple menu and--
[ Background Sounds ]
So the way that you get to the point
where you can actually read in the XML
and conduct XPath queries on it,
you have to use simple XML load file, I think that's it--
[ Background Sounds ]
Let's just do a print r on this to begin with.
[ Background Sounds ]
Yeah. Simple XML element load file.
So this file is in the same directory as menu to XML
so let's take a look at what this looks like.
It should be the same file actually.
So you can see if I do a print r it doesn't look very great
on the top so let's actually, echo pre.
[ Background Sounds ]
Alright, so simple XML load file returns a six simple XML element
object and inside that object is an array, an associative array,
well it's [inaudible] but the comment property goes
to another simple XML object and the pizza's property
of the simple XML object goes to another simple XML object.
So in order to access, let's do--
[ Background Sounds ]
If we do XML pizzas item and--
[ Background Sounds ]
And this one is called tomato and cheese
and in simple XML element or in the simple XML element class,
[ Background Sounds ]
It's more tricky to get a hold of the attributes
which is why you might want to stay away
from them and instead go--
[ Background Sounds ]
Because now we can descend into this element.
[ Background Sounds ]
Like that.
So here I called forth the tomato and cheese element
by being able to descend into this.
In each one of these on the menu, you're going to have
to kind of take a look at the menu and figure out how it is
that you want to break it up.
You only have to do a few from each section.
[ Background Sounds ]
You want to think about how to uniquely identify each of these
because somehow you're going to have to pass information
about this exact purchase that's going to be passed
over to the server and it needs to be able to identify
that that element is actually the large broccoli pizza.
So here we could do pizzas item name equals
[ Background Sounds ]
And then we could do a price element
or we could do a size element.
If we do a price element, then we're just going
to have to do large or small.
[ Background Sounds ]
And you could dispense with the price altogether.
Let's see, what it is the broccoli?
Ten eighty five.
Here's another issue.
Let's parse the, let's say that you have pizza name to get
in a variable and we want the broccoli one.
[ Background Sounds ]
Then you could do item.
You could execute an XPath query on this with the XPath method.
And you could say pizzas item name equals
[ Background Sounds ]
And let's see what that gives us.
[ Background Sounds ]
So let's put another one in here just to make sure
that we're not getting the wrong one.
[ Background Sounds ]
That's another one.
I'll add tomato and cheese.
[ Background Sounds ]
That one's cheaper.
Nine seventy five.
[ Background Sounds ]
Okay, we're still getting the correct,
assuming that you have the name of the pizza here
and you already know what you are getting pizzas,
we're getting the right pizza element here.
And let's say that we have pizza size in a variable
and it contains either the word large or the word small,
then you could do the set we--
[ Background Sounds ]
So now the pizza we want is indicated or is this array
or this result right here with a single element
that is now available inside the pizza we want variable,
so if we wanted to get at the pizza size
that we did then we should be able to--
[ Background Sounds ]
Pizza we want.
And this is an array so we have to do zero,
and we have to iterate into the array in order
to get the first object out.
It just so happens that there's only one result.
You might want to find want to find
out how many XPath results there are in which case you'd want
to do count of the array and in this case it'll do one
because there's only one result.
[ Background Sounds ]
And if we want to get at the, let's put the small size in just
so that we know we're getting the right one.
[ Background Sounds ]
So for broccoli it's six eighty five.
[ Background Sounds ]
And we want to get at the pizza size.
[ Background Sounds ]
And it echoes out ten eight five.
So now what if you wanted to get two of these
and then print that out?
If I do this, if I get ten eighty five times two I get
twenty so there's something funky going on there and it has
to do with the type conversion.
When you get things out of XML, they have to be converted
into the form that you want to use it in PHP.
So let's say that we want to--
[ Background Sounds ]
Store it as a float.
[ Background Sounds ]
Okay, so now we get a better answer.
You can see it's twenty-one point seven,
but floats are approximations and that's a big problem
with money if you're approximating with cents.
Now grant it with a pizza restaurant,
you're probably not going to get into the quantities
where it's really going to matter
but when you're building things for clients you should assume
that it's really important for you not to mess
with their money, so in this case it might actually be smart
for you to think twice about storing this as a float
and dealing with it as a float.
Floats are always,
approximations are always one number divided by another number
and it's that what you're getting is the number that's
closest to whatever that is and if you add enough
of them together eventually you'll get a rounding error.
You might get two numbers that add
up to ten point nine nine instead of adding up to eleven.
So instead, what we could do is store it like this,
in pennies because pennies are quantifiable and then
at the point where we actually display it
out to the screen we can still divide it by 100
and still get twenty-one point seven
and at this point you might be wondering how you get it
to format the right way and there's in some
of the model code for this section, app model--
[ Background Sounds ]
So this function, sprintf, is often used to format strings.
[ Background Sounds ]
You can also use number format and which takes a number
and then a number of decimals so let's try that.
[ Background Sounds ]
Okay. So now we need a dollar sign.
If you put it in single quotes the dollar sign will appear
as you want.
If you put it in double quotes, then you'll kind
of confuse PHP a little bit but it'll probably be okay
because when you use double quotes, it interpolates it.
So actually here I shouldn't be using double quotes,
I should be using single quotes
because every time you use double quotes on a string,
PHP wastes a few clock cycles trying to see
if there is a variable in there that it needs to interpolate,
but let's see if this works.
Yeah, that works okay.
So now you can display the total out to the screen
but if you do all your math in terms of pennies,
then you'll never get any rounding errors
or anything like that.
You might want to use the ceil function in order to get
to the ceiling if you're rounding things.
You might want to get to the floor function if you want
to round to the floor.
In general, you're going to have to somehow create a way
to display the menu and then make a way for a user
to select an item and pass a unique identifier of that item
to the user or to the server and one way that you can do that is
by passing each of these parameters at git parameters.
So you could do a level one equals pizzas and level two,
or you could even, since each of this is a separate category,
you could say, instead of calling these pizzas,
you just get rid of the item and instead call this pizza.
Now you have a really simple categorization
where when you're displaying the pizzas menu you can pass
in the menu name and then pass in the name
of the element you want to select
and then the relevant price and you'll have
to keep track using the session, a variable.
You'll have to keep track
of what is stored in the user's cart.
You can go back to previous sections code if you want
to see a few examples of that.
So in six, sorry, no-- in six twenty-seven we talked
about session so in here you can go through these examples
in order to see how to use the session on variable.
The basic gist of it is that you need to call session start
at the very top of the code and since you're going
to be using templates, you'll want to do this in one template
and then include that in all of pages that the user sees
so that all of the users don't see each other's carts.
One little thing to think about is that the session,
the way the session works is that it's literally a folder
on the server that is named like a long number
and that long number equals a number that is stored
on the user's computer in a cookie that is sent along
with the request to the server and so if you think
about every single user having a different number
and a different folder on the browser, then you'll see
that you probably don't want to store the menu
in the session variable because essentially then what you'll be
doing is for user one, two, three, you'll store a menu
and then for user one, two, four you'll store the same menu
and so there'll be a lot
of storage duplication if you do that.
Instead, you should think of a way to generate the views
from the XML in realtime or cash them in some other way.
And so that you aren't unnecessarily burdening the
server with the details of the menu.
So let's see, I wanted to show you a few different XPath tools
so if you go to GitHub dot come slash codekiln slash s75 hyphen
sections you can get all of the code for each of the sections
and then down here on under XPath,
there are a few different tips.
Here you can use this add-on called scraper in order to test
out XPath so you'd open up Chrome
and you'd say add to Chrome and then--
[ Background Sounds ]
I have all these--
[ Background Sounds ]
Oh yeah, I messed with the source.
[ Background Sounds ]
Okay, so what scraper is good for is that if you come
to a page like this which has the list
of all the postal abbreviations and let's say you were working
on a project where you needed a dropdown list that had all
of the postal codes in it and you wanted your users
to select the postal codes,
then if you have the scraper extension installed you can
right click on an element and say scrape similar
and you can say it gives you a good guess of the XPath
that lets you scrape all of those postal abbreviations.
Here you can see kind of what it's doing.
Alabama AL, ALA dot ALA dot oh one.
That's just reading this very first row,
but if you press control shift c
and examine the element you can guess that it's always going
to be the second table data element in this table
that contains this postal abbreviations.
So maybe you could say you want just the second one
and then you realize that it already has a predicate limiting
you to the very first table row so now when you remove
that predicate, you get all of the states and you can copy
from there into a tool like notepad plus plus
and here you can use regular expressions
to clean up the text.
If you select regular expression in notepad plus plus,
you're able to use regular expression keywords
like backslash w is a nonword character,
you can see there are a couple of those,
and then I could do a digit character followed
by a digit character that may or may not be there followed
by another nonword character and if I replace all of those
by nothing now I have all of my abbreviations and a few extras
because it includes like minor outlying islands
and stuff like that as well.
So at this point you could paste it into your PHP code
and make a select where each of these is an option
that you could drop down.
Another example of using scraper, you can,
if you are on a rating site and here they make it pretty hard
to just get a list of all the people, they have it here
on the page but if you wanted to actually make a list of each
of this people, you'd have to type it out one by one
or copy it out one by one, and if you select here
and do scrape similar, it gives you a guess but if you look
at the search code, you can see that they've obfuscated it.
They've put tables within tables within tables.
And so if you go down and you notice that the TR here,
the table row, has a height
of thirty then now you could search for,
and if you do two forward slashes that means all elements
where this matches, so I'm going to look for the TRs,
all of the TRs in the document would return tons and tons
of TRs, and you can see some of them are in there.
We want a subset of that.
We want the TRs where there's an attribute height equal to thirty
and now you have the same list.
You can copy it and paste it
in the notepad plus plus and clean it.
Up here I'll do another [inaudible] example.
We'll do a nonword character followed by a digit followed
by another possible digit followed by a nonword character.
Let's see how far that gets us.
Now we have another digit followed
by a literal period followed by another nonword character
and I believe there is another digit
and the question mark means zero or one of these
so now we've got that.
So now you have your list if you wanted to do a quick blog post
about that or whatever or do a Google search on each of those.
So scraper is a great way to practice your XPath skills.
In fact, you can even open up the XML
for your menu in your browser.
You'll have to make sure that it has the right permissions.
So if you do l s dash l you can it is not world readable
so we chmod six forty four menu dot XML and now we'll go back
to the sections and menu dot XML is here and you can see
that it doesn't have any style information associated with it.
Here if you press control shift c--
[ Background Sounds ]
Well, this is not the raw XML by any means.
I was thinking that you'd be able to actually use XPath right
on the thing but it doesn't look like you'll be able to.
But I did want to point out that the XPath that you're able
to get in scraper you're also able to get
at using this search elements dialogue in Chrome
so if you click here and right click,
like let's say we right click on this a, this anchor element
that is for the PHP manual and you do copy XPath
and then do search elements and paste it in
and maybe remove some of the predicates then you can flip
through the different matches.
Here's the introduction match and it gives you a good guess.
Here we have the star operator which matches any element
and then we're putting a predicate on id equals left bar
and then whatever element has an id attribute equal to left bar,
we're looking at the elements that have a ul child
and an li child and then finally an a child.
So you'll get pretty comfortable with XPath
in this assignment, hopefully you will.
If you don't do something terribly work-aroundy you will.
And so do you guys have any questions
about XPath or XML in PHP?
I think we've covered everything that you basically need to know.
We're going to be online answering questions
and stuff as well.
[ Background Sounds ]
[ Inaudible Comment ]
Yeah.
[ Inaudible Comment ]
Yes. So the question was, does the spec include the requirement
that you have an ability
to see your entire cart before you check out
and I haven't read the latest version of the spec in detail
but I believe it does.
Previous years have had that requirement and so you'll want
to make a page that enables you to see the contents of your cart
and that enables you to add things to you cart
and subtract things from your cart before checking out.
That's a good question.
And let's just take a look at that file.
[ Inaudible Comment ]
So the question was, so the general format of the project is
to create a categorization of the menu in XML and then
to use PHP to pull the information from the XML
and then display it out to the page
and the use PHP's section functionality in order
to store the information about the cart
that the user is interacting
with through separate page requests
and then finally providing them with the ability to check
out and clear their cart.
Is that kind of your-- you were just trying
to clarify the process?
Yeah, that's generally it.
[ Inaudible Comment ]
Can you say that last part, whatever you selected what?
[ Inaudible Comment ]
So the question is, should I make
so that you can select several items and then log out
and then log back in and then still have those items selected
and the answer to that is that you don't have any logging in
and logging out functionality in this application.
If you want to do that, that's above
and beyond this spec. This spec is only to implement the cart.
So in this case, this application is kind
of a trivial ecommerce site
because in a real ecommerce site we would be gathering credit
card information and you wouldn't want
to gather credit card information
without confirming a user's e-mail address and stuff
like that and you probably won't want to go that far
in this assignment because the details of sending mail
through a server that's running on your own computer
and getting it to actually arrive in a real e-mail inbox,
that's pretty complicated
and that's beyond the scope of this project.
It can be one but it's a more complicated development
situation than we really have the time to deal with.
Does that pretty much-- yeah.
So there is so much to work with here.
If I was going to sit down tonight with a student
who didn't know where to start,
I would say first develop your menu XML, develop a menu XML,
don't develop the entire menu, just develop a menu XML,
if it has like ten items in it or something.
So--
[ Writing on Board ]
And then render menu and then render way to select items
and then add ability to put in cart and then add the ability
to check out and what check out means in the case
of this assignment is telling the user,
you have purchased this amount, it will be billed
to your e-mail account or to your credit card or whatever
and then you should call session destroy and clear the session
so that if they go through another purchase they'll be able
to fill up their cart again.
And once you get to this point where you'll actually able
to render ten items and render a way to select them,
add an ability to put in the cart and then check it out
and call session destroy, then you can add a few more items
for edge cases and, you know, so step six would be iterate
and inflate the menu and change the rendering for the bugs
that you get when you inflate the rendering.
And if you can close this circle at least once before you get
to the point where you're trying
to render all the different categories and dealing
with all the subtle things, you will get a lot farther
and you will understand the scope
of the project before because, you know, you can get really,
really involved with the menu if you want to and it's best not
to get hung up in any one of the steps.
So it's seven twenty-five.
I think that's probably as much as have time for tonight.
Is there any more questions?
If not, we can take them offline.
So good luck on the project.
Get started tonight, tomorrow.
The 18th is just a week, a little over a week away
so that means that, you know, if you can close this loop
by Friday and get the questions to us
on Saturday then you can spend the next three days kind
of trying to figure out the submission process and trying
to figure out the permissions on the server and all of this
like kind of tricky things.
You should allocate, if you've never worked with Linux before,
you should probably allocate like at least 15 percent of all
of your time to deployment.
If not more.
Maybe 20 or 25 percent.
The very first time you deploy to the assignments
in this class, you'll find that that is really hard
and that is not unlike real life.
When you actually deploy a website,
it is usually not painless.
It's usually a tricky process.
So in general with web development projects,
you should allocate at least 15 percent of your time
to deployment, I mean, unless it's a huge project
in which case 15 percent, you know, it's only going
to take a fixed amount of time probably so.
Alright, that's about everything.
Thank you for your attention and thank you for your patience
with our technical difficulties.
We'll attempt to get them resolved before next week.
Thanks so much.