Theme a multiple CCK field with a table

Sometimes CCK contrib modules cannot do exactly what you want. It’s time to build your custom CCK field!

Official documentation on CCK fields creation for Drupal 6 is incomplete and some passages are obscure. If there is a good howto you have to read before do any CCK customization, this is Creating Custom CCK Fields. This howto supposes you’ve read and understand it before continue. If you want to create a custom field, you can read the complete Creating a Compound field. A custom multiple compound field (with more than one field for element, e.g. an image and its description).

Read these howto well, you’ll spare time later

Well, you have followed the howto, you have your own compound field but now you have a problem. You want to display compound field data as cells in a table, and each field as row.

On following example, we have a name list made with a multiple compound field with “firstname” and “lastname” columns.

KarenS tell you that you’ve to use CONTENT_HANDLE_MODULE instead of CONTENT_HANDLE_CORE on hook_formatter_info() .

// The machine name of the formatter.
function my_funny_module_field_formatter_info() {
  return array(
    'default' => array(
      'label' => t('Default'),
      // An array of the field types this formatter
      // can be used on.
      'field types' => array('examplefield'),
      // CONTENT_HANDLE_CORE:   CCK will pass the formatter
      // a single value.
      // CONTENT_HANDLE_MODULE: CCK will pass the formatter
      // an array of all the values. None of CCK's core
      // formatters use multiple values, that is an option
      // available to other modules that want it.
      'multiple values' => CONTENT_HANDLE_MODULE,

/** Set the formatter **/
function my_funny_module_theme() {
  return array(
    'my_funny_module_formatter_default' => array(
      'arguments' => array('element' => NULL),
      'function' => 'funny_display_table',

/** Here you format your table data as array **/
function my_funny_module_formatter_default($element) {
  $data = array(
  return $data;

/** This function will display a table even where data array is empty:
 ** You have to put an additional control statement to avoid this.
 ** $element will have $data from formatter_default() above
function my_funny_module_display_table($element) {
  $header = array(
    t('First name'),
    t('Last name'),
  $i = 0;
  while (!$end) {
    /** Any row will contains **/
    if(array_key_exists($i, $element)) {
      $rows[] = array(
        'firstname' => $element[$i]['#item']['firstname'],
        'lastname' =>$element[$i]['#item']['lastname'],
    else {
      $end = TRUE;
  /** Theme a table with data from element and header **/
  return theme('table', $header, $rows);

Note: to format a table you have to change only “multiple values” on my_funny_module_field_formatter_info(): you can leave my_funny_module_widget_info() as is.

See also:

Save user profile on Drupal

Tested on:

  • Drupal 5.x

After you have created some user fields through Profile module provided by core, you can have the need to save value into the user object. Here a quick howto to do this.

On user creation:

/** create user profile ($new_user will be an user object) */
$new_user_array = array (
  'name' => "funnyusername",
  'pass' => "MyVerySecurePassword",
  'mail' => "info@example.gom",
  'status' => 1, # status: active
$new_user = user_save(NULL, $new_user_array, $category = 'account');
/** assign values to profile fields */
$new_user_edit =  array(
'profile_surname' => "Yumemiya",
'profile_name' => "Arika",
/** create and save profile fields */
profile_save_profile($new_user_edit, $new_user, "Character ID");

Where “Character ID” is the category name for profile_surname e profile_name.

To load current user instead creating new one, you have to use

global $user;

instead a previously declared user object $new_user.

See also:


  • Using this method during a cronjob (using hook_cron) I experienced an error: profile values are passed, but not written, but only if cronjob is launched automatically, and not forced by Report screen (as admin). After some days, I discovered that it’s a permission issue.
    Add a “cronbot” user with some privileges over user (“administer user”) to allow writing even on hidden Profile field.
    On a dedicated server, with a dedicated IP, you can automatically login by IP (by IP Login module for 5.x and 6.x) the cronjob using the server IP or loopback address ( depending on server configuration (I use the first in production, the latter on local testing).

    1. Add an ip_login Profile field (single line text field, hidden field)
    2. Enable IP Login module
    3. Assign ip_login field to IP login by IP Login configuration screen
    4. Create a new role named “cronbots”, with “administer users” permission.
    5. Create a new user named “cronbot”, with “cronbots” role assigned
    6. Change the “IP login” field for “cronbot” to your server IP ( or your static IP address as listed on ifconfig on *nix servers)

    On the next automatic cron run (not force it), you’ll see the “cronbot” user logging in. On Drupal logs, the cronjob execution pass from “Anonymous” to “cronbot”, and profile fields are rightly written.
    The other way:
    Just write profile field via db_query. (You don’t want to do a weird thing like that, right? 😉 )