New terms from treehouse – Enhancing a Simple PHP Application Part 1 – Integrating Validation Errors, Cleaning URL’s with Subfolders, Cleaning URL’s with Rewrite Rules, and Refactoring the Codebase

Integrating Validation Errors

Setting an Error Message Variable

Our goal is to change the contact form errors so they display with styling rather than taking you to a new page with just the text. We’ll start by removing the echo commands for the error messages and putting them into a variable $error_message instead. We’ll also remove the exit command. Note that we can use the same variable name because each message is in a different conditional.

Screen Shot 2014-12-15 at 2.49.09 PMScreen Shot 2014-12-15 at 2.49.40 PM

Next, we’ll add a conditional around the code to send the email only if there are no errors, so we’ll check if it’s set with isset.

Screen Shot 2014-12-15 at 2.54.03 PM

Now, there’s still a conditional in there that could display an error message, We’ll rewrite it so if it’s successful, we redirect, and if not, we set the error message variable.

Screen Shot 2014-12-15 at 2.57.14 PM


Displaying the Error Message

There are two outcomes to this, either the email is sent successfully, or we set the error message variable. We’ll set a quick conditional to show that if it’s set.

Screen Shot 2014-12-15 at 3.02.03 PM

Screen Shot 2014-12-15 at 3.04.15 PM

To have this display better, we’ll move the code for it to the top of the form.

Screen Shot 2014-12-15 at 3.09.48 PM Screen Shot 2014-12-15 at 3.07.04 PM

Next, we’ll make it so that the the welcome message above that displays only if there’s no error message.

Screen Shot 2014-12-15 at 3.11.52 PM

The last tweak we should do is make it so that if the form is submitted with no info, we give a more specific error than “You must give a valid email address”. The issue here is that the email check is later in the code, and is therefore overwriting the first conditional that checks if any of them are blank.

Screen Shot 2014-12-15 at 3.14.24 PM

To fix this, we’ll add some conditionals around the last three error messages to check if the $error_message is already set. Note that the AND conditional can be written as && instead, and usually is.

Screen Shot 2014-12-15 at 3.17.51 PM Screen Shot 2014-12-15 at 3.18.40 PM


Re-Displaying the Submission

When someone fills out the form and there’s an error, we display the error message but also remove what they’ve entered! That’s annoying.

Luckily, if the request method is POST we’ve loaded what they’ve entered into variables at the top of the conditional, and can use these later for the value attributes in our input fields. Since textarea’s don’t have value attributes, we must put it in between the opening and closing textarea tags.

Screen Shot 2014-12-15 at 3.20.46 PM

Screen Shot 2014-12-15 at 3.25.57 PM


Escaping Output

2 Core principles – filter input, and escape output. Right now, if someone entered malicious code into our form, it would display on the screen.

Screen Shot 2014-12-15 at 3.28.25 PM Screen Shot 2014-12-15 at 3.28.47 PM

Even worse, what if that code closed our form and created a new one that submitted the data to their server? The page will look completely different.

Screen Shot 2014-12-15 at 3.30.07 PM Screen Shot 2014-12-15 at 3.30.13 PM

They could send that out to people. They’d visit this page on your server, and their credentials would be sent off to the malicious one! This is called Cross-site Scripting (XSS). To combat this, you can escape output in php with a simple function call name htmlspecialchars() wrapped around the things you’re outputting to the screen. It converts special characters like opening and closing angle brackets to their entity names, so they get displayed instead of being treated as html.

Screen Shot 2014-12-15 at 3.35.38 PM Screen Shot 2014-12-15 at 3.35.22 PMScreen Shot 2014-12-15 at 3.35.31 PM


Cleaning URLs with Subfolders

Introducing Subfolders

Right now our addresses have things like .php or a variable in their url. If we clean them up it can help with SEO and make them easier to remember.

Subfolders will help with this. You know how servers go to index.html by default, while not displaying domain.com/index.html? We can use that with subfolders for the same outcome. First we’ll do our receipt.php page. We’ll make a folder called receipt, then rename the php page to be in there.

Screen Shot 2014-12-15 at 3.49.53 PM 1

If we navigate to that folder, we’ll see this.

Screen Shot 2014-12-15 at 3.50.25 PM

To fix that, rename it to index.php. This will display the markup, but at the same time the styling and includes won’t work, as well as links to other pages.

Screen Shot 2014-12-15 at 3.51.58 PM

Most websites are set up like this, with sub folders hierarchy. To reference a parent directory, it’s just like CSS with ../. This will fix our includes and links, but we still need to fix the styling.

Screen Shot 2014-12-15 at 3.54.55 PM Screen Shot 2014-12-15 at 3.54.59 PM


Using Root-Relative Web Addresses

The links in the header do not work, because they’re looking for links in a directory they don’t have access to on the receipt page. A better way for these is with an root relative url, which start with a slash, which tells the browser to start at the root of the domain. /shirts.php would have the browser start at the root, then look for a file in the root folder called shirts.php.

Screen Shot 2014-12-15 at 3.59.11 PM

So, we’ll edit the links in our header file. You can link to the home page with just a slash. We’ll do that for the main nav links, and also for the css files. Now, everything works.Screen Shot 2014-12-15 at 4.01.31 PMScreen Shot 2014-12-15 at 4.01.34 PM Screen Shot 2014-12-15 at 4.05.14 PM


Using Absolute Server Paths

Let’s say you want to include a file for some code, but you don’t want to use a relative link. You don’t want to use an absolute link either because you don’t want to have to wait for a web request to a different web page. Instead, you write the absolute server path like this (it depends on your OS).

Screen Shot 2014-12-15 at 4.09.43 PM

If you’re not sure what to write for that, you can use $_SERVER[“DOCUMENT_ROOT”]. Note that it does not have a trailing slash at the end.

Screen Shot 2014-12-15 at 4.13.03 PM Screen Shot 2014-12-15 at 4.12.50 PM

So, can now actually use that by concatenating it to the beginning of our root relative paths. Since there is no slash at the end of the document_root, we can leave the one at the beginning of the root relative one, so when this is live it lines up correctly.

Screen Shot 2014-12-15 at 4.17.02 PM


Introducing Constants

If we were to move our site files to a subfolder in the root directory, our absolute server paths would no longer work. To fix this, we’ll define one variable for the root of our site that we could use on all pages. We’ll make a new include file called config.php. Note: for files with just php, you should leave off the closing ?>, because the browser will add it automatically for you, and it will help avoid whitespace.

Screen Shot 2014-12-15 at 4.21.36 PM

However, this value is not meant to change, so it’s better here to use a constant instead of a variable. You set them to a value, but unlike variables, nothing can change their value later in your programming. To create one, write the define function, which takes two arguments, the name aka label, which should be in all caps, the second being its value. We’ll then make another constant set to the root path whatever we’re in, then the base_url’s value.

Screen Shot 2014-12-15 at 4.28.53 PM

We’ll now include the config file at the top of our receipt.php file using a require_once and a relative path. This is ok because we only need to do it once per file and this is the only thing we need to change if the hierarchy changes. This let’s us have access to the constants for the rest of the page, so we’ll plug ROOT_PANEL in for the includes. Since we have a slash at the end of root panel, we don’t need it at the start of the part we add after. We used base url for the css in the header.

Screen Shot 2014-12-15 at 4.44.27 PMScreen Shot 2014-12-15 at 4.44.35 PM

I was a bit confused on when to use BASE_URL vs root panel. Apparently base url is for linking to a domain for files like js, images, css and the other main pages, while root panel is for includes of other php files. This is somewhat explained here, but I’m still a bit shaky on this.

If we needed to change the subfolder the project was in from shirts4mike_local to something else, all we’d need to do now would be to change what we have in the config file.


Moving the Other Pages

Basically, we need to do what we did for the receipt page for the other ones as well. This includes:

1. Making a subfolder for it and putting it in there, then changing the php files name to index.php.

2. require_once the config file.

3. Change links to css, images, other pages and js to use BASE_URL.

4. Change includes and requires to use the ROOT_PATH constant.

Note that if you need to link to the home page, all you really need is <?php echo BASE_URL ?>.


Cleaning URL’s with Rewrite Rules

Introducing Rewrite Rules

Apache is the web server software most commonly used to run php, and was included with MAMP. By default it will do things like display the index.php file in a folder, but we can change its behaviors with the rewrite rule.

We’ll start by working on the shirts and shirt pages and making a subfolder for them. Once they’re in there, if we go to that page we get a directory listing. Rather than change the name of one to index.php, we’ll use a rewrite rule. The easiest way to do this is to create and include a .htaccess file in the root of the directory. Note that files that start with a . are consider hidden by the OS,  When you upload this to your web server, make sure that you don’t forget to include it.

Screen Shot 2014-12-15 at 5.14.58 PM Screen Shot 2014-12-15 at 5.14.29 PM

The .ht stands for hypertext, and you can set various web server configuration rules here. Your web hosting server must support these for them to work though. MAMP does by default, as do most. Turn them on with the command RewriteEngine ON. Note that this isn’t php and has its own syntax. To make a rule, write RewriteRule then a space. It has two parts, the first is the url it’s requesting, and starts with a ^ and ends with a $. The second part says what happens when this pattern is found. Below, when shirt/ is found, apache will load the shirts/shirts.php file by default. The url will still be domain/shirts/ though.

Screen Shot 2014-12-15 at 5.25.01 PM Screen Shot 2014-12-15 at 5.24.58 PM

Note that we also had to go in and update the shirts page to require_once the config file, update the links with base url and root path, and also update the product.php page so the path to the images now uses base url.


Get Variables and Rewrite Rules

Right now the shirt details pages use get variables and look like this: domain.shirt.php?id=101/.

Here, we make a new rewrite rule. It checks for the address shirts/, then to check for a range of numbers we do brackets, and inside that 0-9. To check for any number of numbers, add a +. Then, we write the second part for what we want apache to load when the first part it requested. For the GET variable at the end, we want it load what was entered in the first part. To get that, go back to the first part and wrap the part you want in parentheses. Then, to back-reference that in the second part, write a dollar sign and 1. The first set of parentheses is 1, the second will be 2, etc.

Screen Shot 2014-12-15 at 5.36.48 PM

Now to edit the shirt file to make this work. We’ll require once the config file, then edit all our links and includes with the appropriate base url or root path constants.

Screen Shot 2014-12-15 at 5.39.37 PM Screen Shot 2014-12-15 at 5.39.30 PMNow, if someone were to write domain/shirts/108/, they’d be taken to the correct page. However, we also need to update the links on the shirts page to use that format now instead of actually writing out the GET variable. We can do this in our products.php page, in the function we created that adds the list items.

Screen Shot 2014-12-15 at 5.41.55 PM


Redirecting Old Web Addresses

When you change web address like we’ve done here, it’s important to redirect the old ones to the new ones, for if someone links to an old page, or one comes up in a search engine. Let’s start with the old receipt.php page.

Screen Shot 2014-12-15 at 5.48.21 PM Screen Shot 2014-12-15 at 5.50.13 PM

However, if we just do that it will load the receipt.php url, which is not the redirect we want. To do that, add the [R] flag at the end of it.

Screen Shot 2014-12-15 at 5.49.43 PM Screen Shot 2014-12-15 at 5.49.54 PM

We’ll update that for the contact and shirts pages as well. Another thing – when a server responds to a browser, it sends a response code, like 200 for success or 404 for file not found. 301 is to say that the requested resource has moved permanently, so search engines know to index the new resource rather than the old one. To modify the flag, just add =301 to the R.

Screen Shot 2014-12-15 at 5.53.21 PM


Rewrite Rules with Query Strings

Now to make some rules for the old shirt pages that had the GET variables using a rewrite condition. To check the query string (the part of the url that comes after the ?), write %{QUERY_STRING}. We’re looking for one that is an id with one or more numbers, so we can use what we did before for that part. If the url matches this condition, we want it to do the rewrite rule which we’ll write below. If the condition is true, the rule will check if the url match its own condition, in this case shirt.php, then redirect to the new one. To back reference the number from the condition, simply wrap what you want from there in parentheses, and in the rule write %1. Lastly, by default apache will add the query string to the new web address as well. To prevent this, just add a ? with nothing on it.

Screen Shot 2014-12-15 at 6.04.52 PM Screen Shot 2014-12-15 at 6.04.47 PM


Adding a Trailing Slash

If you were to go to domain/shirts without a slash at the end, the web server would add one for you at the end since it’s a folder. If you were to try to go to domain/shirt/101 without the ending slash, it would give you a not found error, since that page is not a folder. This is also because our rewrite rule for the shirt pages is looking for a slash at the end.

We’ll write a rule that looks for shirt urls ending in a number without the trailing slash. We’ll wrap the whole thing in parentheses and then backreference it with a slash at the end.

Screen Shot 2014-12-15 at 6.10.16 PM


Refactoring the Codebase

Introducing Refactoring

Many times when you first write some code, you don’t write it the best way possible. This is often due to not understanding the needs of the feature. You refactor to make it easier to read and maintain, and to add to and improve later.


Duplicating SKU as an Array Element

Here we have our products array. Notice how the key is the SKU (Stock Keeping Number).

Screen Shot 2014-12-17 at 1.15.58 PM

The array_reverse() function takes one argument, the array you want to reverse, and returns a new element with the array in reverse order. However, the key’s for the elements are not reserved and are now the standard 0, 1, 2 etc. Note that for this to work you must set array_reverse() = to a variable, as it doesn’t reverse the original array itself, it returns a new array that’s a copy that’s been reversed.

Screen Shot 2014-12-17 at 1.17.34 PM

The array_shift() function takes one argument, the array you want to shift, and removes the first element from the array. It’s return value is the first value from the original array, the one it removed. This once again doesn’t reserve the key values and replaces them.

Screen Shot 2014-12-17 at 1.19.07 PM

The removed array looks like this. It doesn’t have the key from before either.

Screen Shot 2014-12-17 at 1.19.46 PM

We don’t want to remove the sku from the key, we just also want it in the array. So, we’ll use automated duplication with a foreach loop.

Screen Shot 2014-12-17 at 1.24.24 PM

Screen Shot 2014-12-17 at 1.37.55 PM


Modifying List View Code

Since the SKU is now also in the array, we can modify our get_list_view_html() function to no longer need the key, and instead use just the array. First remove the product_id as an argument, then modify the code to use $product[“sku”] instead.

Screen Shot 2014-12-17 at 1.44.06 PM

Screen Shot 2014-12-17 at 1.45.35 PM

Then, we can update where the function is called, on the shirts page, and the home page.

Screen Shot 2014-12-17 at 1.46.33 PM Screen Shot 2014-12-17 at 1.46.13 PM

Home:

Screen Shot 2014-12-17 at 1.47.13 PMScreen Shot 2014-12-17 at 1.58.21 PM


Separating Concerns: Models

Right now the code for the 4 most recent products on the home page is on the home page itself, which isn’t great if we want to use it elsewhere later. Separation of Concerns principle involves major divisions between the major types of code. We have two at the moment: 1. Data/business logic like shirt pricing. 2. Code that generates web pages like html. We should have each in separate sections, like when we moved the products array into it’s own file. This is a way to avoid duplication preemptively. A model is a file that contains variables and code, and that everything in there is related to data, and our product.php file fits this concept.


Moving Recent Products to the Model

Here we’ll achieve a separation of concerns by moving the recent items logic over to the model file. We’ll start by going to products.php and creating a new function called get_products_recent().  We’ll have it create an empty array called $recent. Then, we’ll need to loop through each shirt one by one to see if it’s one of the last four shirts. Even though we don’t have access yet to a variable with all the shirts, will put on in called $all, then add some comments on what the conditional should do. Then, we’ll have the function return the value of the new array.

Screen Shot 2014-12-17 at 2.02.08 PM

Right now we have our products array just sitting there, but if we were to put it into a function we could call it and get it’s value whenever needed. We’ll do that, and at the end of this function return the value of $products after everything has been added to it.

Screen Shot 2014-12-17 at 2.04.54 PM Screen Shot 2014-12-17 at 2.04.52 PM

Now, we can go back to our get_products_recent function and call that function. Note that we can’t just write get_products_recent();. It’s RETURNING a value, so we must set it equal to a variable to be able to access that value. In this case we’ll use $all.

Screen Shot 2014-12-17 at 2.09.28 PM

In our shirts.php page, our loop was using the $products array, but right now it can’t since we put that in a function. To use it now, we simply have to set the new function equal to a variable. We’ll also make sure to put this in the shirt details page.

Screen Shot 2014-12-17 at 2.09.18 PM

We’ll also add this in to the code on the home page. Right now the code here for determining if these are the last four shirts is mixed in with the code for displaying them. Let’s work on separating them y copying it over to the products.php page.

Screen Shot 2014-12-17 at 2.12.08 PM

We’ll now need to change all the references to $products to $all, since we put that array in a function. We can also remove the $list_view_html variable declaration, as that’s for how the array will be displayed, and we’re focused on just getting the last 4 items. Now, the first part of that foreach loop make sense to keep since they’re here to determine the last four items, so we’ll keep those and copy them into our other foreach loop. We can remove the rest of the html related code here too. Now, we’re all set! Instead of making any html, this loop simply adds to a variable called recent. We have the function return that variable, so now we can use it whenever needed by calling and setting this function to a variable.

Screen Shot 2014-12-17 at 2.14.09 PM

Screen Shot 2014-12-17 at 2.20.17 PM


Separating Concerns: View

The part of the code for displaying the content is called a view. It doesn’t contain code for data or business logic. Our home page is a view.

Screen Shot 2014-12-17 at 2.22.50 PM

First, we’ll make a variable $recent and set it equal to the return of the get_products_recent() function. Then, we’ll switch out $products for $recent. We’ll remove the code for displaying the last 4 items, since our get_products_recent() function already does that for us. We’ll then simply have the loop concatenate each element of the $recent array onto our $list_view_html variable, then echo that out to the page.

Screen Shot 2014-12-17 at 2.25.41 PM

Screen Shot 2014-12-17 at 2.30.09 PM


Separating Concerns: MVC

MVC stands for Model View Controller. A controller combines data from the model with instructions on how to display things from the view, and sends the final html containing both down to the browser. So, if we wanted to change the home page to show the best selling shirts instead of the most recent, we’d edit the controller. To change the logic of which shirts are most recent, we’d edit the model. To change the homepage from a grid view to a list view, we’d edit the grid.

In our last example, that $recent = get_recent_products() code would actually be controller code. While putting it in its own file is apparently too advanced for us right now, you can get some separation of concerns by putting it at the top of the file.

Screen Shot 2014-12-17 at 2.37.07 PM

Screen Shot 2014-12-17 at 2.39.23 PM

Advertisements

New terms from treehouse – Build a Simple PHP Application Part 2 – Integrating with PayPal, Working with Functions, and Wrapping up the Project

Integrating with PayPal

Creating a PayPal Account

This makes things wayyy easier than doing it yourself. Also, when someone adds something to their cart, you want it to stay there as they navigate the site. This is called persistence. Paypal offers a shopping cart service for this as well.


Configuring Tax and Shipping Rates

In PayPal, under My Account > Profile you can specify your business’s tax id. Under My Money you can add a bank account. You can also set up your sales tax under My Selling Tools. You can also set up shipping costs and options based on weight or number of products sold.


Creating PayPal Buttons

We’ll now make some buttons to add items to the paypal shopping cart. Under My selling tools > Paypal buttons > Update > Create New Button. Choose shopping cart for the type, so it adds the item to the cart. Give it a name, price and an item id, which should match the key from our associative array of products. Under Customize button you can add a drop-down for shirt sizes. When you’re done, click Create button. This will give you some code you can paste into your site.

Screen Shot 2014-12-12 at 4.51.05 PM Screen Shot 2014-12-12 at 4.52.11 PM

This form element has a POST method, and its action is set to paypal’s servers. The target attribute opens the page in a new window or tab. The hidden inputs aren’t displayed on the page but do get submitted with the form. The hosted_button_id is paypal’s id for our red shirt, to help prevent fraud. They then have a table for the drop down. The input with the name on0 lets us know this is the first drop-down. The input with os0 stands for the selection in that drop-down. We’ll add some markup like a label to make things more semantic. They give you an image type input for your submit button, but we’ll instead use the normal submit type with our own text. The last img element is used for tracking. It’s a 1×1 px transparent image that the user can’t see. When the page loads, the image is still requested from the server, which records that request. We don’t need this, so we’ll remove it.

Screen Shot 2014-12-12 at 4.58.18 PMNow we have this. When you click Add to cart, it will take you to the paypal cart page.Screen Shot 2014-12-12 at 4.58.18 PMScreen Shot 2014-12-12 at 4.59.51 PM

Screen Shot 2014-12-12 at 5.00.59 PM

Now we need to replace some of the info in that form with info from our product array, and understand the balance between security on paypal’s end, and ease of use on ours. If we try adding a new shirt size via html, like X-large, paypal will accept it. It will also accept if we decide to change the item_name via a hidden input element’s value.

Screen Shot 2014-12-12 at 5.06.41 PM Screen Shot 2014-12-12 at 5.00.59 PM

However, this means any visitor to our site can change the html and mess with things and paypal will accept it. The only value that doesn’t have this flexibility is price.

Let’s copy the hosted_button_id into our product array.

Screen Shot 2014-12-12 at 5.10.42 PM

We now need to make a button for each item in our catalog. To make it easier simply go back to paypal and click action > create similar button. Once you do that, copy the paypal id for each into your array.


Including the Products Array

Now we’ll make one page that can act as the details page for each of our 8 shirts. First we’ll make a file called shirt.php, and link to it in our shirts.php file. The format will be the same, only the data will differ and we have that in our products array. Since both pages need the array, it’s a good idea to put that in it’s own file so that both can link to it with an include.

Now, we need to link to the right shirt details page address. We can do this by adding a ? to the shirt.php link, then a variable name (in this case we’ll choose id, remember it’s arbitrary), then a value, which will be the shirt’s product_id from the array.

Screen Shot 2014-12-12 at 5.29.08 PM

However, what we need it to do is pull that from each array in the array, so we don’t need to manually write it each time. Right now in the foreach loop we don’t have access to that, only the main array, not the sub ones.. We can load the key of each element into a variable using the =>. This will give us two working variables in the foreach loop, one with the key and the other with the value.

Screen Shot 2014-12-12 at 5.31.22 PM

Screen Shot 2014-12-12 at 5.30.35 PM

Screen Shot 2014-12-12 at 5.28.06 PM

Remember the key name of each array was the number we gave, 101, 102, etc. When you click on the shirt, it takes you to the appropriate page.

Screen Shot 2014-12-12 at 5.38.07 PM


Building the Shirt Details Page

For the shirt.php page, we can access the id from the pages web address using the $_GET variable. First, we’ll load that into a regular php variable. We can then choose the array we want by putting it’s key in square brackets after the main array. Rather than typing a specific number, we’ll use the variable declared above, which is set by the id in the url. $product_id is the key, $product is the array itself.

Screen Shot 2014-12-12 at 5.43.33 PM Screen Shot 2014-12-12 at 5.43.24 PM

If you click a different shirt, you’ll get a different array.

Now, to set up the page. Like the other pages, first we’ll set the section and page variables and include the header and the footer. Then, we’ll set up the html. Note how we dynamically pulled in the name of the shirt.

Screen Shot 2014-12-12 at 5.51.49 PM

We’ll dynamically add the picture as well, using php for it’s src and alt attributes.

Screen Shot 2014-12-12 at 5.56.41 PM

Now to do the details on the right.

Screen Shot 2014-12-12 at 6.00.15 PMScreen Shot 2014-12-12 at 6.00.20 PM

Finally, we’ll pop in the form for the paypal button. We need to add some php so that the button is customized for each shirt.

Screen Shot 2014-12-12 at 6.02.07 PMScreen Shot 2014-12-12 at 6.02.20 PM


Redirecting Invalid Shirt ID’s

What if someone manually changes the web url to an invalid id? We can check this using a conditional at the top of the page, and redirect them back to the shirt.php page if it’s invalid. Let’s do a quick test and echo out our $product and $product_id variables. You can see if the url is invalid, there is still a $product_id, but $product comes out as null, since there’s no array for it.

Screen Shot 2014-12-12 at 6.07.38 PM Screen Shot 2014-12-12 at 6.08.49 PM Screen Shot 2014-12-12 at 6.07.30 PM

We’ll start with a conditional with the isset function to make sure that the $_GET variable named id exists. If it does, it’ll set the product_id variable. Next, we’ll check if our main products array has a shirt with that id in it. If it does, then it sets the $product variable on this page. Using else blocks, if there is no id at all, it will say that message. If there is an id but it’s invalid, then that message will be displayed.

Screen Shot 2014-12-12 at 6.17.58 PM

We can write a second conditional after that that checks whether $product has been set. Due to the previous code block, if it was, we know it was a valid ID.

Screen Shot 2014-12-12 at 6.19.38 PM

The negation operator ! let’s you check if something is NOT something. Here, we make it so that if the $product variable is not set, it redirects back to teh shirts.php page using the header variable.

Screen Shot 2014-12-12 at 6.24.04 PM


Adding Available Sizes

We can customize the shirt sizes for each shirt by adding a new value to our second dimension array, which will actually be another array, a third dimension array.

Screen Shot 2014-12-12 at 6.27.10 PM

Now we can modify our form to use that array instead of the static html. We will use a foreach loop like we did before for the shirts page.

Screen Shot 2014-12-12 at 6.29.58 PM

The shirt sizes listed on the page will now update dynamically based on what is listed in the main product array.


Working with Functions

Introducing Functions

Now to update the main landing page. There are some shirts here, but right now they’re just using static html, rather than the stuff we set up for the shirts page.

Screen Shot 2014-12-13 at 4.43.55 PM

First, we’ll include the product array right above it. Then, we’ll rewrite the list to be generated by a foreach loop. However, we’ve already done something like this before, so it might be better to set up a function to use. Functions usually perform a small, specific task, and don’t do anything until they’re called. There are three parts to a function: 1. Its name. 2. The argument list – a list of values you can tell it you will pass it when it executes it code. 3, It’s return value. In the example below, the name is count, the argument (which you put in parentheses after the name) is the array, and the return value it gives you is the number of elements in the array. Other examples include isset and date.

Screen Shot 2014-12-13 at 4.54.25 PM


User-Defined Functions

Here, we’ll make a function that mimics the count function. First, write the function command, then its name. Then, parentheses with the argument list, in this case $array. We can then use that variable $array in our code. Then, curly brackets which will surround the code block that will be executed when the function is run. Note that variables created outside of a function are not available inside of it.

Screen Shot 2014-12-13 at 5.01.54 PM

Now to make the code to be run. We need it to count the items, so we’ll make a variable and add 1 to it during each run of the loop, which will give us the total. Before that we’ll make a variable for count and set it to 0. Note that this $count variable is completely unrelated to the $count one outside of the function.

Screen Shot 2014-12-13 at 5.04.37 PM

To return this value back to the main code with the return command. Then in our main code we can replace count() with our mimic_count function.

Screen Shot 2014-12-13 at 5.06.00 PM

Screen Shot 2014-12-13 at 5.06.40 PM


Creating the Shirt Display Function

Here’s the gist of the function we need here:

Screen Shot 2014-12-13 at 5.12.30 PM

Since we need this in both shirts.php and index.php, we’ll put it in an include file, and since it will only be used with the products array, we can just put it in there. We’ll copy over the code from shirts.php that already does this. Rather than returning a bunch of echo’d things, it’s better to use the technique before where we make a blank variable and add things to it with concatenation.

Screen Shot 2014-12-13 at 5.18.24 PMScreen Shot 2014-12-13 at 5.19.01 PM

Now to use this function in our pages. Remember that we need to pass in the arguments as well. What’s nice is that now whenever we need to have a list items of shirts, we can just use this function.

Screen Shot 2014-12-13 at 5.23.24 PM Screen Shot 2014-12-13 at 5.23.16 PM


Displaying Only Four Shirts

However, on the home page we only want four shirts displayed. First we’ll make an element called total_products, and set it equal to the number of elements in the array, using the count function so the number will always be accurate. We’ll create a second variable called position and set it 0, which we’ll use to keep track of how many items we’ve looped through. In our foreach loop, we’ll add one to it each time we loop.

Screen Shot 2014-12-13 at 5.28.59 PM

Now we’ll add a conditional to only add the shirt if it’s one of the last 4 elements in the array. The logic will go like this – we can subtract the total number of shirts from the position. When the result less than 4, we know we’re on the last 4 shirts in the array. Total products = 8, position = 5, remaining = 3. So, the math will be total products – position < 4.

Screen Shot 2014-12-13 at 5.34.51 PM

Now, let’s also make it so it adds to a string like we did before. We’ll make an empty variable called list_view_html before the foreach loop. In the loop we’ll have it concatenate to that variable each time it loops. Then, we can echo the variable containing the for list items outside the loop.

Screen Shot 2014-12-13 at 5.37.56 PM

Screen Shot 2014-12-13 at 5.39.21 PM

If we had a ton of shirts, looping through each one like this to find the last four might not be the most efficient approach, but this is okay for now.

The last thing we’d like to do is have the shirts appear in reverse order, so the most recent one comes first. To fix this, we’ll modify the line of code with the concatenation and have the shirt get added to the beginning of the variable.

Screen Shot 2014-12-13 at 5.41.08 PM Screen Shot 2014-12-13 at 5.41.05 PM


Wrapping Up the Project

Validating Contact Form Data

Now to set up the email that gets sent when you fill out the form. First we need to validate the form data we receive. We want to make sure that each field has a value entered, starting with name.

Screen Shot 2014-12-13 at 6.11.00 PM

But what if someone just puts spaces? There’s a php function called trim you can use which will remove the white space at the beginning and end of the text. We can put it in our conditional, but then that doesn’t help us if we need a trimmed name later in the code.

Screen Shot 2014-12-13 at 6.12.51 PM

Instead, let’s trim it up top when we set the variables.

Screen Shot 2014-12-13 at 6.14.39 PM

Next we’ll make the conditional return false if the name, email, or message are blank, using OR.

Screen Shot 2014-12-13 at 6.17.37 PM

If you submit any of those blank, it now takes you to a new page with just the echo message.

Screen Shot 2014-12-13 at 6.18.30 PM

Ok, now we need to protect our form from spam robots. 2 kinds 1. Fill out all forms hoping they’ll be displayed on a website somewhere, like a comments section. 2. More harmful – they have a way of using your form to send out emails to thousands of other people. This is called the email header injection exploit. There it’s described and a code snippet is provided to protect against the attack. Basically, it’s a foreach loop that goes through each post submission to see if it contains a malicious value, and if it does, uses exit to shut it down. We’ll add an error message as well with echo.

Screen Shot 2014-12-13 at 6.26.43 PM

To combat the first kind of spammer we’ll use a spam honeypot field. The spammer fills out every field in the form, so we’ll add one our normal visitors can’t see with a normal name and id like address, then hide it with display:none;

Screen Shot 2014-12-13 at 6.30.28 PM

Then up top, we’ll add a conditional to see if that field has a value, and if it does display an error message and exit it.

Screen Shot 2014-12-13 at 6.32.42 PM

Finally, if there’s an issue with the CSS and a real user accidentally sees it, we’ll add a note to let them know to leave it blank.

Screen Shot 2014-12-13 at 6.33.48 PM


Using a Third-Party Library

A third-party library is basically a set of include files that other people maintain. We’ll use phpmailer to send our emails. The file we need is class.phpmailer.php, which you should copy over to your project into the inc folder, in it’s own folder. Each library you use should get its own folder in the inc folder.

The require_once command is like include, the difference being that if there’s an error, include will give an error but still execute the rest of the code. But, require_once will instead give an error and execute no more code. There’s require, require_once, include, and include_once. The once ones are good if you only want a file to be loaded once, like if it contains functions or sends emails.

Screen Shot 2014-12-13 at 6.44.49 PM

Next we’ll create an object from phpmailer named $mail. This has a method that let’s you validate email addresses. To access an object method or property, first write the objects name, then ->, then the method name, the argument list in parentheses, then curly brackets for the code.

Screen Shot 2014-12-13 at 7.00.06 PM Screen Shot 2014-12-13 at 7.00.01 PM


Sending the Contact Form Email

Now, we’ll use code from the phpmailer example file to set up our email.  Notice that we’re using the -> to set different methods for our $mail object.

Screen Shot 2014-12-13 at 7.05.58 PM

Now, a lot of what we need is already in the variables created from the form submission, so we’ll go through and replace those out. AddReplyTo adds new reply to names to the email. Since we want to reply to the person who filled out the form, we’ll use the variables. SetFrom let’s us set who is sending us the email, in this case once again the person who filled out the form. Since we have that, we don’t actually need the AddReplyTo. The $address variable let’s us set the recipient of this email, in this case us, which we’ll then plug into the AddAddress method.

Methods have parentheses after their names for the argument lists, properties do not. For the Subject property, we’ll edit the message and concatenate the person’s name to the end of it. This makes things more clear and prevents each email from having the exact same subject and getting them all grouped in the same convo. The msgHTML() method sets the body of the email, and we’ll pass in our $email_body variable.

The conditional at the end actually sends the email, calling the method name within it. Here’s how this works. PHP calls the send method, which should send the email, and will return a value of true or false. Since it’s what our conditional is checking, if it’s true, the if block will execute. To check if it did not work we can use the negation operator !.

Screen Shot 2014-12-13 at 7.17.05 PM

If there’s an error, we’ll display a message and stop our code from executing. ErrorInfo doesn’t have parentheses after it so we know it’s a property and not a method.

Screen Shot 2014-12-13 at 7.19.14 PM

The final thing to do is to modify the email body so it uses html break tags instead of php ones.

Screen Shot 2014-12-13 at 7.19.59 PM

If you don’t use a separate mail server, it will use your sites server to send the email, which isn’t recommended.


Deploying the Site

In Paypal, under my selling tools you can upload your logo to your cart page. You can also have it redirect back to your site once the transaction is complete. We’ll make a receipt.php page for that. $section can be set to none, because we don’t need anything underlined in the main nav.

Screen Shot 2014-12-13 at 7.29.30 PM

Now, we need to make the cart picture in the nav actually link to the cart. It’s under paypal > my selling tools > paypal buttons. We can make this into one link using GET variables using a ? to start, then variable=value, then & to add each new one.

Screen Shot 2014-12-13 at 7.31.41 PMScreen Shot 2014-12-13 at 7.32.38 PM

We can now post that link in our header file. Make sure to escape the ampersands with &amp;. The link now works.

Now, load up your site to your server! It’s good to go.


Finishing PayPal Configuration

You can customize your payment page under my selling tools.