Web Development: how to make a website

I get the feeling people don't really know what it is I did for 9 years at my previous job, even on the off-chance that they know where that is. "You made websites, right?" Essentially, sure. But I was a web developer and web programmer, not a web designer. (I'm not so good at graphical displays.) Also I made dynamic websites. That is, I made websites that displayed content that was editable by the users of the website. Specifically, they were database-driven.

My goal for this page is to go a little deeper into how I used BIND, Apache HTTP Server, PHP, and MySQL to do things that nonspecialists can't do. These tools only do so much. The particulars have to be configured and coded by hand. I want to distinguish between what was built-in functionality of the third-party software and what I did.

There is software — cPanel comes to mind — that does offer a graphical interface for all of this, but I want to describe the manual process underneath that layer. I address this a bit in the summary at the end.

The Pieces

web browser
DNS server

web server
database server

I'll use this website as an example for this discussion. Here are all the major pieces required to make this website function for you.

You're the user. You need some kind of web browser and a connection to an Internet Service Provider (ISP). The ISP, domain registrar, and the world's DNS servers are third-parties involved with the process. The company I worked for had its own DNS servers, web server, and database server.

The items in bold are what I manipulated to make a new website.

Domain name registrar

First, I want to own the domain, so I go to a domain name registrar to register the domain name. (This isn't actually owning but renting or reserving for a period of time.) There are many companies that act as registrars of domain names. I create an account on their website, enter the domain name I want, and pay to reserve that domain for a year or more. They ask me to enter in the two DNS servers that know absolutely where the web server is for my domain.

DNS name servers

A Domain Name System (DNS) name server is a computer that can translate a human-memorable domain name into an IP address. So when you type "theleif.org" in your web browser, a request is sent to a name server that can respond with "184.175.114.60", the IP address of the web server which hosts this website. Your web browser then makes the request to the web server at that IP address.

Since I set-up the name servers with the registrar, I now need to set up the name servers so they can respond with the correct IP address. They run BIND, the internet standard DNS software. I log-in to the primary name server ("dns1.example.com" for this discussion) via ssh. I navigate to the directory where the zone files are. These are the individual configuration files for each domain the name server knows about. I create a new zone file named "theleif.org" (can be any unique name) with these contents:

$TTL 1d
$ORIGIN theleif.org.

; Start of Authority
@ IN SOA dns1.example.com. admin.example.com. (
    2017052701 ; Serial (yyyymmddxx)
    12h        ; Refresh slave from master (good range: 20m-12h)
    3m         ; time between refresh Retries (good range: 3m-15m)
    2w         ; slave Expires as authority (good range: 2w-4w)
    1h)        ; the negative caching time - the time a NAME ERROR = NXDOMAIN record is cached (max: 3h)

; Name Servers
@ IN NS dns1.example.com.
@ IN NS dns2.example.com.

; Mail Exchanger
@ MX 10 mail.example.com.

; IPv4 Addresses
@      IN A 184.175.114.60
www    IN A 184.175.114.60
m      IN A 184.175.114.60
mobile IN A 184.175.114.60

At the bottom, you can see the IP address for the web server which will host the domain — "@" means "theleif.org" — and subdomains (www, m, and mobile).

I'm not done yet. I edit BIND's master configuration file to reference this new zone file. I include these lines in that file, which is in the parent directory of the zone files directory:

zone "theleif.org" {
        type master;
        file "zone_files/theleif.org";
};

At this point, I reload the BIND server's configuration files for my changes to take affect.

Web server

Now I want to deal with the actual web server and create a simple home page. I ssh to the web server and navigate to where I want my website's files to be. I create the directory and create a simple PHP file in it named "index.php":

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html;charset=utf-8">
        <title>Home page</title>
    </head>
    <body>
        <h1>My homepage</h1>
        <p>The date is <?php print date('Y-m-d'); ?>.</p>
    </body>
</html>

Then I navigate to where the Apache HTTP Server's configuration files are. (I should note that the web server has Apache installed with PHP. Apache will handle requests for web files and pass off execution of any requested PHP file to the PHP module.) I include this in the configuration file so that Apache will handle requests for my domain and know where the directory is on the server:

<VirtualHost 184.175.114.60:80>
    ServerName      theleif.org
    ServerAlias www.theleif.org
    DocumentRoot /my_website/home_directory
    ErrorDocument 404 http://theleif.org/error.php
    DirectoryIndex index.php

    <Directory "/my_website/home_directory">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

<VirtualHost 184.175.114.60:80>
    ServerName       m.theleif.org
    ServerAlias mobile.theleif.org
    DocumentRoot /my_website/home_directory
    ErrorDocument 404 http://m.theleif.org/error.php
    DirectoryIndex index.php

    <Directory "/my_website/home_directory">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

I restart Apache to reload the configuration file.

Database server

I now feel like I want a database to store some data that will be displayed on my home page, index.php. I ssh to the database server (named "database_server.example.com" for this discussion). (Actually, I always used graphical software called phpMyAdmin since it's so bothersome to type queries by hand.) I run MySQL from the command line and run queries to create the database (let's call it "MY_DATABASE_NAME"), create a table in the database (called "people" with fields "first_name" and "last_name"), add a user "MY_USER_NAME" with password "MY_PASSWORD" that my website's PHP scripts can use to access the new database, and insert some test data into the table that I can load while I develop the website. I conclude by running a query to reload the user access permissions.

Web server changes

Now that the database is set up, I ssh back to the web server. Well... what I actually do is fire up Aptana Studio for file editing. Then I securely FTP my changes to the server. So here are the changes I make to load data from the database table I just created:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html;charset=utf-8">
        <title>Home page</title>
    </head>
    <body>
        <h1>My homepage</h1>
        <p>The date is <?php print date('Y-m-d'); ?>.</p>

        <p>The data in the table:</p>
        <ul>
<?php
$connection_id 
mysql_connect("database_server.example.com""MY_USER_NAME""MY_PASSWORD");
mysql_select_db("MY_DATABASE_NAME"$connection_id);
mysql_query("SET NAMES 'utf8'"$connection_id);
$result mysql_query("SELECT first_name, last_name FROM people"$connection_id);
$count mysql_num_rows($result);
for(
$i=0$i<$count; ++$i) {
    
$row mysql_fetch_row($result);
    
$first_name $row[0];
    
$last_name $row[1];
    print 
"<li>$first_name $last_name</li>\n";
}
mysql_free_result($result);
?>
        </ul>
    </body>
</html>

This is the essence of the database interaction. It's actually a bit more abstracted with some PHP classes that wrap up the functionality of the database connection and querying along with some error handling (because errors will occur and I need to know about them).

404 Errors

If you request a file that doesn't exist on the web server, I want a graceful error page to display in your web browser. I've already set this up above in the Apache configuration file with the line: "ErrorDocument 404 http://theleif.org/error.php". So all I need to do is create a file called "error.php" in my home directory alongside index.php and edit it to display what I want you to see.

Redirect requests when file name changes

Let's say I used to have a file called "donkey.html" and I renamed it to "donkey.php". Everytime you request the web server for "donkey.html", you'll just get my 404 "file not found" error.php page. What I want to do instead is redirect you to the new file "donkey.php" and let you know that it's been renamed.

In my website home directory, I create a file called ".htaccess" that Apache will use for extra processing during the file request. Here are the contents I put in it to solve this problem:

<IfModule mod_rewrite.c>

    #--- turn on mod_rewrite engine
    RewriteEngine on

    #--- old pages
    RewriteCond %{REQUEST_URI} ^/donkey.html [nocase]
    RewriteRule ^(.*)$         /donkey.php [redirect=301,last]

</IfModule>

This comes in handy with search engines to tell them to change their search results for my donkey page.

Mobile website

My website is viewable on mobile devices, but I want to make sure mobile devices get sent to the mobile site when requesting files from the full site. I edit my .htaccess file to include this in the "IfModule mod_rewrite.c" section:

    #--- test for mobile devices
    RewriteCond %{HTTP_USER_AGENT} (nokia|symbian|iphone|blackberry|android|ipod) [nocase]
    RewriteCond %{HTTP_HOST}   !m.theleif.org [nocase]
    RewriteCond %{REQUEST_URI}  (\.php|\.html|^\/$)$ [nocase]  # don't redirect if resource is not php or html file or directory index
    RewriteCond %{QUERY_STRING} !full=yes [nocase]             # don't redirect if passing request for full site (happens when referer is not full site)
    RewriteCond %{HTTP_REFERER} !theleif.org [nocase]          # don't redirect if referer is full site
    RewriteRule ^(.*)$ http://m.theleif.org/$1 [redirect=307,last]

SOPA/PIPA protest of 2012-01-18

What about January 18, 2012, when I wanted to protest SOPA and PIPA by taking down my website? Well, I again edit the .htaccess file to include this in the "IfModule mod_rewrite.c" section:

    #--- SOPA/PIPA protest of 2012-01-18
    RewriteCond %{TIME_YEAR} 2012
    RewriteCond %{TIME_MON} 1
    RewriteCond %{TIME_DAY} 18
    RewriteCond %{REQUEST_URI} !/sopa-protest.php [nocase]
    RewriteRule ^.*$ /sopa-protest.php [last]

All file requests were sent the results of the "sopa-protest.php" PHP script.

I won't go into all the things I can do with .htaccess (and mod_rewrite), but it's a lot. It's powerful stuff.

Automated scripts

Let's say I want to receive an email every morning at 6:00 that includes the full list of people in my database. I can do that by setting up cron on the web server. On the web server (command line via ssh), I run "crontab -e", which allows me to edit the configuration for this job scheduler. I add this line:

0 6 * * * /usr/bin/php /my_website/cronjobs/email_list.php

Next I'll need to create and edit the PHP script "/my_website/cronjobs/email_list.php" to connect to and read from my database and send me an email. cron will make sure the PHP script will execute every morning at 6:00. There are some minor details to take care of, but that'll do it.

Summary

If you've managed to read all of this, I'm sure I didn't give away any secrets that now make you want to create and maintain your own website. It's not something everybody will want to do. What I did want to impress upon you is how much is involved with creating a website. The part of the process that takes by far the most time is of course the creating and editing of the PHP files.

Now, there are easy ways to maintain a website if all you want is a CMS or a blog. WordPress is by far the most popular free software right now that'll do just that. There are even free modules you can install that can extend the functionality of your website. Much of the website-creating business these days is commoditized. It's really only the graphics and unique features that still require professionals.