How to programmatically create a field in Drupal 7

Ever had a site not controlled by the features module or felt that using it, add to much administrative overhead? Or you simply want to learn how to use Drupal field API? This is for you.

In this example I will try to keep the amount of code to the very minimum. Putting too much features into a example have a tendency to put some people off with the amount of code it create. The example will not explain how you create new field types, but rather use one existing provided by Drupal core.

Scope of example

  • Create a custom module named demo_field.
  • Enabling the module create a text field and add it to a content type named article.
  • Disable it remove the field from the content type and delete the field.

demo_field module

Not testing for exiting field name or that the node type (story) actually exist. Make sure field name does not collide and that you have a content type named story. If not, alter the code to match your installation.

demo_field.info

name = demo field
core = 7.x
dependencies[] = field

demo_field.module

<?php
?>

That's right, it is a empty module. The real code is found in til file module_name.install.

demo_field.install

<?php

/**
 * Implements hook_enable().
 *
 * Create a field. Fields can be created without any needs to attach them to
 * entities.
 */
function demo_field_enable() {
 
$field = array(
   
'field_name' => 'demo_field',
   
'type' => 'text',
  );
 
field_create_field($field);

 

/**
   * Bind field to a entity bundle.
   */
 
$instance = array(
   
'field_name' => $field['field_name'],
   
'entity_type' => 'node',
   
'bundle' => 'article',
  );
 
field_create_instance($instance);
}

/**
 * Implements hook_disable().
 *
 * Remove field from node bundle (content type) and then delete the field.
 */
function demo_field_disable() {
 
$instance = array(
   
'field_name' => 'demo_field',
   
'entity_type' => 'node',
   
'bundle' => 'article',
  );
 
field_delete_instance($instance);
 
field_delete_field($instance['field_name']);
  print
'Removed ' . $instance['field_name'] . "\n";
}
?>

This is all code you need to create a field, add it to a content type. Sharing the field with another content type will only require that we add a single line.

Code breakdown

First thing we do is to define a field:

<?php
$field
= array(
 
'field_name' => 'demo_field',
 
'type' => 'text',
);
field_create_field($field);
?>

The very minimum you need to pass to field_create_field() is a name for the field and the type of field. Created fields in Drupal does not have to added to a content type (entity) right away though when you create them through the UI you do not have a choice. The field API on the other hand give you all the flexibility you need. The text field get Drupal default setting since for the sake of simplicity choose to omit any field settings.

<?php
$instance
= array(
 
'field_name' => $field['field_name'],
 
'entity_type' => 'node',
 
'bundle' => 'article',
);
field_create_instance($instance);
?>

This add the field to the node. The very minimum you need to pass to field_create_instance() is the name of the field you plan to attach, the entity type, and the name of the bundle.

Grab the demo_field code

Code can be found in my github repo.

Comments

Why is this a problem? Did you mean programmatically?

Obs, not problem except my spelling :) Node title corrected.

Hi, You should be using the above the code in hook_install and hook_uninstall instead of hook_enable and hook_disable. Also you should use drupal_set_message() in order to print a message instead "print".

I was aiming for simplicity by using hook_enable()/hook_disable(). Tried give a simple example on how field get created and removed, without having tell the user to remember to uninstall the module after they turned it and so on. Yeah, I should have used drupal_set_message(). I mostly work with drush these days, so I forget to think about users enable it through the UI.

How come there are <strong> HTML tags in your code examples?

Interesting. It is actually the markdown input filter that messes up the docblock's. I'll look into it, perhaps try and alter the order of mardown vs codefilter.

It can sometimes be difficult to figure out what goes into the arrays that you pass to field_create_field and field_create_instance, especially if you have detailed configuration about the field that you want to capture. I've found it useful to add the field through the admin ui, enable the Features module on my local dev site, export my content type, then copy/paste the arrays from the .features.field.base.inc and .features.field.instance.inc files into my module's .install file. (Then disable the Features module on my local dev site.)