1. 4.6.x developer/examples/node_example.module
  2. 4.7.x developer/examples/node_example.module
  3. 5.x developer/examples/node_example.module

This is an example outlining how a module can be used to define a new node type.

Our example node type will allow users to specify a "color" and a "quantity" for their nodes; some kind of rudimentary inventory-tracking system, perhaps? To store this extra information, we need an auxiliary database table.

Database definition:


  CREATE TABLE node_example (
    nid int(10) unsigned NOT NULL default '0',
    color varchar(255) NOT NULL default '',
    quantity int(10) unsigned NOT NULL default '0',
    PRIMARY KEY  (nid)
  )

File

developer/examples/node_example.module
View source
<?php

/**
 * @file
 * This is an example outlining how a module can be used to define a new
 * node type.
 *
 * Our example node type will allow users to specify a "color" and a "quantity"
 * for their nodes; some kind of rudimentary inventory-tracking system, perhaps?
 * To store this extra information, we need an auxiliary database table.
 *
 * Database definition:
 * @code
 *   CREATE TABLE node_example (
 *     nid int(10) unsigned NOT NULL default '0',
 *     color varchar(255) NOT NULL default '',
 *     quantity int(10) unsigned NOT NULL default '0',
 *     PRIMARY KEY  (nid)
 *   )
 * @endcode
 */

/**
 * Implementation of hook_help().
 *
 * Throughout Drupal, hook_help() is used to display help text at the top of
 * pages. Some other parts of Drupal pages get explanatory text from these hooks
 * as well. We use it here to provide a description of the module on the
 * module administration page.
 */
function node_example_help($section) {
  switch ($section) {
    case 'admin/modules#description':

      // This description is shown in the listing at admin/modules.
      return t('An example module showing how to define a custom node type.');
    case 'node/add#node_example':

      // This description shows up when users click "create content."
      return t('This is an example node type with a few fields.');
  }
}

/**
 * Implementation of hook_node_name().
 *
 * This is a required node hook. Since our module only defines one node
 * type, we won't implement hook_node_types(), and our hook_node_name()
 * implementation simply returns the translated name of the node type.
 */
function node_example_node_name($node) {
  return t('example node');
}

/**
 * Implementation of hook_access().
 *
 * Node modules may implement node_access() to determine the operations
 * users may perform on nodes. This example uses a very common access pattern.
 */
function node_example_access($op, $node) {
  global $user;
  if ($op == 'create') {

    // Only users with permission to do so may create this node type.
    return user_access('create example node');
  }

  // Users who create a node may edit or delete it later, assuming they have the
  // necessary permissions.
  if ($op == 'update' || $op == 'delete') {
    if (user_access('edit own example nodes') && $user->uid == $node->uid) {
      return TRUE;
    }
  }
}

/**
 * Implementation of hook_perm().
 *
 * Since we are limiting the ability to create new nodes to certain users,
 * we need to define what those permissions are here. We also define a permission
 * to allow users to edit the nodes they created.
 */
function node_example_perm() {
  return array(
    'create example node',
    'edit own example nodes',
  );
}

/**
 * Implementation of hook_link().
 *
 * This is implemented so that an edit link is displayed for users who have
 * the rights to edit a node.
 */
function node_example_link($type, $node = 0, $main) {
  $links = array();
  if ($type == 'node' && $node->type == 'node_example') {

    // Don't display a redundant edit link if they are node administrators.
    if (node_example_access('update', $node) && !user_access('administer nodes')) {
      $links[] = l(t('edit this example node'), "node/{$node-&gt;<span class="php-function-or-constant property member-of-variable">nid</span>}/edit");
    }
  }
  return $links;
}

/**
 * Implementation of hook_menu().
 *
 * In order for users to be able to add nodes of their own, we need to
 * give them a link to the node composition form here.
 */
function node_example_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'node/add/node_example',
      'title' => t('example node'),
      'access' => user_access('create example node'),
    );
  }
  return $items;
}

/**
 * Implementation of hook_form().
 *
 * Now it's time to describe the form for collecting the information
 * specific to this node type. This hook requires us to return some HTML
 * that will be later placed inside the form.
 */
function node_example_form(&$node) {
  $output = '';

  // In order to be able to attach taxonomy terms to this node, we need
  // to display the appropriate form elements.
  if (function_exists('taxonomy_node_form')) {
    $output .= implode('', taxonomy_node_form('node_example', $node));
  }

  // Now we define the form elements specific to our node type.
  $output .= form_textarea(t('Body'), 'body', $node->body, 60, 20);
  $output .= filter_form('format', $node->format);
  $output .= form_textfield(t('Color'), 'color', $node->color, 60, 128);
  $output .= form_textfield(t('Quantity'), 'quantity', $node->quantity, 10, 10);
  return $output;
}

/**
 * Implementation of hook_validate().
 *
 * Our "quantity" field requires a number to be entered. This hook lets
 * us ensure that the user entered an appropriate value before we try
 * inserting anything into the database.
 *
 * Errors should be signaled with form_set_error().
 */
function node_example_validate(&$node) {
  if ($node->quantity) {
    if (!is_numeric($node->quantity)) {
      form_set_error('quantity', t('The quantity must be a number.'));
    }
  }
  else {

    // Let an empty field mean "zero."
    $node->quantity = 0;
  }
}

/**
 * Implementation of hook_insert().
 *
 * As a new node is being inserted into the database, we need to do our own
 * database inserts.
 */
function node_example_insert($node) {
  db_query("INSERT INTO {node_example} (nid, color, quantity) VALUES (%d, '%s', %d)", $node->nid, $node->color, $node->quantity);
}

/**
 * Implementation of hook_update().
 *
 * As an existing node is being updated in the database, we need to do our own
 * database updates.
 */
function node_example_update($node) {
  db_query("UPDATE {node_example} SET color = '%s', quantity = %d WHERE nid = %d", $node->color, $node->quantity, $node->nid);
}

/**
 * Implementation of hook_delete().
 *
 * When a node is deleted, we need to clean up related tables.
 */
function node_example_delete($node) {
  db_query('DELETE FROM {node_example} WHERE nid = %d', $node->nid);
}

/**
 * Implementation of hook_load().
 *
 * Now that we've defined how to manage the node data in the database, we
 * need to tell Drupal how to get the node back out. This hook is called
 * every time a node is loaded, and allows us to do some loading of our own.
 */
function node_example_load($node) {
  $additions = db_fetch_object(db_query('SELECT color, quantity FROM {node_example} WHERE nid = %d', $node->nid));
  return $additions;
}

/**
 * Implementation of hook_view().
 *
 * This is a typical implementation that simply runs the node text through
 * the output filters.
 */
function node_example_view(&$node, $teaser = FALSE, $page = FALSE) {
  $order_info = theme('node_example_order_info', $node);
  $node->body .= $order_info;
  $node->teaser .= $order_info;
  $node = node_prepare($node, $teaser);
}

/**
 * A custom theme function.
 *
 * By using this function to format our node-specific information, themes
 * can override this presentation if they wish. We also wrap the default
 * presentation in a CSS class that is prefixed by the module name. This
 * way, style sheets can modify the output without requiring theme code.
 */
function theme_node_example_order_info($node) {
  $output = '<div class="node_example_order_info">';
  $output .= t('The order is for %quantity %color items.', array(
    '%quantity' => $node->quantity,
    '%color' => $node->color,
  ));
  $output .= '</div>';
  return $output;
}

Functions

Namesort descending Description
node_example_access Implementation of hook_access().
node_example_delete Implementation of hook_delete().
node_example_form Implementation of hook_form().
node_example_help Implementation of hook_help().
node_example_insert Implementation of hook_insert().
node_example_link Implementation of hook_link().
node_example_load Implementation of hook_load().
node_example_menu Implementation of hook_menu().
node_example_node_name Implementation of hook_node_name().
node_example_perm Implementation of hook_perm().
node_example_update Implementation of hook_update().
node_example_validate Implementation of hook_validate().
node_example_view Implementation of hook_view().
theme_node_example_order_info A custom theme function.