function field_create_field

You are here

7 field.crud.inc field_create_field($field)

Creates a field.

This function does not bind the field to any bundle; use field_create_instance() for that.

Parameters

$field: A field definition array. The field_name and type properties are required. Other properties, if omitted, will be given the following default values:

  • cardinality: 1
  • locked: FALSE
  • indexes: the field-type indexes, specified by the field type's hook_field_schema(). The indexes specified in $field are added to those default indexes. It is possible to override the definition of a field-type index by providing an index with the same name, or to remove it by redefining it as an empty array of columns. Overriding field-type indexes should be done carefully, for it might seriously affect the site's performance.
  • settings: each omitted setting is given the default value defined in hook_field_info().
  • storage:
    • type: the storage backend specified in the 'field_storage_default' system variable.
    • settings: each omitted setting is given the default value specified in hook_field_storage_info().

Return value

The $field array with the id property filled in.

Throws

FieldException

See: Field API data structures.

Related topics

74 calls to field_create_field()
AJAXMultiFormTestCase::setUp in modules/simpletest/tests/ajax.test
Sets up a Drupal site for running functional and integration tests.
EntityFieldQueryTestCase::setUp in modules/simpletest/tests/entity_query.test
Sets up a Drupal site for running functional and integration tests.
FieldAttachStorageTestCase::testFieldAttachDeleteBundle in modules/field/tests/field.test
Test field_attach_delete_bundle().
FieldAttachStorageTestCase::testFieldAttachLoadMultiple in modules/field/tests/field.test
Test the 'multiple' load feature.
FieldAttachStorageTestCase::testFieldAttachSaveLoadDifferentStorage in modules/field/tests/field.test
Test saving and loading fields using different storage backends.

... See full list

File

modules/field/field.crud.inc, line 56
Field CRUD API, handling field and field instance creation and deletion.

Code

function field_create_field($field) {
  // Field name is required.
  if (empty($field['field_name'])) {
    throw new FieldException('Attempt to create an unnamed field.');
  }
  // Field type is required.
  if (empty($field['type'])) {
    throw new FieldException('Attempt to create a field with no type.');
  }
  // Field name cannot contain invalid characters.
  if (!preg_match('/^[_a-z]+[_a-z0-9]*$/', $field['field_name'])) {
    throw new FieldException('Attempt to create a field with invalid characters. Only lowercase alphanumeric characters and underscores are allowed, and only lowercase letters and underscore are allowed as the first character');
  }

  // Field name cannot be longer than 32 characters. We use drupal_strlen()
  // because the DB layer assumes that column widths are given in characters,
  // not bytes.
  if (drupal_strlen($field['field_name']) > 32) {
    throw new FieldException(t('Attempt to create a field with a name longer than 32 characters: %name', array('%name' => $field['field_name'])));
  }

  // Ensure the field name is unique over active and disabled fields.
  // We do not care about deleted fields.
  $prior_field = field_read_field($field['field_name'], array('include_inactive' => TRUE));
  if (!empty($prior_field)) {
    $message = $prior_field['active'] ? t('Attempt to create field name %name which already exists and is active.', array('%name' => $field['field_name'])) : t('Attempt to create field name %name which already exists, although it is inactive.', array('%name' => $field['field_name']));
    throw new FieldException($message);
  }

  // Disallow reserved field names. This can't prevent all field name
  // collisions with existing entity properties, but some is better
  // than none.
  foreach (entity_get_info() as $type => $info) {
    if (in_array($field['field_name'], $info['entity keys'])) {
      throw new FieldException(t('Attempt to create field name %name which is reserved by entity type %type.', array('%name' => $field['field_name'], '%type' => $type)));
    }
  }

  $field += array(
    'entity_types' => array(),
    'cardinality' => 1,
    'translatable' => FALSE,
    'locked' => FALSE,
    'settings' => array(),
    'storage' => array(),
    'deleted' => 0,
  );

  // Check that the field type is known.
  $field_type = field_info_field_types($field['type']);
  if (!$field_type) {
    throw new FieldException(t('Attempt to create a field of unknown type %type.', array('%type' => $field['type'])));
  }
  // Create all per-field-type properties (needed here as long as we have
  // settings that impact column definitions).
  $field['settings'] += field_info_field_settings($field['type']);
  $field['module'] = $field_type['module'];
  $field['active'] = 1;

  // Provide default storage.
  $field['storage'] += array(
    'type' => variable_get('field_storage_default', 'field_sql_storage'),
    'settings' => array(),
  );
  // Check that the storage type is known.
  $storage_type = field_info_storage_types($field['storage']['type']);
  if (!$storage_type) {
    throw new FieldException(t('Attempt to create a field with unknown storage type %type.', array('%type' => $field['storage']['type'])));
  }
  // Provide default storage settings.
  $field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
  $field['storage']['module'] = $storage_type['module'];
  $field['storage']['active'] = 1;
  // Collect storage information.
  module_load_install($field['module']);
  $schema = (array) module_invoke($field['module'], 'field_schema', $field);
  $schema += array(
    'columns' => array(),
    'indexes' => array(),
    'foreign keys' => array(),
  );
  // 'columns' are hardcoded in the field type.
  $field['columns'] = $schema['columns'];
  // 'foreign keys' are hardcoded in the field type.
  $field['foreign keys'] = $schema['foreign keys'];
  // 'indexes' can be both hardcoded in the field type, and specified in the
  // incoming $field definition.
  $field += array(
    'indexes' => array(),
  );
  $field['indexes'] += $schema['indexes'];

  // The serialized 'data' column contains everything from $field that does not
  // have its own column and is not automatically populated when the field is
  // read.
  $data = $field;
  unset($data['columns'], $data['field_name'], $data['type'], $data['active'], $data['module'], $data['storage_type'], $data['storage_active'], $data['storage_module'], $data['locked'], $data['cardinality'], $data['deleted']);
  // Additionally, do not save the 'bundles' property populated by
  // field_info_field().
  unset($data['bundles']);

  $record = array(
    'field_name' => $field['field_name'],
    'type' => $field['type'],
    'module' => $field['module'],
    'active' => $field['active'],
    'storage_type' => $field['storage']['type'],
    'storage_module' => $field['storage']['module'],
    'storage_active' => $field['storage']['active'],
    'locked' => $field['locked'],
    'data' => $data,
    'cardinality' => $field['cardinality'],
    'translatable' => $field['translatable'],
    'deleted' => $field['deleted'],
  );

  // Store the field and get the id back.
  drupal_write_record('field_config', $record);
  $field['id'] = $record['id'];

  // Invoke hook_field_storage_create_field after the field is
  // complete (e.g. it has its id).
  try {
    // Invoke hook_field_storage_create_field after
    // drupal_write_record() sets the field id.
    module_invoke($storage_type['module'], 'field_storage_create_field', $field);
  }
  catch (Exception $e) {
    // If storage creation failed, remove the field_config record before
    // rethrowing the exception.
    db_delete('field_config')->condition('id', $field['id'])->execute();
    throw $e;
  }

  // Clear caches
  field_cache_clear(TRUE);

  // Invoke external hooks after the cache is cleared for API consistency.
  module_invoke_all('field_create_field', $field);

  return $field;
}

Comments

i don't understand the purpose of this function's return value and specifically the id property of the field .

field_create_instance needs only the name of the field for field_name , in other words it doesn't require the structure returned by this function

Example on how to programatically add fields to the user profile and how to avail them, or not, into the User Registration form.

<?php
/**
* Implementation of hook_enable().
*/
function MYMODULE_enable() {
 
// Check if our field is not already created.
 
if (!field_info_field('field_myField')) {
   
$field = array(
       
'field_name' => 'field_myField',
       
'type' => 'text',
    );
   
field_create_field($field);

   

// Create the instance on the bundle.
   
$instance = array(
       
'field_name' => 'field_myField',
       
'entity_type' => 'user',
       
'label' => 'My Field Name',
       
'bundle' => 'user',
       
// If you don't set the "required" property then the field wont be required by default.
       
'required' => TRUE,
       
'settings' => array(
          
// Here you inform either or not you want this field showing up on the registration form.
           
'user_register_form' => 1,
        ),
       
'widget' => array(
           
'type' => 'textfield',
        ),
    );
   
field_create_instance($instance);
  }

}

?>

It doesn't look like the 'no_ui' seeting is working properly as of Drupal 7.10.

I have this

<?php
  $field
['settings']['no_ui'] = TRUE;
?>

however, even with this, other content types can add the field from the UI.

Is there anyway to stop this?

thanks!
david barratt

Hi,

I know this is a very old question, but maybe this can help others:

As far as I understand it, the no_ui setting is set in hook_field_info, where the field type is declared.

field_create_field only creates a field based on an existing field type, and my guess it that no_ui can't be overridden on individual fields or their instances.

You would probably have to replicate the code from the appropriate hook_field_info, rename the field type to something else, set no_ui to TRUE, then use that new type when you create your field.

Davidwbarratt is right and "no_ui" is being flatout ignored for fields and instances. You are right that currently "no_ui" is being checked on field_type level only. But in my opinion you should be able to do so for any programatically created field even if you use an existing field type. So I think field_ui should be altered...

But like you said. It might be a far more faster approach to define your own field type instead of trying to get a one-liner patch through for field_ui.

Looks like I didn't read the documentation well myself. If you don't want your field to be re-used or deleted than you have to set the "locked" parameter to TRUE...

$field['no_ui'] = TRUE;

Here I programmatically create & instantiate a field called 'MYMODULE_rating'. The field is defined in the same module which tries to create it in hook_enable()

MYMODULE.install

<?php
/** Implements hook_enable()
*/
function MYMODULE_enable(){
   
# Use me. Otherwise, I won't work because I don't know your custom defined fields ]:->
   
field_cache_clear();
   
field_associate_fields('MYMODULE');

   

# Already created?
   
if (field_info_field('MYMODULE_rating'))
        return;

   

# Create the field singleton
   
$field = array( 'field_name' => 'MYMODULE_rating', 'type' => 'MYMODULE_rating', );
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance = array(
       
'field_name' => $field['field_name'],
       
'entity_type' => 'node',
       
'bundle' => 'wine',

       

'label' => 'Rating',
       
'description' => 'Rating information',

       

'required' => TRUE,

       

'settings' => array(),
       
'widget' => array(),

       

'display' => array(
           
'default' => array('label' => 'hidden'),
        ),
    );
   
field_create_instance($instance);

   

$instance['bundle'] = 'review';
   
field_create_instance($instance);
}
?>

For the curious: the field was declared in MYMODULE.field.inc:

<?php
/** Implements hook_field_info() */
function MYMODULE_field_info(){
   
# Rating field
   
$fields['MYMODULE_rating'] = array(
       
'label' => t('Rating'),
       
'description' => t('rating information'),
       
'settings' => array(),
       
'instance_settings' => array(),
       
'default_widget' => 'MYMODULE_hidden',
       
'default_formatter' => 'MYMODULE_rating',
    );
    return
$fields; # Get all field types with: field_info_field_types()
}

// ... also implemented the default_widget, default_formatter & hook_field_load()
?>

Hello,

I've implemented the second comment, but my field won't show up in user registration form although it has been created. What am I missing?

Regards,

Is the 32 chars field maxlen limit really necessary?

My question comes out of a practical problem encountered due to this limitation: I tried using the Bundle copy module (http://drupal.org/project/bundle_copy) to create several sub-types of the Media gallery content type (http://drupal.org/project/media_gallery) and that failed with:

FieldException: Attempt to create a field with a name longer than 32 characters: media_sp_gallery_image_info_where in field_create_field() (line 74 of /home1/dvdsamer/public_html/webpagesforlife/velkova/modules/field/field.crud.inc).

To reproduce the above error you can export the Gallery bundle and replace all occurences of 'media_gallery' with 'media_sp_gallery' in the export text. Then import. As you can see I only added 3 extra chars to the original field name and yet it now failes because of the 32 chars limit...

So - my question is: is it safe to extend this limit in the field.crud.inc file to, say 64?

... ok a quick test with the check changed to a max of 64 resulted in lots of errors which look pretty bad so I guess it is a 'NO' then...

:(

How can I get the list of type property for defining different field types?

tell me please how to define options of a list_text type field

After some digging around, I found that modules which implement hook_field_info() contain all the information that you need. Just use the search "Function, file, or topic" box to search for "_field_info" and then choose the module whose field info you are looking for from the list it presents you. In our case, we are looking for "list_field_info".

For example, according to:
https://api.drupal.org/api/drupal/modules!field!modules!list!list.module...

<?php
  $field
= array(
   
'field_name' => 'field_example_options_select',
   
'type' => 'list_text',
   
'settings' => array(
     
'allowed_values' => array(
       
'option1' => 'Option Number 1',
       
'option2' => 'Option Number 2',
       
'option3' => 'Option Number 3',
      ),
    ),
  );
 
field_create_field($field);
?>

Should be the data structure for a list_text field.

Here a simple function to add some files to your profile.

<?php
function mymodule_enable() {

 

field_cache_clear();
 
field_associate_fields('user_alternative');

 

// First Name - field_first_name - Text - Text field
 
if (!field_info_field('field_first_name')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_first_name', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_first_name'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'First Name',
     
'description' => 'Type in your first name. The system creates from it and the last name your username.',
     
'required' => TRUE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
   
drupal_set_message($field['field_name'].' was created.');
  }

 

// Last Name - field_last_name - Text -    Text field
 
if (!field_info_field('field_last_name')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_last_name', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_last_name'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Last Name',
     
'description' => 'Type in your last name. The system creates from it and the first name your username.',
     
'required' => TRUE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
   
drupal_set_message($field['field_name'].' was created.');
  }
 
 
// Occupation - field_occupation          Text    Text field
 
if (!field_info_field('field_occupation')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_occupation', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_occupation'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Occupation',
     
'description' => 'Type in your occupation the the community can see it and maybe it will help them to answer your questions / posts in the forum.',
     
'required' => FALSE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
   
drupal_set_message($field['field_name'].' was created.');
  }

 

// Company - field_company - Text  Text field
 
if (!field_info_field('field_company')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_company', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_company'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Company',
     
'description' => 'If you want to <a href="/user/upgrade"> upgrade your account </a> you have to enter this so the supporters are able to grant your request.',
     
'required' => FALSE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
drupal_set_message($field['field_name'].' was created.');
  }
 
 
// Branch of industry - field_branch_of_industry    Text    Text field
 
if (!field_info_field('field_branch_of_industry')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_branch_of_industry', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_branch_of_industry'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Branch of industry',
     
'description' => 'In which branch of industry is your company active?',
     
'required' => FALSE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
   
drupal_set_message($field['field_name'].' was created.');
  }
 
 
// Department - field_department          Text  Text field
 
if (!field_info_field('field_department')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_department', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_department'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Department',
     
'description' => 'In which department of your company are you working?',
     
'required' => FALSE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
   
drupal_set_message($field['field_name'].' was created.');
  }
 
 
// Tel -field_tel - Text    Text field
 
if (!field_info_field('field_tel')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_tel', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_tel'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Tel',
     
'description' => 'Enter your Bussnis number so ower Supporters can reach you better. <br>
                        <strong>This field can only be seen from ower supportes.</strong>'
,
     
'required' => FALSE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
   
drupal_set_message($field['field_name'].' was created.');
  }
 
 
// Mobile - field_mobile -  Text    Text field
 
if (!field_info_field('field_mobile')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_mobile', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_mobile'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Mobile',
     
'description' => 'Enter your Business mobile number so our Supporters can reach you even better.<br>
                        <strong>This field can only be seen from our supporters.</strong>'
,
     
'required' => FALSE,
     
'settings' => array(
       
'user_register_form' => 0,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
   
drupal_set_message($field['field_name'].' was created.');
  }
 
 
// Street - field_street -  Text    Text field
 
if (!field_info_field('field_street')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_street', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_street'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Street',
     
'description' => 'Type in the street where your company is located. So our supporters can grant your upgrade even faster.',
     
'required' => FALSE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
   
drupal_set_message($field['field_name'].' was created.');
  }
 
 
// Zip Code - field_zip_code            Text    Text field
 
if (!field_info_field('field_zip_code')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_zip_code', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_zip_code'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Zip Code',
     
'description' => 'Type in the zipcode of the town where your company is located. So our supporters can grant your upgrade even faster.',
     
'required' => FALSE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
   
drupal_set_message($field['field_name'].' was created.');
  }
 
 
// Town - field_town -    Text    Text field
 
if (!field_info_field('field_town')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_town', 'type' => 'text',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_town'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Town',
     
'description' => 'Type in the town where your company is located. So our supporters can grant your upgrade even faster.',
     
'required' => FALSE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'textfield',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
  }
 
 
//  Country - field_country - Country    Select list
 
if (!field_info_field('field_country') && module_exists('countries')) {
   
# Create the field singleton
   
$field = array('field_name' => 'field_country', 'type' => 'country',);
   
$field = field_create_field($field);

   

# Create the instance on the bundle.
   
$instance['field_country'] = array(
     
'field_name' => $field['field_name'],
     
'entity_type' => 'user',
     
'bundle' => 'user',
     
'label' => 'Rating',
     
'description' => 'Rating information',
     
'required' => TRUE,
     
'settings' => array(
       
'user_register_form' => 1,
      ),
     
'widget' => array(
       
'type' => 'Select list',
      ),
     
'display' => array(
       
'default' => array('label' => 'hidden'),
      ),
    );
   
   
drupal_set_message($field['field_name'].' was created.');
  }
 
 
dsm($instance);
  if(!empty(
$instance)){
    foreach (
$instance as $instance_field){
     
field_create_instance($instance_field);
    }
   }
}

?>

It seems that the purpose of $field['entity_types'] is to limit the entities to which the field can be attached. If it isn't supplied, it gets set to an empty array and can be attached to all fieldable entities.