I know I promised to do nothing but “includes,” and we’ll come back to those soon, but here is a real PHP routine, doing an actual real world job. What does it do? For a multi-author weblog like BloodhoundBlog, it produces a blogroll of the contributors’ weblogs or web sites. I’m sending this out to Morgan Brown, because Blown Mortgage is a multi-author blog — and because Morgan has joined ranks with Cheryl Johnson as a geek-blogger.
Why do this with software when it can be done with the “Links” feature within WordPress? Because a list done this way is self-maintaining. This code is based on the “Frequent Contributors” code on BloodhoundBlog — which would be a lot harder to explain. I added this last week when I upgraded to WordPress 2.3.2.
Here’s the code. I’ll go back through it and comment line-by-line:
<h2>Our Contributors' Web Sites</h2><UL> <?PHP $contribs = array(1,3,6,8,9); $count = sizeof($contribs); shuffle($contribs); for($i=0;$i<$count;$i++) { $thisUser = $contribs[$i]; $curauth = get_userdata($thisUser); ?> <li><a href="<?PHP echo $curauth->user_url; ?>" target="_blank"> <?php echo $curauth->yim; ?></a></li> <?PHP } ?></UL>
Here’s the thing: PHP is a very sloppy language.
From Ada Lovelace to Kernighan and Richie, programming was always done with very tight, very clean code. Hardware was slow and expensive, so programmers were, relatively speaking, plentiful and cheap. Moore’s Law inverts that paradigm, with the result that any cost in hardware is worth bearing to maximize programmer time. This is why you’re always buying bigger, faster hardware, because programmers are sucking up every bit of it and then some. ANSI C was perhaps the apogee of the orbit for clean code: Strongly typed, strict syntax, unforgiving compilers. But, written right, C could get right down to the bone, running as fast, or almost as fast, as functionally-equivalent machine code.
PHP is like C in many, many respects — except that, like Javascript before it, it dispenses with type-checking, function prototyping, most syntax-checking, etc. It’s interpreted at run-time, not compiled, so there’s no compiler to catch errors. Instead of maximizing machine resources, PHP maximizes programmer time. It exists to let a skilled programmer bang out tons of original code in no time flat. Many other web programming environments are similarly loose, and, while this grates on the nerves of any properly punctilious programming professor, the widespread use of fast, forgiving programming languages is why the Web 2.0 world seems to grow like dreams, with new things popping up all the time. You can multiply pi times “Samuel Clemens” and divide that by an array of photographs, but you’ll finish the job before South Park comes on.
Even so: PHP is easy to learn. Every scrap of documentation is on-line, along with tons of good coding examples. Just don’t confuse it with Computer Science.
Here’s what we’ve got in this simple little routine, line by line:
<h2>Our Contributors' Web Sites</h2><UL>
Dood! That’s just HTML. That h2 headline is a common form in the sidebar.php file of a WordPress weblog. This little snippet of code actually runs out of an “included” file, though, just because I like for things that I might change to be isolated from things I’ll probably never edit. That’s a Kernighan and Richie (K&R) kind of design philosophy applied to a text-programming problem. Everything we’ve been talking about since I started talking about PHP relates to a fairly rigorous idea of modularity: If you build your tools in small, easily maintained modules, you’re much less likely to get yourself into trouble. Even if you do, your errors should tell you just which module is failing. My son Cameron, who is a much better programmer than I am, grew up in the world of Javascript and PHP. He writes in vast files that make my brain ache. But: Me and K&R get our revenge when he can’t find a bug.
<?PHP
Let the games begin! PHP runs only on files that are named with the .php extension. It won’t be invoked at all on other types of files. Why? Because the web server, when — and only when — it sees the .php extension, sends that file to PHP first. If the file contains nothing but HTML, it’s passed through to the HTTP handler unmodified. But where PHP encounters “<?PHP”, it starts looking for PHP code. It’s possible to write a whole file in PHP, using PHP commands to “echo” or “print” HTML when it’s needed. It’s more common to work in HTML, escaping into PHP for short burst of code, as in the Slide Show Marge example files I discussed. This little program will do both, working mostly in PHP, dropping out to HTML, escaping back into PHP from the HTML, then finishing in PHP. Why do things this way or that way? Fast and cheap, period. All we want is to do the job we came to do in the easiest possible way.
$contribs = array(1,3,6,8,9);
This creates an array of contributors, giving it the name $contribs. The numbers are the user numbers, from the WordPress “Users” panel, of the contributors we are blogrolling — in this abbreviated case, me, Cathleen, Russell, Jeff Brown and Richard Riccelli. It would be possible to do this programmatically, too, rather than typing in the user numbers. But at BloodhoundBlog, we never kill a contributor, because we know past contributors might decide to come back. Instead, I manually edit this one line when we add or remove a frequent contributor.
$count = sizeof($contribs);
We’re creating a variable called $count by counting the number of contributors. Programming is about managing ignorance. I could say “$count = 5”, but then I would have to edit that line every time I make a change. Instead I edit only that $contribs line and let the software manage the rest of the problem.
shuffle($contribs);
We’re randomizing the array of $contribs so that one person doesn’t always come first or last. It’s a crude kind of egalitarianism.
for($i=0;$i<$count;$i++)
Now it looks like software. Suddenly, we are well and truly in K&Rworld. The “for” command starts a loop. What’s going to happen is that we’re going to execute the loop $count times — in this case five times, but — managing ignorance — it could be any number. The value in $count is an cardinal number — 1, 2, 3, … — but a C-like array is indexed starting with zero — $contribs[0], $contribs[1], $contribs[2], etc. That’s why $i is initialized at zero, and why the loop only runs while $i is less than $count. The code “$i++” is a K&R C unary operator that means “increment (add one to) $i at the end of each execution of the loop”. We’re going to be inside this loop for the next ten lines, which simply means that the next ten lines of code will execute $count separate times, after which we’ll go on to the next line of code.
{
Yeah, it matters. In the C-like world, everything inside a set of curly-braces is defined as a block of code, executing as if it were a single command. Without the curly braces, only the first line after the “for” loop would execute. By putting our code into this block, the entire block executes within the loop. Blocks of code within curly braces can be (deeply) nested, much like nested “divs” in the CSS/HTML world.
$thisUser = $contribs[$i];
For convenience, we’re defining a variable $thisUser with the contents of $contribs[$i]. We could just use $contribs[$i] instead, but using a construct like $thisUser helps to make the code self-documenting.
$curAuth = get_userdata($thisUser);
Now we’re defining a current author with the variable $curAuth. The WordPress-specific function “get_userdata” returns a complex data structure for user number $thisUser, which we are receiving into $curAuth. In subsequent lines, we’ll be interrogating the $curAuth structure for data. This is fairly low-level stuff for WordPress — which is also comprehensively documented on-line. The data we’ll pull out of $curAuth is available by separate high-level functions within “the loop” in WordPress — that is, within each post in the the weblog. It’s only because we’re extracting this information outside of “the loop” that we have to do it this way.
?>
This is my favorite line in the program. What does it say? It says: “Exit from PHP.” You read that right. We are inside a PHP loop, and yet we are exiting from PHP, defaulting out to HTML — as we’ll see in the next three lines. In the entire history of complied software, nobody ever said, “Stop being the active programming environment, but, by all means, continue running the program.” How can this possibly work? Remember that PHP gets to process the whole file before the HTTP handler sees any of it. The version of this little program that runs on BloodhoundBlog lives in a file called “contribBlogs.php”. If I changed the name of that file to “contribBlogs.html”, PHP would never see it. The HTTP handler would throw all the PHP away and it would show the HTML we’re about to see one time, not $count times. PHP will continue to honor the loop, even though we’re exiting from PHP for the moment, because we’re still within the curly-brace block of code. I told you it mattered. Even so, this only works this way because PHP exists to make fast and cheap web pages, rather than to produce elegant programming code.
<li><a href="<?PHP echo $curAuth->user_url; ?>" target="_blank"> <?php echo $curAuth->yim; ?></a></li>
The next three lines are really one line in the real software routine. I broke them up this way so they would fit on the screen. What they are is ordinary HTML commingled with PHP. It’s possible to do all of this within PHP, but it’s easier — faster and cheaper — to do work like this in HTML and then swap into and out of PHP for the ignorance-management jobs. So we set up a list entry in the unordered list we started way back in the first line. Everything we’ve done since then has been leading up to this moment, and we are about to make the first of $count list entries. What’s in our list entry? A link, which we initiate in the usual way. But then, inside the quotes for the link, we swap back into PHP so that we can “echo” out the contents of “$curauth->user_url”. The “echo” command simply spits the information delivered to it out into the HTML stream, and “$curauth->user_url” will deliver the web page address found in the Website field of the User profile within WordPress. It’s easy to forget, after all this time, but we’re building a blogroll. We’ve just echoed out the web address of our first blogroll entry.
The next line is part of the link, opening the blogrolled weblog or web site into a new browser window or tab. I almost always build links this way.
The third line is the linking text. At BloodhoundBlog, we use the Yahoo Instant Messenger field of the User profile to show a pretty-printed version of the user’s weblog or web site. That means we don’t have to include “http://” or “www”, but it can also mean that http://realestatetomato.typepad.com/ could be shown as The Real Estate Tomato instead. I wish the User profile provided a more robust data structure, but we make do by using otherwise unused fields for our own purposes.
In any case, what we’ve done with this line of code, shown and discussed as three lines, is issue a list entry in our blogroll. We have managed our ignorance to produce a line of fully-formatted HTML, which is the point of this exercise.
<?PHP
What does that say? Oh, yes. It says go back into PHP. Why? Because we’re almost done with the first iteration of our “for” loop, and we have to get back to it. We’re waiting for the other shoe to drop.
}
And there it is, the closing curly-brace that terminates the block of code invoked by the “for” loop. Even though we exited from PHP to produce our HTML, we had to go back into it in order to continue processing within the loop. PHP is loose, but it’s not entirely unlaced.
So what really happens is, we go back to the sixth line of the program, the “for” loop. We increment $i, then we test it against $count. If it’s still less than $count, we run the loop again, producing one more list entry with one more link in our blogroll. We do this $count times, total. Then what? Then we stop.
?></UL>
Exit from PHP. Exit from the unordered list. Exit stage left. Put a fork in us. We’re done.
This is what PHP produces from that actual snippet of code when it is run from within BloodhoundBlog:
<h2>Our Contributors' Web Sites</h2><UL> <li><a href="http://BawldGuy.com" target="_blank"> BawldGuy.com</a></li> <li><a href="http://DistinctivePhoenix.com" target="_blank"> DistinctivePhoenix.com</a></li> <li><a href="http://NoHassleListing.com" target="_blank"> NoHassleListing.com</a></li> <li><a href="http://www.ideasincirculation.com/" target="_blank"> IdeasInCirculation.com</a></li> <li><a href="http://BloodhoundRealty.com" target="_blank"> BloodhoundRealty.com</a></li> </UL>
What happened? On the third line, we used a known database of User numbers to carefully manage our ignorance in such a way that we were able to produce a randomized blogroll of our contributors’ weblogs or web sites. By maintaining the User profile database, we can avoid having to enter and update what amounts to duplicate information in the Links database. Moreover, when individual users change weblogs or web sites, they can make the changes themselves in their User profile and that change will be reflected at once in the Contributors blogroll, even though they don’t have access to the Links database. In this respect, doing the job with custom PHP programming makes this list of contributors’ weblogs or web sites self-maintaining. The goal of software engineering is to do a job once programmatically in such a way that it need never be done manually again.
But here’s the bad news: This is a dumb little program. It’s taken close to 3,000 words to explain it, but it is not complicated or difficult or interesting. I can think of half a dozens ways to make it cooler — but I won’t. Why? Because the essence of the Unchained idea is leveraged effort. If I can easily write a little program to suck 95% of the effort out of a common task, that’s great. But that last 5%, no matter how intriguing or challenging, is probably a diminishing return. In other words, while solving the remaining problem might be satisfying or fun, if it doesn’t save a lot more time than it takes to do, it’s not worth doing. My time is better spent on other things. If my time opens up, or if that lingering 5% proves more costly than I had thought, it might be worth more effort later. But — much more likely — I’ll be doing something very different soon, and the problems I thought were so important today won’t even exist tomorrow.
If PHP interests you, it might be worth your while to learn it. But you will have to learn it conceptually, as a gestalt, not as a memorized procedure. I’m amazed that it took this much work to describe a truly dumb little program, but the other end of the stick is that I can look at code I’ve never seen before (in a lot of different computer languages) and figure out what it does. A human language takes years to learn, decades to master. After a while, if you get good at this, you’ll be able to absorb a new computer language almost by osmosis.
We won’t be teaching PHP at BloodhoundBlog Unchained. We won’t have that kind of time. What we will be teaching is the Unchained way of thinking, looking for the leveraged opportunity, where the smallest sustainable effort turns into the greatest attainable benefit. If you revisit our archives, you’ll see that we’ve been talking about that all along…
Getting in touch with your inner geek:
- Apprehending Realtor 2.0: Seven essential skills of the 21st century real estate agent…
- How to make fast, flexible web pages…
- Catch your kid doing something right: Our son Cameron and the upgrade path of SlideShowMarge
- How to make Google your weblog’s best friend…
- Speaking in tongues: Presentable PHP in WordPress
- Speaking in tongues: Dynamically updated lists of links in PHP
- Speaking in tongues just for Cheryl Johnson: Building content-rich custom web sites in PHP
- Speaking in tongues for Morgan Brown: A quick and dirty contributors’ blogroll
- Speaking in tongues: A step-by-step guide to speaking in web sites
Want more? Real Estate Weblogging 101 will speak to your inner geek. And if you want even more than that, be sure to join us for BloodhoundBlog Unchained.
Technorati Tags: blogging, real estate, real estate marketing, technology
Tony - vidlisting.com says:
“multiply pi times ‘Samuel Clemens’ and divide that by an array of photographs”
I recognize that code snippet from the end of a two day coding marathon a few weeks ago. Made sense at the time and if it would have compiled, I likely would have shipped it 🙂
Tony
January 3, 2008 — 6:14 pm
CJ, Broker in L A, CA says:
If I were to parse this down to a simpler level — I would copy and paste that little snippet of code into my WP sidebar.php file – probably put it in a <div></div> … and that would be that?
I would not need to create a separate list of contributors because that little code snippet would create the list on the fly, yes?
The shuffle thing is a stroke of brilliance…
January 4, 2008 — 7:04 am
Greg Swann says:
Edit this line
with your actual contributor numbers. You probably won’t need a div. In the world of CSS, things just work.
Be sure to use the Yahoo Instant Messenger field in your User profiles to specify the pretty-print name of the weblog or web site.
This is what a BHB User Profile looks like:
We use the bio/description field for job title, the Yahoo field for the pretty-printed web site name and the AIM field for City and State. All three of those are available from high-level functions within “the loop” and via get_userdata outside of “the loop.” All of them are used in our Frequent Contributors routine, which is the more-complicated older brother of the code discussed here.
> The shuffle thing is a stroke of brilliance
Kris really liked being first in our list of Frequent Contributors, but when we added Lani, I decided that everyone had the right to be first, so we started randomizing. Every time you refresh the page or open a link, you get a different order, 529 possible permutations right now.
January 4, 2008 — 8:10 am
Morgan Brown says:
Greg – this is excellent and truly kind of you to share! I must return back to my programming bench now – I’ll come back and share the results. bless you!
January 4, 2008 — 9:18 am
Jay Thompson says:
The propeller on my beanie is spinning wildly! I love it, and thanks for sharing!
January 4, 2008 — 4:30 pm