New terms from treehouse – Enhancing a Simple PHP Application Part 2 – Adding Search: Controller & View, Adding Search: Model, Paginating a List: Controller, Paginating a List: Model and View

Adding Search: Controller & View

Creating the Search Page

We’ll make the page by making a subfolder called search, so we can keep our urls clean, then putting an index.php file inside of it. Then, we’ll include the config file, and set the page title and search variable to underline it in the nav when the page is selected. Then, we’ll include the header and footer files.

Screen Shot 2014-12-17 at 3.00.49 PM

Now, we’ll add a new list item to the nav in the header for the search, updating the class and such for search.

Screen Shot 2014-12-17 at 3.03.09 PM

Screen Shot 2014-12-17 at 3.04.07 PM


Building the Search Form

Here we’ll add some html for the header and form. Note that for the text input he gave it the name s, which is common for search fields. If you search for something, notice how you get s=value you entered in the query string.

Screen Shot 2014-12-17 at 3.09.17 PM Screen Shot 2014-12-17 at 3.08.45 PM

If you leave the form’s action attribute blank, it will redirect back to the current page. For the method attribute, if you give it no value the default value is GET. You should use POST when the form is creating records or taking some other action like sending an email. For retrieving or getting data, like a search, you should use GET. Still, it’s good practice to specify them anyway in the form element. To indicate the current folder, ie for a redirect, use ./, which is for the root of the current directory.

Screen Shot 2014-12-17 at 3.13.07 PM


Handling the Form Submission

We’ll start by making a blank variable $search_term to eventually hold the value entered in the search field. Then we’ll make a conditionally based on whether a value is set for the s get variable. If it is, we’ll add that value to the $search_term variable, and at the same time trim it. Then, we’ll add another conditional that checks if the $search_term variable is not blank. If it’s not, we’ll pull in the product.php file (the model).

Screen Shot 2014-12-17 at 3.20.29 PM

We’ll go to the model now to make a function to perform when the search is performed. We’ll call it get_products_search, and it will take one argument, the search term. We’ll start with an empty array called $results that we can add to, and make a variable $all equal to the return value of the function that gives us the main array. Then, we’ll add a foreach loop to go through those and give us the results. The conditional inside should look for matches, and add them to results. We’ll then return the $results variable so we can use it later.

Screen Shot 2014-12-17 at 3.25.11 PM

Now we can go back and add this function and it’s return value to our search page, passing our $search_term variable as its argument. We’ll also add some troubleshooting code to display the code on the screen if there’s a search entry.

Screen Shot 2014-12-17 at 3.31.32 PM

Screen Shot 2014-12-17 at 3.31.26 PM


Displaying the Products

Now to actually have the products display on the screen. First we’ll remove the troubleshooting code. We’ll then add a conditional below the form checking if the $search_term is not set. If it is, we’ll add ul tags surrounding a foreach loop, which goes through the array and echo’s out the return value of the function get_list_view_html for each element.

Screen Shot 2014-12-17 at 3.41.51 PM

Screen Shot 2014-12-17 at 3.42.43 PM


Accounting For Empty Results

We’ll also make the search field retain the value entered, using the same method as before for the contact form error scenario with the htmlspecialchars() function to prevent people writing malicious code.

Screen Shot 2014-12-17 at 3.49.06 PM

Now to account for what happens if there are no matches. We can simulate this by commenting out the part that adds to the array in the model.

Screen Shot 2014-12-17 at 3.50.54 PM

We can then use the native php function empty() to check if an array has any elements. We’ll use this and the negation operator to make a if else block, where if there is nothing in the array, it displays a message saying no results were found.

Screen Shot 2014-12-17 at 3.56.21 PMScreen Shot 2014-12-17 at 3.56.30 PM


Adding Search: Model

Introducing the strpos Function

Now to make the searching work with the conditional we set up in the products model file. The strpos (string position) function (looks for one piece of text inside of another. The first argument it takes is the piece of text you want to search in, the second is the one you want to search for. It will return the place in the position of text it occurred.

Screen Shot 2014-12-19 at 3.43.34 PM Screen Shot 2014-12-19 at 3.43.38 PM

It can search variables as well. Here we have it search for something not there as well. It looks like it didn’t return anything, but it did.

Screen Shot 2014-12-19 at 3.44.52 PM Screen Shot 2014-12-19 at 3.45.08 PM


Introducing Boolean Values

Boolean values can be true or false, and can be written without quotation marks. If we use var_dump instead of echo, we can see more info about the return values. You can see now that if the text isn’t found it returns a boolean value of false.

Screen Shot 2014-12-19 at 3.52.28 PM Screen Shot 2014-12-19 at 3.52.12 PM


Introducing the PHP Manual

The PHP Manual contains the documentation for everything you need to know, including functions. For example, trim. It will tell you the version it was first available in, gives a description and technical info. Arguments listed in square brackets are optional. Info on the return value is displayed in front of the function name. The word before the argument tells you the data type it accepts for that argument, like string. If it says mixed, it accepts multiple types. It will also list out the return values you get depending on what you enter.

Screen Shot 2014-12-19 at 3.57.55 PM


Introducing Identity Comparison

With strpos, the value we’re searching for is referred to as a needle, and the one we’re searching in is the haystack. It takes an optional third argument that lets you offset the search so you don’t start at the beginning.

Screen Shot 2014-12-19 at 4.03.58 PM

Now, under the return values section they give you a warning that if it doesn’t find it it may return a non-boolean value which evaluates to FALSE. So, you should use the === operator, as that checks for the data type as well as the value.

Screen Shot 2014-12-19 at 4.05.53 PM

Screen Shot 2014-12-19 at 4.06.36 PM

Type juggling means that php will convert the two values to the same type, and then see if they match. So, 5 == “5” would be true. But, so would 0 == false. So, for booleans its good to use === instead. 0 === false would be false. To check if things are not equal and not of the same type, you’d use !== (not !=== because the ! takes the place of the first = sign).

The stripos function is slightly different in that it ignores if the characters are upper or lower case, so we should use that instead.


Performing the Search

Now back to our code. We’ll put the stripos function in the conditional, and have the the thing it searches be the array element that gets loaded into it by the foreach loop, $product, with the name key set so it only searches that value. We’ll have it search the $s variable, which is the search term argument that’s passed to the main function. We’ll use the !== operator to check if it returned a value that is not boolean false. If it didn’t, we’ll add it to the list to be displayed. If no matches are found, we’ll display the message that we couldn’t find any.

Screen Shot 2014-12-19 at 4.17.25 PMScreen Shot 2014-12-19 at 4.17.42 PM  Screen Shot 2014-12-19 at 4.16.51 PM


Paginating a List: Controller

Introducing Pagination

What currently happens:

1. Someone clicks the shirts link, and our rewrite rule redirects them to shirts/shirts.php.

2. The controller code in that file requests all the shirts from the product.php model page.

3. The view code, also on the shirt.php page, then displays all the shirts at once.

What will happen with pagination

1. When someone goes to /shirts/, the controller will have to determine which of the shirts pages is being requested (1,2,3 or 4), then which subset of shirts it needs for that page.

2. The controller requests just those shirts from the model products page.

3. The view will then display just those 8 shirts. We’ll add the pagination links above and below the shirts, and the view needs to know which page its on so we can apply the class to that element.


Getting the Count of Products

We’ll need a function that returns the total number of products in the array. To do that, we’ll define a new one. We’ll set a variable equal to the return of get_products_all, then set another variable equal to the count of that, then return that second variable.

Screen Shot 2014-12-19 at 4.35.21 PM


Retrieving the GET Variable

We can use a GET variable for a page number without any rewrite rules because the items available and their order may change, and it makes it easy for people to navigate from page to page by changing the URL. If you’re on the first page though, the url should just be domain.com/shirts/.

Screen Shot 2014-12-19 at 4.37.36 PM

First, we’ll set a variable $current_page equal to the get value of the variable pg. We’ll add some test code to check if this worked.

Screen Shot 2014-12-19 at 4.40.17 PM Screen Shot 2014-12-19 at 4.40.14 PM

Now, if there is no pg variable, the $current_page variable will be blank, so we’ll add a conditional to check for this. If the pg GET variable is empty, we’ll set the $current_page variable to 1.

Screen Shot 2014-12-19 at 4.42.50 PM


Adjusting Larger Page Numbers

What if someone enters a pg number higher than the number of pages we have? Lets redirect to the last page, but we need to know how many pages we have. To do this, we’ll ask the model how many pages we have, then calculate the number of pages from that.

We’ll get the total number by setting a variable equal to the return value of our get_products_count variable. We’ll also put the number of products per page in a variable as well, in case that changes later. We want to divide them, but what if we had an uneven result? We can use the ceil() function, which always rounds floats up.

We’ll then add a conditional which checks if the current page is larger than the current page. If it is, we’ll redirect to the last page.

Screen Shot 2014-12-19 at 5.03.46 PM


Adjusting Invalid Page Numbers

What if someone puts a string in the query string, or not a number? We can use the inval() function to convert whatever what entered to become an integer. For most strings, this will set them to 0.

Screen Shot 2014-12-19 at 5.06.55 PM

Let’s add another conditional for if that happens and $current_value gets set to 0.

Screen Shot 2014-12-19 at 5.08.15 PM

So, if someone were to enter words now, it would just redirect them to the main shirts page.


Calculating Shirts From Page Number

Right now our shirts page is showing all the shirts due to the variable $products. We want this to instead show a subset, which takes a starting and ending number.

Screen Shot 2014-12-19 at 5.17.30 PM Screen Shot 2014-12-19 at 5.17.25 PM

Screen Shot 2014-12-19 at 5.18.02 PM

We’ll calculate the ending shirt by multiply the page number by the number of shirts per page. To calculate the starting shirt, will take the the current page number and subtract one from it, to get the previous page’s number, then multiply that by the number of pages to get the last shirt of the last page.. Then, we’ll take that and add one to it.

Now, the last page might not have the full 8 shirts on it, like if we had 31 products total. So, we’ll add a conditional that checks if the $ending shirt if greater than the total number of shirts, and if it is we’ll just set it equal to the total number of shirts.

Screen Shot 2014-12-19 at 5.27.35 PM


Paginating a List: Model and View

Creating the Model Function

We now need to make a function that returns the subset of products for the appropriate page. We’ll go to products.php and make a new function called get_product_subset, which will take two arguments, the position start and the end. We’ll set it up similar to the other functions where we needed a subset, where we declare an empty array, make a variable of the products array, and adding a forearch loop for that. We’ll save the conditional for later, but if it’s true have it add that element to the empty $subset array.

Screen Shot 2014-12-23 at 12.33.01 PM


Limiting the Products

Now, for the conditional. We’ll need a position variable that increases by one for each element in the array. Then, we’ll need to check if that falls within our desired shirt range. We want to only add elements whose position is greater than or equal to the starting position, and less than or equal to the ending one.

We need to add 1 to our position variable each time we loop. We could write $position = $position + 1;, but you can also instead write $position += 1;

Screen Shot 2014-12-23 at 12.46.32 PM


Testing Model Code

We could test on our controller page, but right now there can only be 4 different pages, and 8 items per page. If we test on our models page we can try out some other scenarios. We’ll make a new file called model-test.php, include the products.php file, and var_dump the function. We’ll check for some ranges, like 1 to 2.

Screen Shot 2014-12-23 at 12.51.30 PM Screen Shot 2014-12-23 at 12.51.25 PM

Now to try this on the actual shirts page. The get_list_view_html function is taking the variable $product, so at the top we’ll set that equal to our new subset function and pass in the $start and $end variables.

Screen Shot 2014-12-23 at 1.06.32 PM


Introducing While Loops

Now to add the pagination links. A while loop is like a conditional except it runs multiple times, until its condition is no longer met. You first set a counter variable outside of it, usually named $i and set to 0. Inside the loop, you’ll add a line to increase $i by one for each loop run. For the condition, we’ll test if $i is less than the total number of pages. Here, we’ll echo out $i to show it increasing with each loop.

Screen Shot 2014-12-23 at 1.12.04 PM Screen Shot 2014-12-23 at 1.11.58 PM

To make it easier to mingle the php and html, we can change the top curly bracket of the while loop to a colon (:), and the ending one to endwhile. This makes it easy to wrap each section in its own php tags.

Screen Shot 2014-12-23 at 1.14.56 PM


Adding HTML Markup

First, we’ll wrap the echoed $i in an anchor tags. For the link, we’ll use php to set it equal to the current directory (./) plus ?pg= plus the looped page value for this loop run. This adds the links, and they work!

Screen Shot 2014-12-23 at 1.20.47 PMScreen Shot 2014-12-23 at 1.20.52 PM

Now, we want to make it so that for the page we’re on, that that link isn’t a link and is instead a span. You can do something similar with if conditionals by replacing the curly braces with a colon and endif. We’ll check if $i is equal to the current page. If it is, we’ll add a span. If it’s not, we’ll add a link. Note: you can write an else block after an if block using the colon method with else :.

Screen Shot 2014-12-23 at 1.25.36 PMScreen Shot 2014-12-23 at 1.25.49 PM


Using Partials

We also want the pagination links below our shirts, but we don’t want to copy and paste code. So, we’ll make another include file called list-navigation.html.php. The .html is a common naming practice because this is view code that exists simply to display something on the page. This is aka as a partial. We’ll copy our code into there, then include it when needed in our shirts.php page.

Screen Shot 2014-12-23 at 1.30.00 PM Screen Shot 2014-12-23 at 1.29.55 PM

We should do the same thing for the get_list_view_html code.

Screen Shot 2014-12-23 at 1.32.20 PM


Understanding Comments

Comments are essential in describing what bits of code do in case someone else needs to come in on the project or you need to come back and work on this at a later date. Here are some we added for the shirts.php controller code, and the products.php model page. For functions, you should describe what it does, the arguments it receives and what its return value is. The extra stars are like bullet points and are there just for formatting.

Screen Shot 2014-12-23 at 1.37.48 PMScreen Shot 2014-12-23 at 1.40.17 PM

For functions, people often use a standard format called phpdoc, Arguments are listed as @param, and return values are marked as @return.

Screen Shot 2014-12-23 at 1.41.32 PM

New terms from treehouse – WordPress Theme Development Part 1 – Starting a WordPress Theme, Working with CSS and JS in WordPress Themes, WordPress Header and Footer Templates, The WordPress Loop, and Building Page Templates in WordPress

Starting a WordPress Theme

Where WordPress Themes Live

Under Admin > Appearance > Themes you can see the ones that have been installed, and look for new ones to add. Installed just means the files for it are saved in our site’s server. Only the Active theme displays. When you buy a commercial theme, you must upload the zip file under Add New. If that doesn’t work, check the zip, it may have other stuff in there like licensing info, PSD files, a child theme, etc. So, make sure you’re installing the actual zip of the template.

Screen Shot 2014-12-18 at 1.18.50 PM

It’ll now be in your theme section. To manually install a theme, go to your project folder > wp-content > themes. When we’re making our own, this is where we’ll be working.


The WordPress Template Hierarchy

The codex page for this explains that this is all the possible files you can use when building a theme. The diagram here shows the flow for the type of page you’re trying to build, and the type of php file you should end up with. The outcomes on the right on the standard names, while the light blue and orange ones in the middle are more customized. Index.php is all the way on the right, and is a back up template for all other files.

wp-template-hierarchyWPhierarchy.com takes this and makes it into clickable links to the appropriate section in the codex.


Setting Up a WordPress Theme Folder

Make a folder in your wp-content > themes directory, but make sure to choose a unique name that someone probably hasn’t chosen before. Open the folder with sublime, and add three files: style.css, index.php and functions.php. index and style are required files for it to show up under themes eventually. All the meta info for a theme lives in the CSS file at the top in a comment. The Tags are helpful if you’re going to list this in the themes directory. To add a picture for your template, use a image named screenshot.png, with the dimensions 880 by 660px.

Screen Shot 2014-12-18 at 2.12.52 PM


Activating a WordPress Theme

Click Activate to do this. If you have styles.css instead of style.css it will appear in the bottom in the broken themes section with a description of why. If you remove index.php you’ll have the same problem. If you activate the theme and visit your page at this point you’ll find a blank page, which makes sense.


Working with CSS and JS in WordPress Themes

Porting Over Static Template CSS

Simply copy and paste the css over into the style.css file in your theme folder. If you have an @import rule, the best way to handle that is by the functions.php file.

Screen Shot 2014-12-18 at 2.19.33 PM


Adding CSS to a Theme Via the Functions.php File

From the static site we also have normalize and foundations. Copy those into a new css folder in the theme folder. Then in functions.php, make a new function wpt_theme_styles. The wpt_ (wordpress treehouse) is namespacing to make this function’s name unique so it won’t conflict with other plugins that may have functions with similar names. Next, inside that call the wp_enqueue_style function, which lets us link to stylesheets for our theme. The first parameter it takes is a name you can give the file, and the second is the link to it. To do that, use the function get_template_directory_uri concatenated with the path to the file. That function gets us from wherever our root is to the template folder.

We’ll link to both normalize and foundation, and also the google font from our import rule (which we don’t need the get template directory function for), and the mains style.css file.

Finally, use the add_action function to tell WP when to call these files. wp_enqueue_scripts is a hook that tells what css and js files to load for a given page.

Screen Shot 2014-12-18 at 2.38.47 PM


How to Link to JS Theme from the Functions.php File

First, copy the JS over to your theme. Note that you don’t need to copy jQuery because WP ships and installs with it running. Now, in functions.php, make a theme called wpt_theme_js.  Here, we’ll use the wp_enqueue_script function, and like before give it a name and link to the file but also an array of dependents, a version, and a true/false parameter for where you want it to appear in the footer. Foundation is dependent on jQuery, so we’ll add that in, and app.js is dependent on both. Finally we’ll use add_action again so this is called when WP enqueues its scripts.

Screen Shot 2014-12-18 at 2.49.07 PM

Now, you could just have these links in the header tags, but this is more dynamic and preferred as you have to worry less about the root structure and file paths.

If you want to use the jQuery $, in WP this is not auto assumed to have to do with that. You need to add a wrapper for no conflict jQuery. Here, we’ll edit our app.js file for that.

Screen Shot 2014-12-18 at 2.47.56 PM


WordPress Header and Footer Templates

The Header.php and Footer.php Files

These files are important as they let you have the code for the header and footer in their own files you can call on any page you make. First, make a file for each. You call them on a page using the get_header(); and get_footer(); functions.

Screen Shot 2014-12-18 at 2.55.15 PM Screen Shot 2014-12-18 at 2.55.19 PM


Porting Existing Headers and Footers into WordPress

Go to your index file and copy from the top of the page down to the bottom of your header tag or div. Then for the footer copy over everything from the beginning of your footer element down to the bottom of the page, including the closing html tag. Then, clean up your code by removing anything that will be replaced by code form elsewhere. For the title, insert the wp_title() function to have WP determine the page you’re on and display that as the page for you. Delete the references to the CSS and JS, replacing them with the function wp_head(), to let WP know we’re about to be at the end of a head tag, so it should load any functions that need to be here, like our wp_enqueue_scripts ones in the add_action on the functions page.

Screen Shot 2014-12-18 at 3.02.11 PM

Next for the header element, we’ll switch out a link to index.html for bloginfo(‘url’), which will give the url of the site. Then for within the a element, we can do bloginfo(‘name’) to output the name of the site. We can then copy and paste this where needed.

Screen Shot 2014-12-18 at 3.06.15 PM

In the footer, we’ll remove the social links, and change the copyright date to use echo date(‘Y’). Remove the js links, then put in a wp_footer() function. This lets WP to it can put stuff it needs before the closing body tag, like js files. This also results in WP inserting a lot of JS here for the admin header at the top of your site.

Screen Shot 2014-12-18 at 3.14.36 PM


The WordPress Loop

An Explanation of the WordPress Loop

The loop is a powerful block of code at the heart of most templates. It checks for what content is available for a page, then loops through and displays it. It starts with an if statement to see if content is available. It then moves into a while statement that will execute as long as there is code or content to be displayed.

It can be displayed using a shorthand method (the first two blocks below), or a longhand method (the third).

Screen Shot 2014-12-18 at 3.26.24 PM

The shorthand method lets you write your opening, put in a bunch of code, then just put in the closing part, as shown in the example on that page.


Adding the Loop to the Index.php file

Apparently we don’t need normalize, so lets comment that out in our functions file.

Screen Shot 2014-12-18 at 3.30.51 PM

Screen Shot 2014-12-18 at 3.36.19 PM

Now to add the loop for our dynamic content by copying and pasting it from its codex page.

We can then switch out the content for dynamic content using functions like the_title or the_content, which thankfully have very clear and semantic names.

Screen Shot 2014-12-18 at 3.35.43 PMScreen Shot 2014-12-18 at 3.35.48 PM

If we were to go in and add another post under our admin section, it will appear here now as well!

Screen Shot 2014-12-18 at 3.37.54 PM

If we add a page, then customize our site to use a static home page, that will display as well.

Screen Shot 2014-12-18 at 3.39.55 PMScreen Shot 2014-12-18 at 3.39.29 PM

This works because index.php is the back up template for all pages, and since we don’t have specific ones right now for blogs or pages, it uses index.php.


Common WordPress Functions Used Within the Loop

A lot of the ones you’ll want are under the Post section in the function reference. Some say the_something while others say get_something. The the ones will echo that thing out, while the get one will let you get the something and save it as a variable for later. The ones start with is are conditionals, and let you know things like if you’re on a single page or not. Under the Others section you’ll find familiar ones like the_title, the_author, etc.


Building Page Templates in WordPress

The Page.php File

This controls what static pages like the about or contact page look like on your site. First we’ll copy our index.php page to a page.php file. Then we’ll change the no post found message. The e_() that’s wrapped around it let’s this text work with language files for the translation of your site.

Screen Shot 2014-12-18 at 4.13.49 PM

We’ll add some new pages under admin for our portfolio, about us, and contact us. You’ll note that the permalink is the page id, so we’ll change that to use the post name instead.

Screen Shot 2014-12-18 at 4.16.28 PM

If we go to view a page, it will now use the page.php template instead of index.php.


Creating Custom Page Templates in WordPress

Here we want to make a new page template that has two columns, the left of which for nav. We’ll copy page.php and make a new file page-sidebar-left.php. Then at the top of the file, add a php comment with Template Name:. This tells WP this is our custom template.

Screen Shot 2014-12-18 at 4.22.37 PM

We’ll then copy over code from our static blog.html page. Note that the container elements are outside of the loop, and repeated elements are inside of it.

Screen Shot 2014-12-18 at 4.31.54 PM

Now that we’ve created this, we can go to a page in the admin section, and under templates on the right choose this template.

Screen Shot 2014-12-18 at 4.28.51 PM

Screen Shot 2014-12-18 at 4.31.38 PM

Now we can create and choose a custom template for each page!