Login

Drupal 7 Adding Custom Content Type with Custom Fields (Field API)

In this post we are going to use the custom field "news_date" described in the previous post "Drupal 7 Field API - A simple example".

The module in this post automatically installs a content type with two instances of our "news_date" field (begin and end). 

First a little background:

Drupal 7 introduces the  concept of "entities"  A "node" is a specialization of an "entity". Content types are a further specialization of "node".

An entity can be defined as "fieldable" (which node is).  Thus, "content types" are also "fieldable" (i.e. we can add fields).

Our new module is called "newletter". Here is the "newletter.info" file.

name = News Letter
description = news letter for Drupal 7
dependencies[] = news_date
package = public-action newsletter
version = VERSION
core = 7.x
files[] = newsletter.module
files[] = newsletter.install

Note! We set our "news_date" module as a dependency. We don't want to try and install our new content type without the required field (i.e. news_date) installed.

Next our "newletter.install" file. Just a few simple arrays and method calls:

<?php
function newsletter_install() {
 
  // Ensure the forum node type is available.
  node_types_rebuild();
  $types = node_type_get_types();
  node_add_body_field($types['newsletter']);
 
  foreach (_newsletter_installed_fields() as $field) {
    field_create_field($field);
  }
 
  foreach (_newsletter_installed_instances() as $instance) {
    field_create_instance($instance);
  }
 
}
 
function _newsletter_installed_fields() {
  $t = get_t();
  return array(
    'field_start' => array(
      'field_name' => 'field_start',
      'cardinality' => 1,
      'type'        => 'news_date',
    ),
    'field_end' => array(
 
      'field_name' => 'field_end',
      'cardinality' => 1,
      'type'        => 'news_date',
    ),
   );
 
}
function _newsletter_installed_instances() {
  $t = get_t();
  return array( 
   'field_start' => array(
      'field_name' => 'field_start',
      'label'       => $t('The Start Date.'),
      'bundle' => 'newsletter',
      'entity_type' => 'node',
      'widget'      => array(
        'type'    => 'news_date',
      ),
      'display' => array(
        'default' => array(
          'label' => 'above',
          'type' => 'news_date_formatter',
        ),
      ),
      'description' => 'Begin Date',
    ),
   'field_end' => array(
 
      'field_name' => 'field_end',
      'label'       => $t('The End Date.'),
      'bundle' => 'newsletter',
      'entity_type' => 'node',
      'widget'      => array(
        'type'    => 'news_date',
      ),
      'display' => array(
        'default' => array(
          'label' => 'above',
          'type' => 'news_date_formatter',
        ),
      ),
     'description' => 'End Date',
    ),
 
  );
}
 
function newsletter_uninstall() {
 
  $sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
  $result = db_query($sql, array(':type' => 'newsletter'));
  $nids = array();
  foreach ($result as $row) {
    $nids[] = $row->nid;
  }
 
  // Delete all the nodes at once
  node_delete_multiple($nids);
 
  $instance = array('field_name' => 'comment_body','bundle' => 'comment_node_newsletter','entity_type' => 'comment');
  field_delete_instance($instance);
 
  $instance = array('field_name' => 'body','bundle' => 'newsletter','entity_type' => 'node');
  field_delete_instance($instance);
 
   $fields = array_keys(_newsletter_installed_fields());
   foreach ($fields as $field) {
      field_delete_field($field);
  }
 
  // Purge all field infromation
   field_purge_batch(1000);
}

To summarize, we are performing the steps normally done manually through the administration screens (i.e. adding and configuring fields with our content type). Note! Our entity type is "node" and our content type is referred to as a bundle "newletter".

In Drupal 7 you must explicitly add a "body" field when you create a custom content type, thus the call to node_add_body_field($types['newsletter']);.

Our actual module file only needs to do a couple things. Define the "content type" by implementing hook_node_info(). Implement hook_form() to make sure our "title" is rendered in the input form.

<?php
 
function newsletter_node_info() {
  return array(
      'newsletter' => array(
          'name' => t('News Letter'),
          'base' => 'newsletter',
          'description' => t('A news letter content type'),
          'has_title' => TRUE,
          'title_label' => t('Newsletter Title'),
          'locked' => FALSE,
      ),
  );
}
 
function newsletter_form($node, $form_state) {
  $type = node_type_get_type($node);
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => check_plain($type->title_label),
    '#default_value' => !empty($node->title) ? $node->title : '',
    '#required' => TRUE, '#weight' => -5
  );
 
  return $form;
}

Comments

Peculiar article, totally what I was looking for.

to ? to ? decrease ? exchange ? that