[ 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.