In this article, we’ll
build a simple, template-driven site that separates style, content,
and structure in your website. We’ll create a cross-browser
stylesheet switcher that remembers the user’s preferences,
touching on php variables, cookies, if statements, and including
pages with require once.
Separating style, content, and structure
The separation of style from content has become the bugbear of
the HTML developer. Traditionally, we’ve used well-written
CSS and XHTML to achieve this separation, and we’ve seen how
much easier it is to update our sites or provide multiple styles
when we write our markup this way. By adding some very basic PHP
to this mix, we can take this modularity a step further, making
it easier not only to update our styling, but our structure as well.
In essence, we can create our own basic Content Management System.
PHP is an open-source server-side language. In order to use PHP,
you will need the PHP module installed on your server. Most Linux
servers have this module installed, and the PHP module is also available
for Microsoft servers. If you are unsure about your server or modules,
just ask your web host.
Essentially, the master template will use XHTML for structural
markup, CSS for style, and some basic PHP to manage it all. Some
very basic work with PHP variables will give us multiple style sheets,
and will allow us to display different content documents within
the same template. Since PHP is a server-side language, all the
fancy work is done at the server, before the browser ever gets a
peek, so this approach makes cross-browser support much easier to
acheive.
Client-side languages like JavaScript do their work on the client—the
browser—so the success of a page built with JS depends on
the quirks of the individual browser. Since the browser never sees
any PHP, just the flat XHTML results of the PHP, we don’t
have to worry about a browser supporting PHP.
We’ll use a fairly typical site structure: menu + content.
Start the page as you would any HTML page: build the “<html>…
<head>…</head>… <body>…”
shell, and within the body set out your div tags to identify the
structure of your document.
<div class="body">
</div>
<div class="menu">
</div>
require_once()
Now we’ll use some basic PHP to include the content. require_once
‘includes and evaluates the specified file during the execution
of the script’. In other words, it inserts another file into
the document and evaluates the contents of that file for any scripts.
The once aspect is a safeguard to ensure that we don’t include
the file multiple times, which can cause problems like resetting
our variables.
However, require_once() only works in the more recent versions
of PHP, so if you have a module older then PHP4 installed on your
server, you would need to use include() or require() instead.
<div class="body">
<?php @ require_once ("body.html"); ?>
</div>
<div class="menu">
<?php @ require_once ("menu.php"); ?>
</div>
Placing the @ symbol before require_once suppresses any error-messages
that might be triggered in the included file. You see, PHP has some
default error-messgaes, which can be incredibly useful during development.
However, they’re not the sort of thing we often want our users
to be staring at. By inserting the @ symbol before a function, we
can suppress those error-messages. In many cases, custom error handling
would probably be the best solution, but for this article we’ll
keep it simple and just suppress them.
Since we are using PHP in this file, we have to save it as a PHP
document, so let’s save it as template.php. You may have noticed
that menu is also a PHP document, while body is an HTML document.
This is because menu is going to parse some PHP variables, while
body will be nothing but text.
Now we have a page that calls in two separate documents, menu.php
and body.html, and inserts the contents of those files into the
page before showing it to the browser. Since these two files will
be included within the body of this existing shell, there is no
need for <html> <head> or <body> tags in these
two files—just pure content.
Switching content with PHP variables
So far, we have separated the structure of our template from the
content that will be inserted into that structure, but as everything
is hard-coded, this is still a static page. Some basic PHP variables
will allow us to use this single structure as a template from which
we’ll call different content files. If you want to change
the structure of your site down the line, you need only update this
one document, and your entire site will reflect those changes.
Let’s say we’re building a site about French Communists.
We want the basic structure and design to remain the same, but we
want to include different chunks of content depending on which communist
the user wishes to learn about. So, rather than have two separate
pages with redundant markup and structure (babeuf.html, and picasso.html),
we use one master PHP document to host the separate chunks of content.
The menu will stay the same for every page, so we can keep the
menu.php hardcoded, but as the body will be changing we’ll
need to use a variable to give us a way to reference these changes
dynamically.
PHP variables can be identified by their preceding $. So, we can
change the hard-coded body.html into a dynamically updateable variable
by coding it as $page.html. Every reference to $page will be replaced
by whatever we set the variable $page to be.
Change the body reference to:
<div class="body">
<?php @ require_once ("$page.html"); ?>
</div>
We’ll set the variable in the query string (everything that
comes after the "?") of the url: template.php?page=babeuf.
The code above will replace any instance of $page with babeuf,
so $page.html becomes babeuf.html. If we want to call picasso.html
into that same template, we would set the Picasso link in our menu
to template.php?page=picasso.
Along this line, if you run a blog, you can set your blog to output
nothing but content, and build a PHP shell that will insert the
proper page. This will give you one page of structure and markup
in which all the different archives can be included. template.php?page=blogger
or template.php?page=2002_02_01_archive. Redesigning your site involves
updating one PHP page and your style sheets, and every archive will
be updated automatically. (Ed. – See ALA’s Slash Forward
to find out how to use mod_rewrite to create user-friendly URLs
in just this sort of situation.)
Minimizing included pages
Creating a system that assembles our final document out of several
pages enables an extremely modular site, but each require_once()
requires a little extra time on that server, as we load another
separate file into our document. So, it is always a good idea to
keep the number of included pages down to a minimum. Since menu.php
is hardcoded — it never changes as we always ask for the exact
same file — we actually could just enter our menu directly
into the template. That would save one require_once, gaining the
time the server would spend locating and inserting the appropriate
document.
We could achieve more flexible results with a database query while
limiting the number of separate calls, but to maintain the simplicity
of this example, we’ll keep it as is for this article. Besides,
I am still frightened of databases.
There is always a balance between ease of code and ease of maintenance,
and between speed of coding and speed of loading. As always, test
different versions in multiple circumstances to find what works
best for your site, and don’t be scared of databases.
Anyway, now we’ve got a single page for structure, which
can include many different chunks of content. You refer to the style
sheets as you would any other XHTML document, from within the <head>
of template.php.
Switching style with PHP variables
But what if we want switchable styles as well as content? To do
this with PHP, we’ll just use another PHP variable; let’s
call it $style. In the head of template.php, add:
<?php echo "<style type=\"text/css\"
media=\"all\">@import
\"$style.css\";> </style>"; ?>
echo functions a lot like JavaScript’s document.write(),
writing everything between the quotes into the source of the document.
Since the content we are writing into the source contains quotation
marks, we need to let the server know which quotation marks we want
it to write as punctuation, and which ones are there to identify
the stuff we’re printing. Typing a \ before the quotation
mark will make the server print the quotation mark as a quotation
mark.
So, if we set the variable style to “default” in the
query string like this: template.php?page=babeuf&style=default,
the code above will print out:
<style type="text/css" media="all">@import
"default.css";> </style>
We can change styles on the fly by changing the variable style
so that it will match to an alternative style sheet (template.php?page=babeuf&style=print).
And since all the busywork is happening on the server, these alternate
style sheets will function on any browser that supports CSS.
Note that the raw ampersand (as in page=babeuf&style) is not
standard XHTML, so before you upload your files, be sure to global
replace every instance of & with & within links. It
will still render properly in the links. For clarity’s sake,
I will keep the ampersands raw in this tutorial (as I do while I
code as well), but remember to encode them before uploading. The
exception to this rule is for instances that never reach the browser,
like redirects, but we will cover that later.
However, there is a shortcoming to this solution. Since we do all
this style sheet manipulation with PHP variables, the browser has
no idea that there are alternate style sheets. In other words, the
Mozilla menu option for switching style sheets will show the current
style sheet as the only option.
As the other browsers will soon follow suit to offer this feature,
and as this is the W3C-suggested method for using alternative style
sheets, let’s alter our code so that it will work nicely with
future browsers, without sacrificing compatibility with the old
ones.
Add the following after the existing style sheet reference:
<?php echo "<link rel=\"alternate
style sheet\"
type=\"text/css\"
href=\"print.css\" title=\"Printable\" />";
?>
<?php echo
"<link rel=\"alternate style sheet\"
type=\"text/css\"
href=\"default.css\" title=\"Default\" />";
?>
Now we have a cross-browser style sheet switcher that takes advantage
of the latest alternate style sheet features as well. If we set
the $style variable as well as the $page variable in each query
string in menu.php, then the user’s selected style will be
maintained throughout their visit.
For instance, the link in to the section on Babeuf would be:
<?php echo "<a href=\"template.php?page=babeuf&style=$style\">babeuf</a>";
?>
This parses the existing $style variable as well as the new $page,
keeping the style consistent while changing the content.
If we wanted to maintain the content and just change the style—say,
to a printable version—then we’d do the opposite, maintaining
the content by passing the existing value for $page, and changing
the value of $style.
<?php echo "<a href=\"template.php?page=$page&style=print\">
Printable version</a> "; ?>
Saving the preferred style with PHP cookies
You can even maintain the selected style between sessions with a
PHP cookie. PHP cookies are incredibly easy to set. The basic format
is:
setcookie ("cookie name", "cookie value", time()+how
long you
want the cookie to last); ?>
So if we want to set a cookie called “styleCookie”
that stores the user’s selected style (the $style variable),
we would type the followingat the very top of template.php:
<?php
setcookie ("styleCookie", $style, time()+40000000);
?>
This will save a cookie called “styleCookie” on the
user’s computer with a value of whatever $style is currently
set to, and keep it there for a little over a year.
When the user returns to the site on another visit, we need to
pull up that cookie and set $style to that value. The easiest way
to do this is with a redirect page. Even if you don’t want
to mess about with cookies, it is a good idea to use a redirect
page if you want users to get to this page from the root of your
site. Without a redirect page, in order to reach the Babeuf page
hypothetically sitting at FrenchCommunists.org, the user would have
to enter www.FrenchCommunists.org/template.php?page=babeuf&style=default.
That’s quite a url-ful. So if we save a redirect page at
index.php that sends the user to this url + query string, all the
user needs to type to access the proper page is www.FrenchCommunists.org.
PHP redirects
A straightforward PHP redirect would look like this:
<?php Header ("Location:
http://www.FrenchCommunists.org/template.php?page=home&style=default");
?>
Note that as this PHP is never read by the browser, we can keep
the & raw, and it will still validate as XHTML. In fact, if
we change it to & the server will choke. So, in any case
where the browser is doing the parsing (as in <a href), it is
okay to switch the & to &. When the server is parsing
it without the browser, keep it raw. If you’re confused by
this, a little trial and error with the XHTML validator will clear
things up.
Also note that as this is not an XHTML page, we don’t need
the typical <body> <head> structure; a file containing
nothing but the redirect will do just fine.
The cookie parser
If we added a cookie parser at the redirect page (index.php),
it would look like this:
<?php
<if ($styleCookie == "") {
< $style="default";
<}
<else {
< $style=$styleCookie;
<}
<Header ("Location:
http://www.FrenchCommunists.org/template.php?page=home&style=$style");
<?>if statements in PHP are very similar to if statements
in JavaScript or ActionScript. The basic format is:
if (this is true) {
<then do this
<}
<else {
<otherwise do this
<}
In our case, we first need to check if $styleCookie equals nothing
(it hasn’t been set).
if ($styleCookie == "") { If the cookie doesn’t
exist (the user has never visited before or prefers not to accept
cookies), then we set the style to default:
<$style="default";
<}If the cookie does exist (it doesn’t equal nothing),
then we set $style equal to the $styleCookie:
else {
< $style=$styleCookie;
<}Regardless which if statement was parsed, $style now has a
value, so we can use the same redirect to bring us to the appropriate
page:
Header ("Location:
http://www.FrenchCommunists.org/template.php?
page=home&style=$style");
This index/ redirect document declares the default values for all
of our variables if they have not already been set. But just in
case someone manages to bookmark the template page instead of the
index/redirect, we really should declare default values in our template
as well. That way, if some calls template.php directly, without
specifying any variables in the query string, we can still build
a reasonable page for them.
Back in template.php, underneath the setcookie script, add:
<?php
<if ($style == "") {
<$style="default";
<}
<if ($page == "") {
<$page="home";
<}
?>
The syntax should look familiar to you now. This will set default
values for our two variables if they do not already have values.
So, a person skipping the redirect document and asking for http://www.FrenchCommunists.org/template.php
will effectively be given http://www.FrenchCommunists.org/template.php?page=home&style=default.
And there you have it: separating style, content, and structure.
We’ve created template.php for the structure, and into that
master document we’ve brought our separate style sheets and
content files. We used PHP variables and require_once to insert
the appropriate content and style, and did it in a way that takes
advantage of the latest style sheet-switching properties of current
browsers, while also giving this ability to older browsers. Finally,
using PHP cookies and a redirect, we made the site remember the
user’s preferred style sheet.
|