Page components

In the last lesson, we looked at how to organize the files in a site. Now for another topic on site management: page components.

Most websites use the same page layout over and over. For example, the page you're looking at now has a menu at the top. Almost all pages use the same menu. They have the same footer as well. The lessons are on the left of every page. And so on.

There are hundreds of pages on this site. If I wanted to add something to the main menu, I'd have to touch every page, right? What a pain. Unless...

Maybe I could write the HTML for the menu once, and share it across pages. Hmm...

Regions

Here's the home page for Goatland. You can try it, and download it.

Goatland home page

It has three regions:

  • Top
  • Content
  • Footer

Regions

The two other pages, rides and tickets, have the same structure.

Here's the start of the code for the home page:

  • <!DOCTYPE html>
  • <html lang="en">
  •     <head>
  •         <meta charset="UTF-8">
  •         <title>Home | Goatland</title>
  •         <meta name="viewport"
  •           content="width=device-width, initial-scale=1, shrink-to-fit=no">
  •         <link rel="stylesheet" href="library/styles.css">
  •     </head>
  •     <body>
  •         <div id="top">
  •           <p id="site-name">Goatland</p>
  •           <nav>
  •             <a href="index.php">Home</a>
  •             <a href="rides.php">Rides</a>
  •             <a href="tickets.php">Tickets</a>
  •           </nav>
  •         </div>
  •         <h1>Welcome</h1>
  •         ...

Here's the code for rides. It's almost the same, with the differences marked.

  • <!DOCTYPE html>
  • <html lang="en">
  •     <head>
  •         <meta charset="UTF-8">
  •         <title> Rides | Goatland</title>
  •         <meta name="viewport"
  •           content="width=device-width, initial-scale=1, shrink-to-fit=no">
  •         <link rel="stylesheet" href="library/styles.css">
  •     </head>
  •     <body>
  •         <div id="top">
  •           <p id="site-name">Goatland</p>
  •           <nav>
  •             <a href="index.php">Home</a>
  •             <a href="rides.php">Rides</a>
  •             <a href="tickets.php">Tickets</a>
  •           </nav>
  •         </div>
  •         <h1> Rides </h1>
  •         ...

Injecting page fragments

Let's take out the head section, and put it in a separate file called, say, head.php.

  • <meta charset="UTF-8">
  • <title> ??? | Goatland</title>
  • <meta name="viewport"
  •   content="width=device-width, initial-scale=1, shrink-to-fit=no">
  • <link rel="stylesheet" href="library/styles.css">

Hmm. How about we make a folder called library, to keep things in. Put head.php there.

We can use PHP's require_once to insert one file inside another. So we could change the home page to:

  • <!DOCTYPE html>
  • <html lang="en">
  •     <head>
  •         <?php
  •         require_once 'library/head.php';
  •         ?>
  •     </head>

Cool! Do the same for the other pages, and head.php will be injected into every page. If we want to change the head part of every page, change one file, head.php, and be done! Even if there are thousands of pages on the site, change one file to change all pages.

Adela
Adela

What about that title tag? That changes for every page.

Oh, right. No problem. Change the home page to:

  • <!DOCTYPE html>
  • <html lang="en">
  •     <head>
  •         <?php
  •         $pageTitle = 'Home';
  •         require_once 'library/head.php';
  •         ?>
  •     </head>

The tickets page would have:

  • <!DOCTYPE html>
  • <html lang="en">
  •     <head>
  •         <?php
  •         $pageTitle = 'Tickets';
  •         require_once 'library/head.php';
  •         ?>
  •     </head>

Change head.php to:

  • <meta charset="UTF-8">
  • <title><?php print $pageTitle; ?> | Goatland</title>
  • <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  • <link rel="stylesheet" href="library/styles.css">
Ethan
Ethan

Cool! So in the page, set a variable. In the page fragment, output the variable.

Right!

We could do the same for the top and footer regions.

A template

I can make a template file, maybe called template.php:

  • <!DOCTYPE html>
  • <html lang="en">
  •     <head>
  •         <?php
  •         // Title for tab goes here. | Goatland appended automatically.
  •         $pageTitle = '';
  •         require_once 'library/head.php';
  •         ?>
  •     </head>
  •     <body>
  •         <?php
  •         require_once 'library/top.php'
  •         ?>
  •         <h1>Page title</h1>
  •         <p>
  •             Some killer content.
  •         </p>
  •         <?php
  •         require_once 'library/footer.php';
  •         ?>
  •     </body>
  • </html>

When someone wants to make a new page, they copy the template, and adjust it.

If we want to change the navbar across the site, edit top.php. To change the footer, edit footer.php.

Careful with the paths

PHPStorm gives me a warning about top.php.

Warning

top.php has a link to tickets.php. PHPStorm says it can't find tickets.php. But there it is, in the lower right of the screen shot, and the whole thing works.

Reflect

Why is PHPStorm giving that warning?

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Ethan
Ethan

OK, top.php has <a href="tickets.php">, so PHPStorm is looking for tickets.php in the same folder as top.php. That's the library folder.

But tickets.php is in the folder above the library folder.

That's right!

Ray
Ray

Wait, how come it works, then?

Georgina
Georgina

Oh! I get it. The code in top.php is never used by itself. It's injected into pages like rides.php, that are in the folder above the library folder. When top.php is injected, the links are right.

Correct! When you're writing code to be injected, write it so it works after the injection had happened.

Reuse

This is an example of the "management" part of MIS. Simply moving common code into separate files makes a site cheaper to maintain. Cheap is good.

Principle

Reuse

Reuse your code across programs, using functions and page components.

Reuse is a big cost controller. Look for ways to reuse what you're already done.

Job interview

This sounds good in a job interview: "I learned how to use page components to make sites cheaper and easier to manage."