If you've ever built a large website that requires private files, then you've probably run into this before. In Drupal 6 the CSS optimization requires that the files be stored publicly. This is a known bug that will not be fixed according to the drupal developers.

The boss just shot you an email. He wants the user’s profile to get updated whenever that user creates a story node. He also wants to automatically post badges to a user’s profile when their story has been viewed a certain number of times. And you can’t use the statistics module, because it killed his family. Can you have it by this afternoon?

No problem. Hook_nodeapi’s got this.

There are many things you may want to do to a new user on your Drupal website. You may want to apply a new role, require approval, or even programmatically create node with the new user as the author. So let's get started...

So the trick here is obviously using the $op insert as it is only called once upon user creation.

One of the most frustrating things to deal with as a Drupal programmer can be Ubercart. Often, you need to complete a simple task such as sending an additional email, or giving a user a new role, and your options are to use Rules, Conditional Actions or just program it yourself.

Rules or Conditional Actions allow you to execute PHP, but sometimes you don't want to store your php code in an unformatted text field in the database. Enter hook_order(). One of Ubercart's primary hooks for getting stuff done.

Aegir is wizardry, pure and simple. Once you’ve got it set up and running there’s almost no excuse not to have all of your sites on it.

There are plenty of great tutorials on moving your existing site into Aegir like Dboettger’s tutorial or Aegir’s Community tutorial but they assume that you’re pretty handy with the command line.

If you don’t feel comfortable with the command line or you don’t want to mess with it you can still pull the migration off.


Recently I needed to implement caching for a custom Drupal module. I needed my module to cache exactly every 30 minutes on the hour and half-hour.

After doing my homework, I found the necessary Drupal functions in cache_get() and cache_set().

Additionally, I found a good warning in this Civic Actions blog post (Drupal Gotchya: Cache_get() Returns Expired Items) about Drupal relying on cron to determine whether a cache has expired.

The best way to handle caching the way you want is to write some custom wrapper functions. This will give you the ability to deal with edge cases as you need. Here are my custom cache_get and cache_set functions.

NOTE: This post describes the very simple process of starting a custom module. The purpose is to use this as a basis for all other custom modules created in Drupal 6 or Drupal 7.