Have you ever been in a situation where you needed to collect a certain type of data on a node form and display it in a certain way that wasn't supported by the core Drupal field types? Rather than using a text field to display something like a phone number or email address, you may consider using the phone or email modules instead, both of which are perfect examples of why you may need to define your own custom field types.
For the sake of this example we will define a field type for inputting a vehicle license plate number and state (I have no idea why you would need this). First, we'll need to define the types of data stored in these fields in the .install file using hook_schema.
Next, tell the fields module about your new field type using hook_field_info in your .module file. The widget is the input form and the formatter is the field display.
Create your field widget type(s) using hook_field_widget_info. You'll select the widget when adding the field to a content type, which would allow you to specify multiple input formats for this particular field. In most cases, you'll probably only need one of these (or none if you're using one of the core widgets). In this case, since we're collecting the plate number and state as separate pieces of data, we'll need to create a widget with those fields.
You can define the field settings form using hook_field_settings_form. This will show up in the Global Settings sections of the field configuration page upon adding it to the node and will apply to this field across all instances of it.
You can also use hook_field_instance_settings_form to define settings that are specific to the entity type which you are adding the field to. This would enable you to use the same field across different content types and change these settings.
The input form (ie: widget) can be built using hook_field_widget_form. The switch case is necessary if you're defining multiple widgets.
hook_field_presave can be used to prepare the data from the widget to be inserted into the database. Since our widget uses multiple fields nested inside a fieldset, we will need to map the field values to the correct place in the data array to be nested in the database.
Use hook_field_is_empty to tell Drupal how to check if the field is empty and handle it accordingly. This is necessary if you mark the field as required.
Now setup the field validation callback with hook_field_validate. In this case we really don't need any validation, but in case you do, here's how to do it.
Now you'll need to define your formatter(s) and specify the field output using hook_field_formatter_info and hook_field_formatter_view.
And voila! a shiny new license plate field type for use anywhere on your entities, nodes, and users.
Was this post helpful to you? Share your comments below!