Building blocks of Drupal
Everything is an entity in Drupal. Everything starts like an entity anyway; Node is a kind of entity, user as well, entities – just specialized. If you are familiar with OOP, this is very basic stuff. When dealing with content, at the top of the hierarchy, we have the content type, which his is kind of a blueprint for the node. To generalize even further – we have the field that’s kind of a blueprint for a field instance.
Drupal, out-of-the-box installation includes two content types: Article and Basic page. If you take a look at the field list for the content type Article (admin/structure/types/manage/article/fields), you’ll find Title, Body, image, etc. The field Title that you see at the top of the list is not technically field as the rest of them, it’s part of the node – you’ll see that in a minute.
Nodes are stored in the database table called node. If you take a look you’ll find a column called title. However, all other fields from that content type field list have their own database tables. Actually, make that two; one for the current data and another for revisions.
For example, field called Body has its own tables called field_data_body & field_revision_body. If you’re nosy as I am, you have probably already seen that the content type Article has a field called body as well as the content type Basic page. Then how come there is only one table in the database? That’s correct; both field instances of the field Body are using the same database table, field_data_body.
So you can define a field with certain ground settings but use many instances of it, on bunch of different places. All instances of this one field, store their data on the same place, in the same database table.
List of created fields and their settings are stored in the database table called field_config. Field instances and settings regarding these are stored in to the field_config_instance table.
- id – The primary identifier for a field.
- field_name – The name of this field. Non-deleted field names are unique, but multiple deleted fields can have the same name.
- type – The type of this field.
- module – The module that implements the field type.
- active – Boolean indicating whether the module that implements the field type is enabled.
- storage_type – The storage backend for the field.
- storage_module – The module that implements the storage backend.
- storage_active – Boolean indicating whether the module that implements the storage backend is enabled.
- locked – Field can or can not be altered by users.
- data – Serialized data containing the field properties that do not warrant a dedicated column.
- cardinality – Sets the number of values one can enter in this field, FIELD_CARDINALITY_UNLIMITED for unlimited.
- translatable – If value(s) in this field are translatable.
- deleted – Is this field deleted
- id – The primary identifier for a field instance
- field_id – The identifier of the field attached by this instance
- field_name – The textual identifier of the field attached by this instance
- entity_type – This is might say node or user…
- bundle – Often the machine name of the content type (article, page)
- data *
- deleted – Is this field deleted
Field types out-of-the-box are listed below, machine name of the field type is the highlighted one. You’ll need this later when it’s time to programmatically create one.
- Boolean :: list_boolean
- Decimal :: number_decimal
- File :: file
- Float :: number_float
- Image :: image
- Integer :: number_integer
- List (float) :: list_float
- List (integer) :: list_integer
- List (text) :: list_text
- Long text :: text_long
- Long text and summary :: text_with_summary
- Term reference :: taxonomy_term_reference
- Text :: text
There are other field types that ship with contributed modules. Some of the usual ones are:
- Node reference node_reference Part of the references module
- User reference user_reference Part of the references module
- Relation relation Pretty young module with lots of potential
Ok let’s have a look at some code, shell we… First we’ll go trough creating fields and instances, then deletion and at last some cool query possibilities that came along in Drupal 7.
Creating fields programmatically
There isn’t much to say here. You pass an associative array to field_create_field(array $options). Have a look at the function page for the details on options. You’ll probably get a runaround until you find what you’re looking for fun.
field_create_field(array( ‘field_name’ => ‘color’, ‘type’ => ‘text’, ‘cardinality’ => 1, ‘settings’ => array(), ‘entity_types’ => array(‘user’, ‘node’), ));
You might consider to check if the field exists before creating one… field_info_field(string $field_name).
Creating field instances programmatically
Then after you have created a field, you need an instance to be able to use it. After you create the field instance Drupal will make sure that your instance is attached to the wanted content type (bundle). There are many properties/settings for field instance creation. I’ll name a few usual and some are covered in the Field API.
field_create_instance(array( ‘field_name’ => ‘color’, ‘entity_type’ => ‘user’, /* Attaches the field instance to the User account */ ‘bundle’ => ‘user’, ‘label’ => t(‘Eye color’), ‘description’ => t(‘Your eye color’), ‘widget’ => array( ‘type’ => ‘text_textarea’, ‘weight’ => 0, ‘settings’ => array(‘size’ => 50), ), ‘display’ => array( ‘default’ => array( ‘label’ => ‘above’, ‘settings’ => array(), ‘weight’ => 1, ), ‘teaser’ => array( ‘label’ => ‘above’, ‘settings’ => array(), ‘type’ => ‘hidden’, ), ), ‘required’ => TRUE, )); // Another instance of the same field // “color”, with slightly different settings. field_create_instance(array( ‘field_name’ => ‘color’, ‘entity_type’ => ‘node’, /* Attaches the instance to the content type Article */ ‘bundle’ => ‘article’, ‘label’ => t(‘Color’), ‘description’ => t(‘Your favorite color’), ));
There are tons of different settings at your disposal and they vary with different types of fields and widgets. You can always print out the structure of an existing field to see its settings.
// Gets you the structure of the field we created above. print_r(field_info_field(‘color’)); // Gets you the structure of the second // field instance we created earlier. print_r(field_info_instance( ‘node’, /* Entity type */ ‘color’, /* Name of the field for this instance */ ‘article’ /* Name of the bundle */ ));
Field instance widgets
These are the usual widgets, however, any module can introduce its own widgets if needed.
- options_buttons – (Check boxes/radio buttons)
- options_onoff – (Single on/off checkbox)
- options_select – (Select list)
- text_textarea_with_summary – (Text area with a summary)
- text_textarea – (Text area)
- text_textfield – (Text field)
- relation_default – (Relation dummy widget)
- number – (Text field)
- image_image – (Image)
- file_generic – (File)
- taxonomy_autocomplete – (Autocomplete term widget)
- user_reference_autocomplete – (Autocomplete text field)
- node_reference_autocomplete – (Autocomplete text field)
Deleting fields & field instances programmatically
Pretty straight forward here as well.
// Fetch the instance (object) $field = field_info_instance(‘node’, ‘color’, ‘article’); // Delete it. field_delete_instance($field); // Fetch the instance (object) $field = field_info_field(‘color’); // Delete it field_delete_field($field);
Note that if you call the field_delete_instance() on a last instance of a field, It will remove the field as well.
Querying entities using cool field conditions
To make your life easier, Drupal comes with something called Database abstraction layer.
Here is a scenario: get only articles that have the word “drupal” in their title and were tagged with the term id 4.
Two things we need to remember here. As I mentioned earlier, title is not a field, it’s a property, stored in the node table. Second thing is that the content type article has a field called tags, which is of type taxonomy_term_reference – this means that the value stored in the field is a taxonomy term id (tid).
Depending on the type of the field we are dealing with, value parameter must be referenced to accordingly: taxonomy_term_reference (tid), node_reference (nid), user_reference (uid), text (value), etc…
$query = new EntityFieldQuery(); // We are looking for a node $query->entityCondition(‘entity_type’, ‘node’) // Bundle (the content type) is the Article ->entityCondition(‘bundle’, ‘article’) // Title should contain the word “drupal”, just like // I promised, it’s a node property and not a field. ->propertyCondition(‘title’, ‘drupal’, ‘CONTAINS’) // Since the field tags is a taxonomy_term_reference, // we are looking for a “tid”. ->fieldCondition(‘tags’, ‘tid’, 4); // Just can keep chaining these until you’re happy… print_r($query->execute()); // voila
There you go – EntityFieldQuery, cool stuff!? Note to self: memorize! 🙂
Handling field data while working with nodes and other entities
Most of the time I end up working with the field data by handling a node object or other similar entities.
// Node $nid = 1; // Get the node object $node = node_load($nid); // Check if the field exists && assign the field value. isset($node->my_special_field) && ($node->my_special_field[$node->language][‘value’] = ‘My value’); // Save the field node_save($node); // Potential problem with the example above is that you // need know a lot about the field to be able to set/get // its value. There is a drupal function (below) but // you still need to know same things about the field. // // Solution: write your own function that gets // you your values hassle-free 🙂 // User $uid = 1; $user = user_load($uid); $field_values = field_get_items(‘user’, $user, ‘my_special_field’); print_r($field); /* You should see something like this, depending on the type of the field. Array (  => Array ( [value] => This is the first special value [format] => [safe_value] => This is the first special value )  => Array ( [value] => This is the second special value [format] => [safe_value] => This is the second special value ) ) */