Skip to content

Building a “Tag Cloud” in PHP

Dear Reader,

Just a few more and I promise I’ll get off the programming kick. I was working on my AJAX based resume last night (what, doesn’t everybody have one?) and got everything but the Skill Cloud” done. My idea of a skill cloud comes from the latest toy that people are deploying on the web, tag clouds. It seemed to me that it should be pretty straight forward to create one and so I dove off the board before making sure there was water in the pool.

Not being very good at math, I was struggling with how to take my list of x skills and evenly space them into a maximum of 10 categories. (tagcloud_1 – tagcloud_10) Here’s a quick rundown of what I came up with.

My data set is my list of skills deployed at a given company. Each bullet point for a company has a list of skills attached to it. Each skill has a weight that is determined by how proficient I am at that particular skill. (1=nubie…10=demigod) For each company, I gather the list of skills I used and sum their weights. For those of you in the valley, I will explain. If I used FoxPro on 3 bullet points in a job and my FoxPro weight is 10 (which it is) then my FoxPro score for this job will be 30. If I also used Java on 1 bullet point at this job and my Java weight is 1 (which it is) then my Java weight for this job will be 1.


$ceiling = 1;
$floor   = 99999999;

First, compute the boundaries of the current weights. I thought about using array_walk in this situation but I eventually want to OOpify it and I’m not sure if array_walk can play nice in an OOP world.


for($lcvA=0;$lcvA<count ($rsArray);$lcvA++)
{
	$ceiling = ($rsArray[$lcvA]['weight']>$celing
		?$rsArray[$lcvA]['weight']
		:$ceiling);
	$floor  = ($rsArray[$lcvA]['weight']<$floor
		?$rsArray[$lcvA]['weight']
		:$floor);
} // for($lcvA=0;$lcvA<count($rsArray);$lcvA++)

Now get the spread. The spread is the difference between the ceiling and the floor.


$difference = ($ceiling-$floor);

Ok, now break the spread into 9 different buckets. We already know what 1 is, it’s the floor. Since we want a total of 10 total categories we divide the spread by 9.


$increment = $difference/9;

Finally, take the current weight for each item and shove it into the proper bucket.


for($lcvA=0;$lcvA<count ($rsArray);$lcvA++)
{
	$rsArray[$lcvA]['weight'] = 
		intval(($rsArray[$lcvA]['weight']-$floor)/$increment)+1;
} // for($lcvA=0;$lcvA<count($rsArray);$lcvA++)

That’s it. Now the array contains weights that are comparable to their original weights but are in the range of 1-10. Now in the output, I use a span tag to wrap each skill and the ID of the span tag is tagcloud_x where X is the weight. Add 10 IDs to my style sheet and it’s done. This code is overly verbose mainly because I’m using it as an example. Also, please forgive my lack of OOP. Version 2 will be OOpier, I promise!

Here are the styles I added to mine for reference.


#tagcloud_1 
{
	font-family: Arial, verdana, sans-serif; 
	font-size:16;
} 

#tagcloud_2 
{
	font-family: Arial, verdana, sans-serif; 
	font-size:16;
	font-weight: bold;
} 

#tagcloud_3 
{
	font-family: Arial, verdana, sans-serif; 
	font-size:16;
	font-style: italic;
	font-weight: bold;
} 

#tagcloud_4 
{
	font-family: Arial, verdana, sans-serif; 
	font-size:20;
} 

#tagcloud_5 
{
	font-family: Arial, verdana, sans-serif; 
	font-size:20;
	font-weight: bold;
} 

#tagcloud_6 
{
	font-family: Arial, verdana, sans-serif; 
	font-size:20;
	font-style: italic;
	font-weight: bold;
} 

#tagcloud_7 
{
	font-family: Arial, verdana, sans-serif; 
	font-size:24;
} 

#tagcloud_8 
{
	font-family: Arial, verdana, sans-serif; 
	font-size:24;
	font-weight: bold;
} 

#tagcloud_9 
{
	font-family: Arial, verdana, sans-serif; 
	font-size:24;
	font-style: italic;
	font-weight: bold;
} 

#tagcloud_10 
{
	font-family: Arial, verdana, sans-serif; 
	font-size:28;
} 

Until next time, love you bunches,
(l)(k)(bunny)
=C=

How NOT to write a FOR loop in PHP

Dear Reader,

Ok, so I’m on a programming roll right now…sue me.

Here’s a piece of code I saw yesterday on a mailing list. At first I thought it was borked and started to reply that there’s no way it would work…son-of-a-gun if it doesn’t…sort of.

< ?php 
for ($j=A; $j <= Z; $j++) 
{
    echo $j."\n";
    if ($j==Z) break;
} 
?>

I’ve never seen anyone increment a character value before. It intrigued me so I played with it for a few minutes. First let me say if someone on one of my teams every wrote code like this…well, it’s a ‘Career Limiting Move’. Character values are just that, characters. If you need to build a list of the letters of the alphabet, do it the way programmers have been doing it for at least the 23 years I’ve been programming, iterate through the numbers 65-91. Use the chr() function to get your letter. (c’mon, other than the numbers changing, we even did that on my old C=64!)

The second problem with this code is that without the IF statement, that it doesn’t do exactly what you would expect it to do. Run the code without the IF and look at the output. I’m not sure I know why it does that. I’m not sure why $j does not evaluate to == Z when it actually displays the Z. I could probably dig in and find it but I really don’t care.

For those interested, a better way to do this would be:

< ?php 
for ($j=0; $j <26; $j++) 
{
  echo chr(65+$j)."\n";
} 
?>

It’s fewer lines of code and we are not using string types as numbers.

This is a good example of “Just because you can, doesn’t mean you should.”

Until next time, my prayers are with you today.
(l)(k)(bunny)
=C=

Forks!=Threads!

Dear Reader,

Yes, another programming blog…get over it. For you non-techies, go get some candy or something, let the grown-ups talk. BTW, TinaT! (This is not a Tutorial!) This is just a monologue of what I went through to get a program to fork.

Ok, so over the holidays I spent some time deep into code. I wrote apacheLogSplit a few weeks ago so I could import a customer’s log files into MySQL so I could root around in them. (Hey, I like rooting around in data!) Anyhow, program worked like a charm but it was a bit slow. So after I released it, I decided to see if I could speed it up. The first thing that came to mind was “boy it would be nice if this were a multi-threaded application.” Unfortunately, PHP is not a multi-threaded environment. The best we can do is fork it. I like working on new concepts with existing projects because I’ve already worked out the details of the logic so I can concentrate on the new concepts I’m learning. So like a fat-man doing a swan-dive, I took the plunge with apacheLogSplit.

Having never worked with forking before, I did what any lazy programmer does, I googled around to see what others had done that I could steal. As luck would have it, there’s a class in pear called PHP_Fork. It’s specifically designed to encapsulate the forking process and make it easier to work with in an OOP environment. (and if you are not writing OOP then just hang your head in shame and walk away slowly.) since apacheLogSplit was built using OO, it seemed the perfect solution. That is until I tried to install it. PHP_Fork requires PHP be compiled with –enable-cli –with-pcntl –enable-shmop. Even after recompiling it to meet the specs (I didn’t have shmop compiled originally) it still wouldn’t *&^%!!! install using pear. Well, when the tools fail you, reach for the sledgehammer; I resorted to downloading it and installing it manually. Once I placed it manually in the proper pear directory I was on my way.

I knew my program was overly complex. Version 1.0 was a learning experience for a different lesson. I was experimenting with PHP5’s new OOP features. While I got everything to work the way I wanted to, if you’ve looked at the code you know there are a bunch of abstract classes, even an interface that gets implemented. So before I could do much with it, I had to simplify it. (Much like I need to do with this blog.) I got rid of all the abstract classes and such and pared it down to 3 main classes (the main controller class, the line class and the SQL writer class) and a few lines of procedural code in the main program to handle parameters and such. (Yes, I KNOW I could have moved that into an object!)

So, we now have code we can work with and our Fork.php installed. We are now ready to get down to some serious forking around. The first thing I learned is that I had a mis-conception of how forking worked. I knew that it was not the same as a thread but I assumed that when you forked code that the child started again form the beginning. Not so, the child process begins running with the statement after the fork. Very important distinction and it’s probably a mis-conception that only I had.

Once I crossed that hurdle, I was able to make quick progress. I had already designed my code so that the main body of processing took place inside an object; I made this object my thread marshaler. It read in a line from the file and then handed it to the first idle thread.

My threads have 2 subordinate objects, a line parser and a SQL writer. As I said earlier, for simplicity’s sake I did away with all the abstract classes etc. This version of the program can not be easily extended to write to XML, etc. I did that so as to simplify the code for readability and because I question whether anyone will actually take the time to do it. Once simplified, the object interaction is simple and easy to follow.

This brings me to the final hurdle I had to overcome, parent-child communication. This is where I REALLY miss threads. Threads make this a might easier because you can directly fire methods on the child form the parent. And because they are threads, they will sit in a sleep state until you do fire a method on them. In this case, each child sits in a loop waiting for a message. Once it receives a message, it processes the line and then goes back into its loop.

The only way to send the child a message is to use shared memory. PHP_Fork handles this nicely by setting up the semaphores and defining the 2 methods setVariable() and getVariable(). Using them you can set a variable in the parent and retrieve it in the child. So in my loop I set the variable lineValue. The child loops until it finds a value for lineValue and then goes to work processing it. Easy as pie, interprocess communication. Note that it is possible but a bit more complicated to fire a method on the child thread with a parameter. I chose not to bother with it in this case but I could have just as easily done that.

That’s it. My little PHP program is now a multi-process program. Here’s the kicker. It didn’t make any difference in speed. The main problem I have is that I’m running the program on the same box as MySQL. Thus they are competing for processor resources. 2 threads ran about the same speed 10 threads actually ran slower. I think the results would have been different if I were running them on separate boxes on a LAN.

Until next time, come back home safely.

(l)(k)(bunny)
=C=

PHP5! Finally

Dear Reader,

I finally took the plunge to PHP5! I learned 1 very important lesson that anyone coding in PHP or administering servers running PHP should know. NEVER EVER EVER upgrade to the latest version if you are running Zend*. Zend lags the php releases by a few days. In my case, I am using ZendOptimizer. The latest version 2.5.10a does not work with PHP 5.1. There is a hint that 2.5.13 is in the works if you know where to look but I could only find the FreeBSD version. So after tinkering for a couple of hours I dropped back to the 5.0.x tree.

Oh, also, when moving from 4.x to 5.x, I had to uninstall and reinstall a pecl extension I had. Upgrade won’t work because pecl thinks it knows better. Why would you want to rebuild the version that is already there? (grrrr) Since there is no force option, I did the only thing I could think of…uninstall and reinstall.

Anyhow, for those of you curious, current versions of DirectAdmin and Installatron work with 5.0.x. (Granted I’ve not done much in the way of testing but they do come up.)

Squirrelmail is hopelessly hosed though. (That’s why I’m not reading my email right now)

Anyhow, back to the grind.

Until next time, I’m counting down the days.

(l)(k)(bunny)

=C=

Oh HELL Yea!

Dear Reader,

PHP Console Mode

This rocks more than anything I’ve seen added to PHP in some time.

I grew up programming FoxPro. One of the great things about FP/VFP was the command window. Just fire it up and start issuing commands. It was wonderful. You could easily get things done, test new ideas, even check syntax. SideNote: I got in trouble at a previous job because a lot of what I did was in the command window and not in prg files. Now the company they replaced me with can’t figure out how to do simple tasks like data analysis. (Guys, I’m sorry you can’t find a competent programmer to replace me. Next time, don’t make such rash decisions)

Anyhow, this is going to be da bomb and my killer reason for switching to PHP5.

Until next time, have a wonderful day.

=C=