You are here
Drupal 7 - A Simple Content Type: Text fields and areas
This post builds upon a previous post: Drupal 7 - A Simple Content Type
Text fields and areas are one of the main ways to gather data from users whether they are filling out your site contact form or submitting an article to your site. Our Simple Content Type already contains a text field, the title, and a text area, the body, although they are not declared that way. The title field is the only default field for nodes and we will use one in this example but we will not include a body in this version of Simple Content Type as we already know how to add a body to our content types and having the body field will just clutter up the display. Let's get started by uninstalling any previous copies of the Simple Content Type module. Next, let's add three fields: one text field and two text areas, one with format filters and one without. Here is our updated hook_install() function:
function simple_content_type_install() {
// create the simple content type
node_types_rebuild();
$types = node_type_get_types();
// create all the fields we are adding to our content type
foreach (_simple_content_type_installed_fields() as $field) {
field_create_field($field);
}
// create all the instance for our fields
foreach (_simple_content_type_installed_instances() as $instance) {
$instance['entity_type'] = 'node';
$instance['bundle'] = 'simple_content_type';
field_create_instance($instance);
}
// disable comments for this content type
variable_set('comment_simple_content_type', COMMENT_NODE_CLOSED);
}
Just like in other examples we use two foreach statements coupled with functions that return associative arrays to make the task of adding fields to our content type easy. We could just stuff the settings into the install function but using functions for this task makes the code more readable. We next need to modify the uninstall hook to delete any fields we created for our content type. Here is our hook_uninstall() function:
function simple_content_type_uninstall() {
// gather all the content while the module was enabled
$sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
$result = db_query($sql, array(':type' => 'simple_content_type'));
$nids = array();
foreach ($result as $row) {
$nids[] = $row->nid;
}
// delete all the nodes at once
node_delete_multiple($nids);
// delete all the fields defined by this module
foreach (array_keys(_simple_content_type_installed_fields()) as $field) {
field_delete_field($field);
}
// delete any remaining field instances attached to this content type
$instances = field_info_instances('node', 'simple_content_type');
foreach ($instances as $instance_name => $instance) {
field_delete_instance($instance);
}
// delete our content type
node_type_delete('simple_content_type');
// purge all field information
field_purge_batch(1000);
}
Both of the functions we are using in the above hooks reside in a file called 'simple_content_type_functions.inc'. This file will hold all the non-hook functions we code for use in our hooks. In order to use the functions in this file we need to add the new functions file to the .install file:
require_once('simple_content_type_functions.inc');
We could also add this file include to the .module file to share functions, but in our example we have no need for it there. Our file, simple_content_type_functions.inc, has two functions:
function _simple_content_type_installed_fields() {
// textfield
$fields['simple_content_type_textfield'] = array(
'field_name' => 'simple_content_type_textfield',
'label' => t('A Textfield'),
'type' => 'text',
'module' => 'text',
);
// text area without filters
$fields['simple_content_type_textarea'] = array(
'field_name' => 'simple_content_type_textarea',
'label' => t('A Textarea'),
'type' => 'text_long',
'module' => 'text',
'translatable' => '1',
'foreign keys' => array(
'format' => array(
'columns' => array(
'format' => 'format',
),
'table' => 'filter_format',
),
),
'indexes' => array(
'format' => array(
0 => 'format',
),
),
);
// text area with filters
$fields['simple_content_type_txtarea_fltr'] = array(
'field_name' => 'simple_content_type_txtarea_fltr',
'label' => t('A Textarea with format filters'),
'type' => 'text_long',
'module' => 'text',
'translatable' => '1',
'foreign keys' => array(
'format' => array(
'columns' => array(
'format' => 'format',
),
'table' => 'filter_format',
),
),
'indexes' => array(
'format' => array(
0 => 'format',
),
),
);
return $fields;
}
function _simple_content_type_installed_instances() {
// textfield
$instances['simple_content_type_textfield'] = array(
'field_name' => 'simple_content_type_textfield',
'type' => 'text',
'label' => t('A Textfield'),
'widget' => array(
'type' => 'text_textfield',
'weight' => '-1',
'settings' => array(
'size' => '20',
'max_length' => '100',
),
),
'display' => array(
'default' => array(
'label' => 'inline',
'settings' => array(),
'type' => 'text_default',
'weight' => -1,
),
'teaser' => array(
'label' => 'above',
'settings' => array(),
'type' => 'hidden',
'weight' => -1,
),
),
);
// textarea without filters
$instances['simple_content_type_textarea'] = array(
'field_name' => 'simple_content_type_textarea',
'type' => 'text_long',
'label' => t('A Textarea'),
'widget' => array(
'settings' => array(
'rows' => '5',
),
'type' => 'text_textarea',
'weight' => 0,
),
'display' => array(
'default' => array(
'label' => 'above',
'settings' => array(),
'type' => 'text_default',
'weight' => 0,
),
'teaser' => array(
'label' => 'above',
'settings' => array(),
'type' => 'hidden',
'weight' => 0,
),
),
'required' => 0,
'settings' => array(
'text_processing' => '0',
'user_register_form' => FALSE,
),
);
// textarea with filters
$instances['simple_content_type_txtarea_fltr'] = array(
'field_name' => 'simple_content_type_txtarea_fltr',
'type' => 'text_long',
'label' => t('A Textarea with format filters'),
'widget' => array(
'settings' => array(
'rows' => '5',
),
'type' => 'text_textarea',
'weight' => 1,
),
'display' => array(
'default' => array(
'label' => 'above',
'settings' => array(),
'type' => 'text_default',
'weight' => 1,
),
'teaser' => array(
'label' => 'above',
'settings' => array(),
'type' => 'hidden',
'weight' => 1,
),
),
'required' => 0,
'settings' => array(
'text_processing' => '1',
'user_register_form' => FALSE,
),
);
return $instances;
}
We start by defining a text field with a size of 20 and a maximum length of 100 characters. By defining these values when creating the fields we tell Drupal to place these restrictions on all instances of that field when validating any data submitted through them. Next we set up two almost identical text areas. Text areas are similar to text fields in that you can define the size of the area to present but instead of using 'size' and 'maxlength' we need to use 'rows' and 'cols'. Our text areas are the same size but do have one crucial difference which dramatically alters there functionality: text_processing. By setting 'text_processing' to 0 in the first text area we disallow format filters from being used on the text in the area. Setting 'text_processing' to 1 allows format filters to be used which can provide a multitude of options to the user. Install and test and you should see something like below:
Download the source for this example.
- Add new comment
- 5 comments


Wonderful job!
Firstly I want to thank you for helping me with making my first steps into Drupal module development. I couldn't find so nice and well explained examples into the whole Internet!
Secondly, I have a question:
I tried to add a custom validation but for some reason it doesn't work. Here is what I do in the .module file.
//Add a function that should be called when validating.
function simple_content_type_form_alter($form, $form_state, $form_id){
if ($form_id=='simple_content_type_node_form'){
$form['#validate'][] = 'validate_simple_content_type';
}
}
//and here is the function itself.
function validate_simple_content_type($form_state){
dsm('I work!');
form_set_error('test_error', t('This is a test return of an error.'));
}
10x in advance.
Rework the validation function
You are missing a parameter for your validation function. Try the following:
function validate_simple_content_type($form, &$form_state){
dsm('I work!');
form_set_error('test_error', t('This is a test return of an error.'));
}
It didn't work as well. As I
It didn't work as well. As I analyzed it a bit I found out the the validating function doesn't execute at all.I tried with placing "break or die" functions in the validation-No effect(Site worked perfectly). Also tried placing a Breakpoint in the function and debugged it. And the site was working perfectly(didn't stop at the breakpoint). If I check the "#validate" array I see I've added the function successfully.
0 (String, 18 characters ) node_form_validate | (Callback) node_form_validate();
1 (String, 28 characters ) validate_simple_content_type | (Callback) validate_simple_content_type();
Can you comment where the simple_content_type is the name?
Hi, even in the official 'examples' module, there's the same problem. node_example is both the name of the module, AND the content type that is being created. So it becomes confusing when I try to copy this and create my own content type - where does the module name go, and where does the content type's? BTW, thanks, you are alone making a good effort like this :)
Content Type Name
The name of your new Content Type is set in the hook_node_info() function for your module which should be in your MODULE.module file. You can see an example of this in the first version of this example. You would set the 'name' value for a new node type to the name for your new content type. The module name is set in the MODULE.info file along with some other module specific data. I have added comments to the first version of this example to help identify these.
Post new comment