When I first wrote this column back in January 1999, I had no clue
that it was going to be so wildly popular, and I had even less of a clue
that PHPBuilder was going to take off and become as widely-used as it
is today.
Since this topic seems to be so important to a wide range of developers,
I'll revisit it in more detail, sharing more bits of code with you.
Almost any developer knows that search engine placement is
critical to the success of a web site. What many people don't
know is that a lot of search engines cannot index many database-driven
pages (basically any page with a '?' or '&' in the URL).
So when I set about building
gotoCity.com, one
of my goals was to make the site database-driven, but still indexable. I didn't want
any use of cookies or mile-long URLs, and I wanted useful, context-sensitive
meta tags to be generated from every page quickly and with no effort on my part.
More importantly, the method shown here actually works. My Gotocity.com
web site was getting up to 150,000 page views per day just from search engines
alone. That's more than enough to crush a web server.
To pull this off, I started with a subtle Apache feature that can "force" a
script to be called for any certain directory tree. In my case, I wanted all
URLs that fall under "/local/" to call a script. This would be MUCH easier
than creating 200,000 localized web pages and a genuine directory
structure to match it.
This forces every request that starts with "/local/" to call a script called
"local" (just "local", not "local.php3") in the
$DOCUMENT_ROOT (usually called "/htdocs/")
of your server. "local" then uses PHP to parse the URL and act accordingly.
The code for my "local"" script is on the last page of this article. You can of
course replace "local" with any filename you want, as long as you change your
httpd.conf accordingly.
Sample
.htaccess file:,/div>
<Files local>
ForceType application/x-httpd-php3
</Files>
Removing the '?' and '&' from the URL string is a necessary first step, and it's
sufficient for many tasks. However, you can take it further by having context-sensitve
meta tags generated on the fly for every page.
When I build a site, I create a common library that is include on every page
throughout the site. You can call this file shared.inc or whatever.
Shared.inc sets up the database for me, and, more importantly, contains a function call
for the header and footer of the site.
<?php
//sample shared.inc file
//set up database connections
//any global variables for background
// colors or path names
function site_header($title) {
//contains common HTML
//for the header
}
function site_footer() {
//contains common html
//for the footer
}
?>
You would then call site_header() and pass in the page title for each page. That's exactly how
PHPBuilder works.
If you have an architecture like this, all of a sudden you can do some really slick
things in site_header(). Not only can I create the standard HTML header/title/body tags,
but I can create meta tags using the $title string.
Let's go into more detail now:
<?php
//sample shared.inc file
//set up database connections
//any global variables for background
// colors or path names
function site_header($title) {
//contains common HTML
//for the header
echo '<HTML>
<HEAD>
<TITLE>PHPBuilder.com - '.$title.'</TITLE>';
//set up metatags
//take out "the", "and" and "a"
//a truly gifted developer would use
//a great Regular Expression here
$keywords=str_replace("the ",'',strtolower($title));
$keywords=str_replace("a ",'',$keywords);
$keywords=str_replace("and ",'',$keywords);
$keywords=str_replace("\"",'',$keywords);
//make the string comma-separated
$meta_array=explode(' ',$keywords);
$meta_words=implode($meta_array,', ');
echo '
<META NAME="KEYWORDS" CONTENT="PHP, '.$meta_words.'">
<META NAME="DESCRIPTION" CONTENT="PHP Developer, Web Developer, '.$title.'">
';
echo '</HEAD>
<BODY TEXT="#000099" BGCOLOR="#FFFFFF">';
}
function site_footer() {
//contains common html
//for the footer
echo '</BODY></HTML>';
}
?>
There, now the site_header() function prints out the usual stuff + meta tags that are built
from the $title string that you pass in. For best results, use a descriptive title on your pages.
On the next page, I'll show you you how to use the URL string to create a hierarchy.
The following code is what I used in the construction of
Gotocity.com. My goal was, as I mentioned, to eliminate all
'?' and '&' characters from the URL. I wanted to drill down
from the general (country, in this case the US) to the specific
(a given topic page in a given city in the country specified).
Fortunately, all cities in the US are given a unique identifier, a
ZIP code, and each city also resides in a state. So you can drill
from Country -> state -> city -> topic page in a logical fashion.
The important thing to note is that, if you're viewing a "country" page,
then the 'state' won't be present in the URL. If you're viewing a 'state'
page, both 'country' and 'state' are in the url, so you can use both
as criteria when you select from the database.
The URL string is set up in a global variable called $REQUEST_URI. All
you have to do is examine the string and figure out where you're at. I do
that by explode()'ing the string using the / separator.
<?php
/*
Sample URLs:
/local/2/us/IA/a/50613/apartment/ - apartments in Cedar Falls, IA
/local/2/us/IA/a/ - group of cities in Iowa
/local/2/us/ - States in the US
/local/1/us/IA/a/50301/ - Des Moines City.net
*/
$url_array=explode("/",$REQUEST_URI); //BREAK UP THE URL PATH
// USING '/' as delimiter
$url_affil_num=$url_array[2]; //Co-Branding info
$url_country=$url_array[3]; //Which Country?
$url_state=$url_array[4]; //Which State?
$url_alpha_state=$url_array[5]; //Cities starting with a-g
$url_zip=$url_array[6]; //If present, build thispage
$url_content=$url_array[7]; //If present, build a sub-
// page for this city
/*
separate includes were designed to fetch the affiliate cobranding
and build appropriate style sheets on the fly. Data validation is
done prior to each query. If a URL is incorrect, bow out gracefully
or redirect home
*/
if($url_zip) {
/*
If present, query the Zip code database and build the page.
Inside the city.inc, we will check for which "content page"
we are building, if any.
*/
} elseif ($url_state) {
/*
If URL PATH ends here, query Zip code database,
selecting DISTINCT cities in this state
*/
} elseif ($url_country) {
/*
If URL PATH ends here, query ZIP code database,
selecting DISTINCT states for this country
*/
} else {
/*
must be mal-formed. Redirect to home
*/
Header( "Location: http://db.gotocity.com/local/2/us/");
exit;
}
?>
There, now you have all the building blocks you need to create
useful, dynamic, AND search-engine friendly web pages by the millions.
--Tim