Web Developers: February 04, 2004

Get Thawte's NEW Step-by-Step SSL Guide for Apache

In this guide you will find out how to test, purchase, install and use a Thawte Digital Certificate on you Apache web server. Throughout, best practices for set-up are highlighted to help you ensure efficient ongoing management of your encryption keys and digital certificates. Get your copy of this new guide now.

GNOMEREPORT: Major Milestones Approacheth

So did you feel the wrath of myDoom? I know I sure did, both at work and home. Now personally I didn't get the virus, but the networks I am on got quite a healthy hit of the traffic. I'm pretty sure work stayed clean for the most part, but I can't say the same for my home ISP.

So today is the 4th or 5th, depending on when you are reading this. That means 10 days to Valentine's Day (have you sent your e-cards yet?) and 18 days till my birthday! Another year, another wish list, another cake, and the start of another countdown. I'll be 28 this year, so I'm not hitting any major milestones but I'm getting there.

Speaking of wish lists, I got a nice package a few weeks ago from someone who wanted to thank me for some work I've done in the past. It's so nice when you set out to help people and they turn around and surprise you with a thank you like that. This is a good business lesson for all of you out there, unless you've read the Web Design Business Kit. When you get a referral for some work, be sure to send at least a thank you card to the person who provided you the lead. Even if the lead doesn't pan out, the "thought" you've provided will be worth something to the referring person. Then if something does come about, be sure to extend your thank you with a small token of your appreciation. The next time this person goes to refer someone for work, you'll be high on their list because you took the time to acknowledge their efforts.

Digitally Yours,
Eric Jones

TALK: CMS Talk, Shout, And Lessons Learned

Yes, I know TALK is usually towards the bottom, but I got a ton of feedback from last week's PROJECT; I just had to pass it all on. So instead of posting it at the bottom where some of you might catch it, I'm bringing it to the top so that most of you, more than likely, will catch it.

First off, Gnomie Bruce has a great explanation as to why ID keys should be numbers versus text:

Hi, Eric! In your project article on CMS you make the following statement - "I've set the ID field as the primary key, but you could use the e-mail if you wanted to. Personally, I like using ID fields over text; it's easier to manage and work with."

Perhaps this is not enough explanation for new users since you didn't tell them WHY it is 'easier to manage and work with.' It is not just because of 'text' - it is because the 'text' almost always has meaning, meaning which is subject to change.

If you do not control your key field, then your keys are subject to change beyond your control - setting up an administrative nightmare. To continue with your example, let us imagine that your 'author' database now has 500 entries keyed by e-mail and your 'articles' database has 5,000 entries, of which 50 are linked to 'eric@lockergnome.com' and due to circumstances beyond your control, your e-mail address changes to 'eric_jones87@hotmail.com.'

When the 51st article is added, there are [a couple of] possibilities that arise:

  1. The new article is added without exception if the 'articles' database is not checking the 'author' database for a valid key
  2. The new article prompts for an 'author' database entry after a cross-check and the data entry person creates a new - duplicated - entry, or realizes that a problem exists and needs to be fixed.

If you own the key, you are probably doing a look-up by e-mail and/or name to find the arbitrary key you control in the 'author' database so it can be placed in the 'articles' database entry - so the realization that a problem exists is more likely to come to the attention of the person entering the data.

The first advantage is to make it easier to discover that there is a problem to be corrected, and, once this is known, there is a difference in the procedure to fix the problem. Where you control the key, the e-mail is simply an information field which is corrected in one place - the 'author' database, and the 51st article is added normally.

If e-mail was the key to the 'author' database, it is now incorrect in 51 places - one in the 'author' database and 50 times in the 'articles' database. So an extra program/script needs to be written to (typically) delete the old 'author' database entry and recreate a new entry with the new key, AND find and replace the old key everywhere it exists in the 'articles' database, AND insure that if the first action executes the second must execute also or raise an error condition so that no orphan records are left in the 'articles' database.

I think it's important to explain this to new programmers before they have created major administrative headaches for themselves - writing the code is the 'easy' part compared to knowing what code needs to be written.

This is also a good time to point out that the PROJECT is going to be built using PHP code and will talk to a MySQL database. So you will need to ensure your host has the ability to provide both of these to you, and you'll want to double check with them to see how you can administer your MySQL database. Most will provide you access to phpMyAdmin, while others might have a custom solution (or nothing at all).

If you need to find a good host within your budget, head over to the Lockergnome Forums and post your requirements (be sure to mention PHP & MySQL) and let the community point you in the right direction.

PROJECT: Functions Fantasia

First you need to visit and then bookmark these links:
PHP Documentation (pay attention to Chapter 5: Functions)
MySQL Documentation

Finally, be sure to review the past articles published to keep up with the rest of us. If you need a reference book to use and help you when in a time of need, I can't recommend anything more than Build Your Own Database Driven Web site Using PHP & MySQL by Kevin Yank. I've worn my book out from passing it around, and as much as I'd love to give you my copy, I don't think we could come up with a schedule to give everyone equal time.

Okay, now to coding! Last week, we talked a bit about SQL and we created a couple of tables in our database. We also inserted a couple of records to get us started. This week we are going to build the PHP functions which will allow us to accomplish a few tasks in our CMS.

So fire up your favorite editor and create a page called functions.inc.php.

This is the file where we will store all our functions for this project. Typically I'd create new files for each group of functions (one for authors, one for pages, etc.) but to keep things simple we are just going to keep it all in one page.

As we learned in a past issue, functions are pieces of PHP code we can use over and over again to accomplish certain tasks. I typically have 4 functions that I include with every php project. I can't take credit for the code, but a good friend of mine wrote them and they have stuck with me ever since.

function error( $msg) { ?><?="\n" ?><script language="JavaScript"> <?="\n" ?>alert("<?=$msg?>"); <?="\n" ?>history.back();<?= "\n"?></script> <?="\n" ?><?exit;}

The function error takes an error message and puts it into a JS pop-up. Very nice and neat for production sites.

The function alert will sent an alert message (typically debugging information) about a script again in a javascript pop-up.

function alert ($msg ) {?><?= "\n"?> <script language="JavaScript"><?= "\n"?>alert(" <?=$msg?>");<?= "\n"?></script> <?}

The function dbConnect is what I use to connect to a database. I set my variable at the top of my include page and then use this one function to connect to the database.

function dbConnect () {
    global
$dbhost, $dbuser, $dbpass, $dbname;
    
$dbcnx = @mysql_connect ($dbhost, $dbuser, $dbpass) or die( "The site database appears to be down.");
        @
mysql_select_db($dbname , $dbcnx);
    return
$dbcnx ;
}

All my query statements go through the dbQuery function. This just makes my code easier to manage and along with the debugging built in makes things easy to fix!

function dbQuery ($sql, $debug= 1){
     if(
$debug == 0){
         
alert( $sql);
    }
    
dbConnect ();
    
$result = mysql_query ($sql);
    if(!
$result ){
        
error( "An error occurred while processing your request, please try again. If this error continues, please contact the site admin.");
    }
    return
$result;
}

So now we need to create a function you can use. Let's create a very simple function which will pull out all the articles in our database.

function get_all_articles (){
    
$sql = "select * from articles";
     
$result = dbQuery( $sql);
    return
$result;
}

The function get_all_articles uses the dbQuery function to send the SQL call select * from articles to our MySQL database. The line return $result; tells PHP we want this function to return the variable $result which is just a query string. Now if you were to just output this variable as is it's going to break. You need to setup some login in you pages so you can out put each bit of data one at a time.

I accomplish this with a for loop. Remember, a for loop is a way that we loop though a dataset an array, query string, etc. and output it to the screen.

Let's create another page. Call this one article.php. It is here that we will call our function and produce some output.

The code for this page will look something like this:

<?
//ensure we include our functions.inc.php file
include( "functions.inc.php");

//First we need to call our function

$article_query = get_all_articles();

// now we can loop through all the rows

for($i= 0; $article_output=@mysql_fetch_array ($article_query );$i++){
?>

Article ID: <?=$article_output["id" ]?> <br />
Title: <?=$article_output[ "title"]?> <br />
Author: <?=$article_output ["author_id"] ?> <br />
Synopsis: <?=$article_output["synopsis" ]?> <br />
Body: <?=$article_output[ "body"]?> <br />
Stamp: <?=$article_output ["stamp"] ?><br /> <br />
<?
}
?>

Now this code will loop through our query string and for each record it will output the id, title, author id, synopsis, body and time/date stamp.

But wait, Eric, where did you get the variable $article_output and $article_query? Well the $article_output is our reference variable. It is what we use to refer to a particular item in a row. The $article_query is the variable we used to reference our function.

Now the above code assumes you are keeping the functions.inc.php and articles.php files in the same directory. If you put the functions.inc.php into another directory, your include line needs to have the complete server path to the file. Something like:

include('/wwww/mysite.com/includes/functions.inc.php');

If you don't know the full path, check with your hosting company to see if they can't help you track it down.

Now what if you want to get just one article and not all of them? Well then you would need a function that would grab a select article and return its data.

<?

function get_article ($article_id ){
    
$sql = "select * from articles where id = $article_id";
    
$result = dbQuery($sql );
    
$row = @mysql_fetch_array ($result);
    return
$row ;
}

?>

This function takes a number which is hopefully the same as the id of one of our articles and grabs all the data associated with that ID. Now before, when we output this text, we had to loop through the returned result. But you'll notice this time that we have a new variable called $row which already grabs the data. So this time when we output, we just need something like this.

Create a page called singleArticle.php

<?
//ensure we include our functions.inc.php file
include( "functions.inc.php");

//First we need to call our function

$aid = '1';

$article = get_article( $aid);

// now we can loop through all the rows

?>

Here is the article you requested:

Article ID: <?=$article ["id"] ?> <br />
Title: <?=$article["title" ]?> <br />
Author: <?=$article[ "author_id"] ?> <br />
Synopsis: <?=$article ["synopsis"] ?> <br />
Body: <?=$article["body" ]?> <br />
Stamp: <?=$article[ "stamp"] ?><br /> <br />

So now you've seen a couple of functions working for you. If you want to see the code in full, check out these files:

functions.inc.php
singleArticle.php
articles.php

Be sure to grab the functions.inc.php file as it has two more functions. They are the same as above, but for authors. So give them a download and see what you can do with them.

NET: A Library For Web Developers

Gnomie Daniel shot me this great link: The Web Developers Library. This site is chock full of information presented in a no-nonsense format. As soon as you hit the main page you'll see what I mean. Very few ads and content, content, content galore! Just take a gander at that menu system on the left; there are more topics there then in most college lectures!

I spent a bit of time browsing around the site and found a lot of the code to be great. Not only is it useful but it's presented in a way everyone would be able to follow along with. So if you're doing ASP, PHP, XML, or HTML, I'm sure you'll find something here to help you along the way!

Explore a world of untapped information!

Thousands of web sites offer their content as RSS newsfeeds, but accessing this information has been cumbersome at best.

Until now, that is.

FeedDemon enables you to quickly explore the world of RSS from your desktop without having to visit hundreds of sites. Written by Nick Bradbury, creator of TopStyle and HomeSite, FeedDemon makes RSS as easy to access as your email.

Get hooked in today!

NET: Whois This Is?

By Pat Wong

Recently, I received an unwanted phone call at work from someone with whom I had agreed to trade music CDs a few months earlier. To make a very long story short, I sent him the CD I owed him, but he did not reciprocate. When I fought back by including his name and city/state on a bad trader page on my Web site, he responded by sending me several threatening e-mails, which culminated in the above mentioned phone call. He wouldn't tell me at the time how he got hold of my work number (I certainly didn't give it to him), but I'm almost certain that he got it from the Whois database.

So what is the Whois database? Here's what Network Solutions says about it:

"The Internet Corporation for Assigned Names and Numbers (ICANN), the nonprofit body responsible for accrediting domain name registrars, requires all accredited domain name providers (including Network Solutions) to make your contact information publicly available."

That includes your e-mail address and whatever snail address you supplied when you registered your domain. If that happens to be your home address, then literally the world can find out where you live.

While Network Solutions and other domain registrars have led the way in trying to eliminate these requirements, the most effective means of ensuring your privacy is something you can do yourself, making the registration of your domain private. There is a nominal fee involved to do this, but once done, anyone who tries to access your personal information via Whois will instead be directed to send snail mail inquiries to a proxy address concerning your domain. Your e-mail and snail addresses will no longer be made available for the world to see, and will remain private.

Considering how small the fee is, private domain registration is definitely worth the expense. Don't think you need to go that far to protect your privacy? Neither did I until my privacy was violated.

MAC: 15" Aluminum PowerBook G4

By Scott Bradach

I am sure you all have seen Apple's 17" Aluminum PowerBook G4 by now: The sleek look, the backlit keyboard, and the oh-so-beautiful screen. But let's face it, that thing is just BIG. So when my quest for a new PowerBook started, (and I had the money saved) the first thing I looked at was the Big 17. Did I mention how BIG that thing is? As cool as it is, and all the great amenities it has built in, I just couldn't justify the size. Enter the new 15" Aluminum PowerBook G4. I had heard rumors of a re-design on the 15" PowerBooks, but nothing I thought of could compare to the new machines.

The model I have is slightly customized. I upgraded to the 1GB of memory (upgradeable to 2GB for an extra $1200), and added the 80GB 5400 RPM hard drive (rather than the 4200 that ships standard). Other than that the specs are basically the same as standard: 1.25 GHz PowerPC G4 processor with 512K L2 Cache, (the base ships with a 1Ghz), 15.2-inch TFT Display (1280x854 resolution) , 1GB DDR333 SDRAM (the base has 512MB) 80GB Ultra ATA/100 hard drive, an ATI Mobility Radeon 9600 (64MB DDR), a backlit keyboard, Gigabit Ethernet, FireWire 400 & 800, USB 2.0, AirPort Extreme built-in, and DVI & S-Video out.

If you have seen the new 12" and 17" models, the new Aluminum case design is nothing new. But it feels SOLID... even more so than my older TiBook. The basic dimensions are the same as on the old model, but the corners are rounded in an aesthetically pleasing manner. If you thought the old TiBook was a work of art, it will look archaic next to the new PowerBook.

The heat issue while sitting on your lap for an extended period isn't bad, but it does get warm to the touch. If you are the type to compute in your underwear, you will find this out soon enough. If you use your PowerBook on a desk, I would recommend getting the iCurve or a comparable laptop stand for the machine, as it will help with the heat immensely. I am sure that Apple has taken all of this into consideration with the design. But, in my opinion, given the investment, it is better to be cautious than sorry.

The new PowerBook ships with all of the connections you need on the sides of the unit (same as with the iBook and new 12" and 17" units). On the left side you have Power, Modem, one of the two USB ports, Audio in and out, and the PC Card slot. On the right, DVI out, S-Video, Gigabit Ethernet, FireWire 800, FireWire 400, the other USB port, and a cable lock connection. All nicely convenient compared to the old TiBook's rear connection and door.

The speakers on the new PowerBook deliver rich sound and have a decent volume range. Compared to my old TiBook, and other Wintel laptops, I think this is one of the best sets of speakers I have heard. While not desktop quality, they are more than adequate for music or DVD playback.

The best part of the new PowerBook is the backlit keyboard function. With my old TiBook, I used an external USB LED light in dark situations. With the new backlighting, it is totally unnecessary. The room can be completely dark with no loss of functionality. And it looks damned cool, too!

I only have one minor complaint with the latch on the new machine. I did some searching on Apple's forums and knowledge base to find that I am not alone in this gripe. The latch does not seem to stay closed when you either pick it up or have it in a laptop bag. This has happened to me on several occasions, and is annoying to say the least. The fixes on the Apple Forums range from sending it back to Apple for a repair, to Do-It-Yourself fixes (I won't relay those DIY fixes here, as you do it at your own risk). Others issues I have read about pertain to dead pixels on the LCD. I don't have this on my unit, but there were several threads regarding this. Many are suggesting that you buy from your local Apple store (or authorized reseller) and to open and check before purchase.

I don't know if it is possible to fall in love with a computer (or even to admit that in print) but I think I am close. Apple's facelift to the new 15" PowerBook, both aesthetically and technically, was much needed. And, in my opinion, a huge success and nice alternative to the sheer size of the 17" PowerBook. It has all the amenities without the desk (or lap) real estate.

As an aside, I had to send the PowerBook back to Apple due to a video problem. I sent it in via Airborne with the box provided by Apple on Monday of this week... I got it back and fixed TODAY... I am damned impressed!

WARE: FrontPage Plug-ins

For all you FrontPage users out there, Gnomie Dennis has a site you should check out. D2Stuff.com has some great FrontPage plug-ins to help you complete some of those webmaster tasks.

Dennis has stuff for CSS Menus, Dynamic links, Polls, Pop-up menus, and more. Not only that, but he is an avid FrontPage user and proponent. He has some great reasons why you should use FrontPage and he's even got some ideas on how FrontPage can help you with search engines.

Thanks Dennis, and great job!