This was my entities and fields presentation from Drupalcamp Colorado 2020.
http://drupalcampcolorado.org/sessions/drupal-7-entities-and-fields-transitioning-d7
4. D7 Code Sprint
• We will be discussing code
• If you are not a coder this
will probably be incredibly
boring to you and you risk
being put to sleep :-D
5. D7 Code Sprint
• We will be discussing code
• If you are not a coder this
will probably be incredibly
boring to you and you risk
being put to sleep :-D
10. The Next Hour
• Discuss key concepts in Drupal 7: Bundles,
Entities and Fields
11. The Next Hour
• Discuss key concepts in Drupal 7: Bundles,
Entities and Fields
• Walk through the creation of a content type
that will add a Bundle of Fields complete
with custom Formatters to the node
Entity
12. The Next Hour
• Discuss key concepts in Drupal 7: Bundles,
Entities and Fields
• Walk through the creation of a content type
that will add a Bundle of Fields complete
with custom Formatters to the node
Entity
• Explain WTH that last comment meant
13. The Next Hour
• Discuss key concepts in Drupal 7: Bundles,
Entities and Fields
• Walk through the creation of a content type
that will add a Bundle of Fields complete
with custom Formatters to the node
Entity
• Explain WTH that last comment meant
• Introduce the most excellent node_example
module
15. Key Concepts
• An Entity is a container for Bundles.
Examples are Node, User, File, Taxonomy
Term, Taxonomy Vocabulary
16. Key Concepts
• An Entity is a container for Bundles.
Examples are Node, User, File, Taxonomy
Term, Taxonomy Vocabulary
• A Bundle is a set of fields that are treated as
a group by the Field API. This is similar to
the concept of a node type in D6
17. Key Concepts
• An Entity is a container for Bundles.
Examples are Node, User, File, Taxonomy
Term, Taxonomy Vocabulary
• A Bundle is a set of fields that are treated as
a group by the Field API. This is similar to
the concept of a node type in D6
• Entities can contain multiple Bundles.
18. Key Concepts
• An Entity is a container for Bundles.
Examples are Node, User, File, Taxonomy
Term, Taxonomy Vocabulary
• A Bundle is a set of fields that are treated as
a group by the Field API. This is similar to
the concept of a node type in D6
• Entities can contain multiple Bundles.
• A field defines a particular type of data that
can be attached to any entity and can be
shared between entities
19. Key Concepts
• An Entity is a container for Bundles.
Examples are Node, User, File, Taxonomy
Term, Taxonomy Vocabulary
• A Bundle is a set of fields that are treated as
a group by the Field API. This is similar to
the concept of a node type in D6
• Entities can contain multiple Bundles.
• A field defines a particular type of data that
can be attached to any entity and can be
shared between entities
• A field can have widgets and formatters
21. The Examples Module
• In my mind the best resource for learning is
The Examples Module.
22. The Examples Module
• In my mind the best resource for learning is
The Examples Module.
• This module used to live exclusively in CVS
23. The Examples Module
• In my mind the best resource for learning is
The Examples Module.
• This module used to live exclusively in CVS
• Now maintained by rfay, Dave Reid, katbailey
and ilo ... node_example is a sub-module the
Examples project
24. The Examples Module
• In my mind the best resource for learning is
The Examples Module.
• This module used to live exclusively in CVS
• Now maintained by rfay, Dave Reid, katbailey
and ilo ... node_example is a sub-module the
Examples project
• Documentation can be viewed from http://
api.drupal.org/ by following the Examples link
25. The Examples Module
• In my mind the best resource for learning is
The Examples Module.
• This module used to live exclusively in CVS
• Now maintained by rfay, Dave Reid, katbailey
and ilo ... node_example is a sub-module the
Examples project
• Documentation can be viewed from http://
api.drupal.org/ by following the Examples link
• http://drupal.org/project/examples - not just
the node module
28. D7 *.install
• We still implement hook_install() and
hook_uninstall()
29. D7 *.install
• We still implement hook_install() and
hook_uninstall()
• hook_schema() no longer needs to be
explicitly called
30. D7 *.install
• We still implement hook_install() and
hook_uninstall()
• hook_schema() no longer needs to be
explicitly called
• Database Structure will resemble D6 CCK
tables
31. D7 *.install
• We still implement hook_install() and
hook_uninstall()
• hook_schema() no longer needs to be
explicitly called
• Database Structure will resemble D6 CCK
tables
• Database Entity revisions are provided
automatically
33. D7 *.install
/**
* Implements hook_install().
*
*/
function node_example_install() {
...
}
/**
* Return a structured array defining the fields created by this content type.
*
* This is packaged in a function so it can be used in both hook_install()
* and hook_uninstall().
*/
function _node_example_installed_fields() {
...
}
34. D7 *.install
/**
* Implements hook_install().
*
*/
function node_example_install() {
...
}
/**
* Return a structured array defining the fields created by this content type.
*
* This is packaged in a function so it can be used in both hook_install()
* and hook_uninstall().
*/
function _node_example_installed_fields() {
...
}
/**
* Return a structured array defining the instances for this content type.
*
* The instance lets Drupal know which widget to use to allow the user to enter
* data and how to react in different view modes.
* This is provided as a function so that it can be used in both hook_install()
* and hook_uninstall().
*/
function _node_example_installed_instances() {
...
}
35. D7 *.install
/**
* Implements hook_install().
*
*/
function node_example_install() {
...
}
/**
* Return a structured array defining the fields created by this content type.
*
* This is packaged in a function so it can be used in both hook_install()
* and hook_uninstall().
*/
function _node_example_installed_fields() {
...
}
/**
* Return a structured array defining the instances for this content type.
*
* The instance lets Drupal know which widget to use to allow the user to enter
* data and how to react in different view modes.
* This is provided as a function so that it can be used in both hook_install()
* and hook_uninstall().
*/
function _node_example_installed_instances() {
...
}
/**
* Implements hook_uninstall().
*
*/
function node_example_uninstall() {
...
}
39. D7 *.install
• hook_install() will set up our content type
• hook_install() is where we create our fields,
if needed
• hook_install() is used to tie our fields to an
Entity as a Bundle
42. D7 *.install
function node_example_install() {
$types = node_type_get_types();
node_add_body_field($types['node_example']);
// Load the instance definition for our content type's body
// http://api.drupal.org/api/function/field_info_instance/7
$body_instance = field_info_instance('node', 'body', 'node_example');
}
43. D7 *.install
function node_example_install() {
$types = node_type_get_types();
node_add_body_field($types['node_example']);
// Load the instance definition for our content type's body
// http://api.drupal.org/api/function/field_info_instance/7
$body_instance = field_info_instance('node', 'body', 'node_example');
// Add our example_node_list view mode to the body instance display by
// instructing the body to display as a summary
$body_instance['type'] = 'text_summary_or_trimmed';
}
44. D7 *.install
function node_example_install() {
$types = node_type_get_types();
node_add_body_field($types['node_example']);
// Load the instance definition for our content type's body
// http://api.drupal.org/api/function/field_info_instance/7
$body_instance = field_info_instance('node', 'body', 'node_example');
// Add our example_node_list view mode to the body instance display by
// instructing the body to display as a summary
$body_instance['type'] = 'text_summary_or_trimmed';
// Save our changes to the body field instance.
// http://api.drupal.org/api/function/field_update_instance/7
field_update_instance($body_instance);
}
45. D7 *.install
function node_example_install() {
$types = node_type_get_types();
node_add_body_field($types['node_example']);
// Load the instance definition for our content type's body
// http://api.drupal.org/api/function/field_info_instance/7
$body_instance = field_info_instance('node', 'body', 'node_example');
// Add our example_node_list view mode to the body instance display by
// instructing the body to display as a summary
$body_instance['type'] = 'text_summary_or_trimmed';
// Save our changes to the body field instance.
// http://api.drupal.org/api/function/field_update_instance/7
field_update_instance($body_instance);
// Create all the fields we are adding to our content type.
// http://api.drupal.org/api/function/field_create_field/7
foreach (_node_example_installed_fields() as $field) {
field_create_field($field);
}
}
46. D7 *.install
function node_example_install() {
$types = node_type_get_types();
node_add_body_field($types['node_example']);
// Load the instance definition for our content type's body
// http://api.drupal.org/api/function/field_info_instance/7
$body_instance = field_info_instance('node', 'body', 'node_example');
// Add our example_node_list view mode to the body instance display by
// instructing the body to display as a summary
$body_instance['type'] = 'text_summary_or_trimmed';
// Save our changes to the body field instance.
// http://api.drupal.org/api/function/field_update_instance/7
field_update_instance($body_instance);
// Create all the fields we are adding to our content type.
// http://api.drupal.org/api/function/field_create_field/7
foreach (_node_example_installed_fields() as $field) {
field_create_field($field);
}
// Create all the instances for our fields.
// http://api.drupal.org/api/function/field_create_instance/7
foreach (_node_example_installed_instances() as $instance) {
$instance['entity_type'] = 'node';
$instance['bundle'] = 'node_example';
field_create_instance($instance);
}
}
49. D7 *.install
• The node_example module uses 3 distinct
fields
• We place these in a helper function so that it
can be called as needed in functions like
hook_install() and hook_uninstall()
50. D7 *.install
• The node_example module uses 3 distinct
fields
• We place these in a helper function so that it
can be called as needed in functions like
hook_install() and hook_uninstall()
• Make sure to see chx’s presentation on Field
API at 2:15pm in the Aten Design Group
room
56. D7 *.install
• The node_example module uses it’s 3
defined field as 3 field instances
57. D7 *.install
• The node_example module uses it’s 3
defined field as 3 field instances
• We place these in a helper function so that it
can be called as needed in functions like
hook_install() and hook_uninstall()
58. D7 *.install
• The node_example module uses it’s 3
defined field as 3 field instances
• We place these in a helper function so that it
can be called as needed in functions like
hook_install() and hook_uninstall()
• This is the fun part ... we get to apply
formatters to the instances to control their
display
65. D7 *.install
• hook_uninstall() is used to clean up the data
created with the node_example module
• hook_uninstall() deletes our fields and their
instances
66. D7 *.install
• hook_uninstall() is used to clean up the data
created with the node_example module
• hook_uninstall() deletes our fields and their
instances
• hook_uninstall() deletes our content type
67. D7 *.install
• hook_uninstall() is used to clean up the data
created with the node_example module
• hook_uninstall() deletes our fields and their
instances
• hook_uninstall() deletes our content type
• hook_uninstall() purges field data from the
system
69. D7 *.install
function node_example_uninstall() {
// Gather all the example content that might have been created while this
// module was enabled. Simple selects still use db_query().
// http://api.drupal.org/api/function/db_query/7
$sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
$result = db_query($sql, array(':type' => 'node_example'));
$nids = array();
foreach ($result as $row) {
$nids[] = $row->nid;
}
}
70. D7 *.install
function node_example_uninstall() {
// Gather all the example content that might have been created while this
// module was enabled. Simple selects still use db_query().
// http://api.drupal.org/api/function/db_query/7
$sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
$result = db_query($sql, array(':type' => 'node_example'));
$nids = array();
foreach ($result as $row) {
$nids[] = $row->nid;
}
// Delete all the nodes at once
// http://api.drupal.org/api/function/node_delete_multiple/7
node_delete_multiple($nids);
}
71. D7 *.install
function node_example_uninstall() {
// Gather all the example content that might have been created while this
// module was enabled. Simple selects still use db_query().
// http://api.drupal.org/api/function/db_query/7
$sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
$result = db_query($sql, array(':type' => 'node_example'));
$nids = array();
foreach ($result as $row) {
$nids[] = $row->nid;
}
// Delete all the nodes at once
// http://api.drupal.org/api/function/node_delete_multiple/7
node_delete_multiple($nids);
// Loop over each of the fields defined by this module and delete
// all instances of the field, their data, and the field itself.
// http://api.drupal.org/api/function/field_delete_field/7
foreach (array_keys(_node_example_installed_fields()) as $field) {
field_delete_field($field);
}
}
72. D7 *.install
function node_example_uninstall() {
// Gather all the example content that might have been created while this
// module was enabled. Simple selects still use db_query().
// http://api.drupal.org/api/function/db_query/7
$sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
$result = db_query($sql, array(':type' => 'node_example'));
$nids = array();
foreach ($result as $row) {
$nids[] = $row->nid;
}
// Delete all the nodes at once
// http://api.drupal.org/api/function/node_delete_multiple/7
node_delete_multiple($nids);
// Loop over each of the fields defined by this module and delete
// all instances of the field, their data, and the field itself.
// http://api.drupal.org/api/function/field_delete_field/7
foreach (array_keys(_node_example_installed_fields()) as $field) {
field_delete_field($field);
}
// Loop over any remaining field instances attached to the node_example
// content type (such as the body field) and delete them individually.
// http://api.drupal.org/api/function/field_delete_field/7
$instances = field_info_instances('node', 'node_example');
foreach ($instances as $instance_name => $instance) {
field_delete_instance($instance);
}
}
73. D7 *.install
function node_example_uninstall() {
// Gather all the example content that might have been created while this
// module was enabled. Simple selects still use db_query().
// http://api.drupal.org/api/function/db_query/7
$sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
$result = db_query($sql, array(':type' => 'node_example'));
$nids = array();
foreach ($result as $row) {
$nids[] = $row->nid;
}
// Delete all the nodes at once
// http://api.drupal.org/api/function/node_delete_multiple/7
node_delete_multiple($nids);
// Loop over each of the fields defined by this module and delete
// all instances of the field, their data, and the field itself.
// http://api.drupal.org/api/function/field_delete_field/7
foreach (array_keys(_node_example_installed_fields()) as $field) {
field_delete_field($field);
}
// Loop over any remaining field instances attached to the node_example
// content type (such as the body field) and delete them individually.
// http://api.drupal.org/api/function/field_delete_field/7
$instances = field_info_instances('node', 'node_example');
foreach ($instances as $instance_name => $instance) {
field_delete_instance($instance);
}
// Delete our content type
// http://api.drupal.org/api/function/node_type_delete/7
node_type_delete('node_example');
}
74. D7 *.install
function node_example_uninstall() {
// Gather all the example content that might have been created while this
// module was enabled. Simple selects still use db_query().
// http://api.drupal.org/api/function/db_query/7
$sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
$result = db_query($sql, array(':type' => 'node_example'));
$nids = array();
foreach ($result as $row) {
$nids[] = $row->nid;
}
// Delete all the nodes at once
// http://api.drupal.org/api/function/node_delete_multiple/7
node_delete_multiple($nids);
// Loop over each of the fields defined by this module and delete
// all instances of the field, their data, and the field itself.
// http://api.drupal.org/api/function/field_delete_field/7
foreach (array_keys(_node_example_installed_fields()) as $field) {
field_delete_field($field);
}
// Loop over any remaining field instances attached to the node_example
// content type (such as the body field) and delete them individually.
// http://api.drupal.org/api/function/field_delete_field/7
$instances = field_info_instances('node', 'node_example');
foreach ($instances as $instance_name => $instance) {
field_delete_instance($instance);
}
// Delete our content type
// http://api.drupal.org/api/function/node_type_delete/7
node_type_delete('node_example');
// Purge all field information
// http://api.drupal.org/api/function/field_purge_batch/7
field_purge_batch(1000);
}
77. D7 *.module
• Finally on to the module file
• Let’s start with the hooks we will recognize
from D6
78. D7 *.module
• Finally on to the module file
• Let’s start with the hooks we will recognize
from D6
• hook_node_info() informs Drupal about our
content type
79. D7 *.module
• Finally on to the module file
• Let’s start with the hooks we will recognize
from D6
• hook_node_info() informs Drupal about our
content type
• hook_menu() tells Drupal where our custom
page is going to live and how to build it
80. D7 *.module
• Finally on to the module file
• Let’s start with the hooks we will recognize
from D6
• hook_node_info() informs Drupal about our
content type
• hook_menu() tells Drupal where our custom
page is going to live and how to build it
• hook_help() provides help information for
users
81. D7 *.module
/**
* Implements hook_node_info() to provide our node_example type.
*/
function node_example_node_info() {
return array(
'node_example' => array(
'name' => t('Example Node'),
'base' => 'node_example',
'description' => t('This is an example node type with a few fields.'),
'has_title' => TRUE,
),
);
}
82. D7 *.module
/**
* Implements hook_node_info() to provide our node_example type.
*/
function node_example_node_info() {
return array(
'node_example' => array(
'name' => t('Example Node'),
'base' => 'node_example',
'description' => t('This is an example node type with a few fields.'),
'has_title' => TRUE,
),
);
}
/**
* Implements hook_menu().
*
* We are providing a default page to illustrate the use of our custom node view
* mode that will live at http://example.com/?q=examples/node_example
*/
function node_example_menu() {
$items['examples/node_example'] = array(
'page callback' => 'node_example_page',
'access arguments' => array('access content'),
'title' => 'Node Example',
);
return $items;
}
83. D7 *.module
/**
* Implements hook_node_info() to provide our node_example type.
*/
function node_example_node_info() {
return array(
'node_example' => array(
'name' => t('Example Node'),
'base' => 'node_example',
'description' => t('This is an example node type with a few fields.'),
'has_title' => TRUE,
),
);
}
/**
* Implements hook_menu().
*
* We are providing a default page to illustrate the use of our custom node view
* mode that will live at http://example.com/?q=examples/node_example
*/
function node_example_menu() {
$items['examples/node_example'] = array(
'page callback' => 'node_example_page',
'access arguments' => array('access content'),
'title' => 'Node Example',
);
return $items;
}
/**
* Implements hook_help().
*/
function node_example_help($path, $arg) {
switch ($path) {
case 'examples/node_example':
return "<p>" . t(
"The Node Example module provides a custom node type.
You can create new nodes using the <a href='!nodeadd'>node add form</a>.
Nodes that you create will be displayed here.",
array('!nodeadd' => url('node/add/node-example'))
) . "</p>";
}
86. D7 *.module
• hook_form() is used to create the basic
content form
• hook_theme() informs Drupal of our theme
callbacks
87. D7 *.module
/**
* Implement hook_form() with the standard default form.
*/
function node_example_form($node, $form_state) {
return node_content_form($node, $form_state);
}
88. D7 *.module
/**
* Implement hook_form() with the standard default form.
*/
function node_example_form($node, $form_state) {
return node_content_form($node, $form_state);
}
/**
* Implements hook_theme().
*
* This lets us tell Drupal about our theme functions and their arguments.
*/
function node_example_theme($existing, $type, $theme, $path) {
return array(
'example_node_color' => array(
'variables' => array('color' => NULL),
),
);
}
89. D7 *.module
/**
* Implement hook_form() with the standard default form.
*/
function node_example_form($node, $form_state) {
return node_content_form($node, $form_state);
}
/**
* Implements hook_theme().
*
* This lets us tell Drupal about our theme functions and their arguments.
*/
function node_example_theme($existing, $type, $theme, $path) {
return array(
'example_node_color' => array(
'variables' => array('color' => NULL),
),
);
}
/**
* A custom theme function.
*
* By using this function to format our node-specific information, themes
* can override this presentation if they wish. This is a simplified theme
* function purely for illustrative purposes.
*/
function theme_example_node_color($variables) {
$output = '<span style="background-color: #ccc; padding: 1em; margin-bottom: 1em; float: left; color: ' .
$variables['color'] . '">' . $variables['color'] . '</span>';
return $output;
}
92. D7 *.module
• Now for the juicy D7 changes!!!
• hook_entity_info_alter() lets us modify the
node_entity to use our custom view mode
93. D7 *.module
• Now for the juicy D7 changes!!!
• hook_entity_info_alter() lets us modify the
node_entity to use our custom view mode
• hook_field_formatter_view() is where we
place the details of our custom view mode
94. D7 *.module
/**
* Implements hook_entity_info_alter().
*
* We need to modify the default node entity info by adding a new view mode to
* be used in functions like node_view() or node_build_content().
*
*/
function node_example_entity_info_alter(&$entity_info) {
$entity_info['node']['view modes']['example_node_list'] = array(
'label' => t('Example Node List'),
'custom settings' => TRUE,
);
}
95. D7 *.module
/**
* Implements hook_entity_info_alter().
*
* We need to modify the default node entity info by adding a new view mode to
* be used in functions like node_view() or node_build_content().
*
*/
function node_example_entity_info_alter(&$entity_info) {
$entity_info['node']['view modes']['example_node_list'] = array(
'label' => t('Example Node List'),
'custom settings' => TRUE,
);
}
/**
* Implements hook_field_formatter_info().
*/
function node_example_field_formatter_info() {
return array(
'node_example_colors' => array(
'label' => t('Node Example Color Handle'),
'field types' => array('text'),
),
);
}
98. D7 *.module
• Last ... but certainly not least
• hook_field_formatter_view() is where we
place the details of our custom view mode
99. D7 *.module
/**
* Implements hook_field_formatter_view().
*
* @todo: We need to provide a formatter for the colors that a user is allowed to enter
* during node creation.
*/
function node_example_field_formatter_view($object_type, $object, $field, $instance, $langcode, $items, $display) {
$element = array();
switch ($display['type']) {
case 'node_example_colors':
foreach ($items as $delta => $item) {
$element[$delta]['#type'] = 'markup';
$color = $item['safe_value'];
$element[$delta]['#markup'] = theme('example_node_color', array('color' => $color));
}
break;
}
return $element;
}
102. Informative Links
• The Field API Tutorial - http://drupal.org/
node/707832
• The Field API Glossary - http://drupal.org/
node/443540
103. Informative Links
• The Field API Tutorial - http://drupal.org/
node/707832
• The Field API Glossary - http://drupal.org/
node/443540
• Adding and Reusing a Field - http://
drupal.org/node/474420
104. Informative Links
• The Field API Tutorial - http://drupal.org/
node/707832
• The Field API Glossary - http://drupal.org/
node/443540
• Adding and Reusing a Field - http://
drupal.org/node/474420
• Making an Entity Fieldable - http://drupal.org/
node/474582
105. Informative Links
• The Field API Tutorial - http://drupal.org/
node/707832
• The Field API Glossary - http://drupal.org/
node/443540
• Adding and Reusing a Field - http://
drupal.org/node/474420
• Making an Entity Fieldable - http://drupal.org/
node/474582
• The Examples Module - http://drupal.org/
project/examples
106. Informative Links
• The Field API Tutorial - http://drupal.org/
node/707832
• The Field API Glossary - http://drupal.org/
node/443540
• Adding and Reusing a Field - http://
drupal.org/node/474420
• Making an Entity Fieldable - http://drupal.org/
node/474582
• The Examples Module - http://drupal.org/
project/examples
• Drupal API - http://api.drupal.org/
108. Share Your Drupal
Examiner.com is moving to Drupal 7 and has been heavily contributing to the Drupal project.
The site is looking for Examiners in the community to write about Drupal - the business of
Drupal, events, interesting tidbits on Theming and Development, and so forth.
It is more than OK to cross post (you retain copyright to the content but do grant
Examiner.com a license to use that content) from your own blog if you already have a home
you write from and, best of all, you get paid for page views.
It is a great way to promote Drupal, increase your own visibility, and/or build your local
Drupal community. If you're interested, contact Stacey at sharrison@examiner.com. Or speak
with us during this Drupalcamp.