picture of Tim Perdue
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.
So in Apache's httpd.conf file, I added the following lines:
<Location /local>
ForceType application/x-httpd-php3
</Location>
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.
Now if you don't have access to your httpd.conf file, you can also try the <files > directive in a .htaccess file. Hundreds of people ran into this stumbling block in the past 16 months. It appears that this method only works on Linux, as people are reporting trouble on FreeBSD and Windows. If you find an .htaccess solution on Windows, let me know.
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