original source :http://www.palantir.net/blog/controlling-nodes-drupal-7
Drupal has numerous ways to control access to content. Some are built into core, others are provided by an add-on module, others are a side-effect of some combination of add-on modules. Some are more or less compatible with others.
To understand the various options, and their trade-offs, it’s important to understand the two basic mechanisms that Drupal offers as well as the tasks they can control: hook_node_access() and the grants system.
A number of modules are available that leverage one or another of these systems to help lock down a site.
Operations
There are, in Drupal 7, five operations that can be performed on a node: Create, Read, Update, Delete, List. It is important to understand that Read (or “view”) and List are different operations. Read acts on a single node. List operates on a series of nodes matching some criteria. Create, of course, operates on the concept of a node rather than an actual node object.
Mechanisms
There are, in Drupal 7, two systems for controlling node access. One is hook_node_access(), which operates on a single node object. Multiple modules may implement this hook and allow or deny access to a given node for a given operation. This happens at runtime, and a module may use whatever criteria it wants to grant or block access.
The other is the node grants system, which operates in two ways. One, it is used for a single node if and only if hook_node_access() neither granted or denied access. Two, it is the only mechanism used, or even available, for List operations. List operations require filtering at the query level, not the object level, which is why they can only be filtered by the grants system, which creates a giant materialized summary of all group/node combinations and stores them in the database. That way, it can modify lookup queries directly and filter out inaccessible nodes before Drupal even sees them. By “list operations”, in practice most of the time what we really mean is “Views”.
An important consideration is that only the grants system can completely hide the existence of a node from a user. However, it is all-or-nothing. Once a node grants-using module is installed, all nodes in the system will have at least one record in the node_grants table, even if it is to say “I don’t care about this one”. hook_node_access(), however, can choose to operate at runtime without any extra overhead, and more flexibility.
If it is important that a node’s existence be hidden entirely, the grants system is the only option. If not, or if it can be emulated by careful control of Views (eg, only nodes of type Foo need to be restricted so a View that lists that node type is restricted to a given role only), then hook_node_access()-based approaches will be lighter weight and more flexible.
Another factor to consider is that multiple node grants modules often don’t play nice together, which could result in nodes not displaying at all or displaying when they should not. When mixing grants modules, some custom glue code may be required to sort out any collisions. Fortunately such glue code is easier to write in Drupal 7 thanks to the addition of new grant_alter hooks.
Tools
There are a number of modules that leverage one or the other access system. Before rolling your own, consider if one of these will serve your needs.
hook_node_access() modules
WorkbenchThis module, or suite of modules, allows create/edit/delete access to be restricted based on a “section”, that is, a (potentially) hierarchical organization of administrative groups in the site that may or may not map to the site’s IA hierarchy. The most common hierarchy to use is a taxonomy vocabulary, but that is not the only one available. Workbench does not restrict read or list operations. It is an administrative tool only, but a very useful one.Organic GroupsOrganic Groups is one of the heavier access modules traditionally, but as of Drupal 7 is much more cleanly designed and modular. It allows nodes and users to be “clustered” into a group, which itself could be defined by any node, user, or other entity. For node access, it allows for users to be able to view nodes only in groups they belong to, or, conversely, nodes in a given group are only accessible to that group’s members. It also as of Drupal 7 allows node permissions, and a few others, to be customized for the context of a given group. That is, users can create nodes of type Article in a given group only if they are a member of that group.
Node Grants modules
Domain AccessDomain Access is a weird module. It leverages the node grants system, but rather than restricting access based on the active user it restricts access based on the domain that was requested. That allows parallel sites to have a single content pool and single administrative pool, since they’re all one Drupal instance, but to filter content relevant to that site only. It is not really useful for restricting what users can view a node; it is more of a site structure tool that happens to leverage node grants.Nodeaccess Nodereference and Nodeaccess UserreferenceThese curious modules grant view, update, and delete permissions using the node access system based on whether or not the node in question has a node reference that points to a node the user has access to. This allows for the creation of potentially complex and uneven hierarchies for node access, as a sort of poor-mans Organic Groups.Content AccessThis module is the latest in a long line that allows per-node and per-type configuration of user access. It leverages the node grants system. A Drupal 7 version is in progress but not yet complete.Taxonomy Access Control and TAC LiteThese similar modules both control access via taxonomy terms. Users have access to a node if they have access to a term that it is tagged with. Drupal 7 versions are still under development, however.
Other options
Another consideration is file access. In many cases nodes may be public, but uploaded files not. Drupal 7 has support for both public and private files, configurable per-filefield. For public files, there is no access control at all and files are downloaded directly without going through Drupal at all. For most files this is fine, and preferred, as it is the most performant option.
If a file is marked private, by default nothing changes. However, the file is then accessed only via a PHP callback, which checks another access hook, hook_file_download_access(). Drupal 7 core does not implement that hook. However, other modules are free to do so. One such module is Field Permissions, which allows an admin to expose a particular field to the field access system. That field then gets its own permissions on the permissions page, which in turn allows the admin to specify which users roles may or may not view that field, and download that file.
Although I am not aware of any modules that allow per-node file download control, one could certainly be written. (If you know of any good ones, please share in the comments!)
If you’re looking to build a Drupal site, check out the modules above and see if they would be helpful. If not, and you need to make your own access control module, watch for my article “Hooked on Security” in Issue #2 of Drupal Watchdog, coming soon to a DrupalCon London near you
– See more at: http://www.palantir.net/blog/controlling-nodes-drupal-7#sthash.fEaev0Nl.dpuf
original source :http://www.palantir.net/blog/controlling-nodes-drupal-7
Drupal has numerous ways to control access to content. Some are built into core, others are provided by an add-on module, others are a side-effect of some combination of add-on modules. Some are more or less compatible with others.
To understand the various options, and their trade-offs, it’s important to understand the two basic mechanisms that Drupal offers as well as the tasks they can control: hook_node_access() and the grants system.
A number of modules are available that leverage one or another of these systems to help lock down a site.
Operations
There are, in Drupal 7, five operations that can be performed on a node: Create, Read, Update, Delete, List. It is important to understand that Read (or “view”) and List are different operations. Read acts on a single node. List operates on a series of nodes matching some criteria. Create, of course, operates on the concept of a node rather than an actual node object.
Mechanisms
There are, in Drupal 7, two systems for controlling node access. One is hook_node_access(), which operates on a single node object. Multiple modules may implement this hook and allow or deny access to a given node for a given operation. This happens at runtime, and a module may use whatever criteria it wants to grant or block access.
The other is the node grants system, which operates in two ways. One, it is used for a single node if and only if hook_node_access() neither granted or denied access. Two, it is the only mechanism used, or even available, for List operations. List operations require filtering at the query level, not the object level, which is why they can only be filtered by the grants system, which creates a giant materialized summary of all group/node combinations and stores them in the database. That way, it can modify lookup queries directly and filter out inaccessible nodes before Drupal even sees them. By “list operations”, in practice most of the time what we really mean is “Views”.
An important consideration is that only the grants system can completely hide the existence of a node from a user. However, it is all-or-nothing. Once a node grants-using module is installed, all nodes in the system will have at least one record in the node_grants table, even if it is to say “I don’t care about this one”. hook_node_access(), however, can choose to operate at runtime without any extra overhead, and more flexibility.
If it is important that a node’s existence be hidden entirely, the grants system is the only option. If not, or if it can be emulated by careful control of Views (eg, only nodes of type Foo need to be restricted so a View that lists that node type is restricted to a given role only), then hook_node_access()-based approaches will be lighter weight and more flexible.
Another factor to consider is that multiple node grants modules often don’t play nice together, which could result in nodes not displaying at all or displaying when they should not. When mixing grants modules, some custom glue code may be required to sort out any collisions. Fortunately such glue code is easier to write in Drupal 7 thanks to the addition of new grant_alter hooks.
Tools
There are a number of modules that leverage one or the other access system. Before rolling your own, consider if one of these will serve your needs.
hook_node_access() modules
WorkbenchThis module, or suite of modules, allows create/edit/delete access to be restricted based on a “section”, that is, a (potentially) hierarchical organization of administrative groups in the site that may or may not map to the site’s IA hierarchy. The most common hierarchy to use is a taxonomy vocabulary, but that is not the only one available. Workbench does not restrict read or list operations. It is an administrative tool only, but a very useful one.Organic GroupsOrganic Groups is one of the heavier access modules traditionally, but as of Drupal 7 is much more cleanly designed and modular. It allows nodes and users to be “clustered” into a group, which itself could be defined by any node, user, or other entity. For node access, it allows for users to be able to view nodes only in groups they belong to, or, conversely, nodes in a given group are only accessible to that group’s members. It also as of Drupal 7 allows node permissions, and a few others, to be customized for the context of a given group. That is, users can create nodes of type Article in a given group only if they are a member of that group.
Node Grants modules
Domain AccessDomain Access is a weird module. It leverages the node grants system, but rather than restricting access based on the active user it restricts access based on the domain that was requested. That allows parallel sites to have a single content pool and single administrative pool, since they’re all one Drupal instance, but to filter content relevant to that site only. It is not really useful for restricting what users can view a node; it is more of a site structure tool that happens to leverage node grants.Nodeaccess Nodereference and Nodeaccess UserreferenceThese curious modules grant view, update, and delete permissions using the node access system based on whether or not the node in question has a node reference that points to a node the user has access to. This allows for the creation of potentially complex and uneven hierarchies for node access, as a sort of poor-mans Organic Groups.Content AccessThis module is the latest in a long line that allows per-node and per-type configuration of user access. It leverages the node grants system. A Drupal 7 version is in progress but not yet complete.Taxonomy Access Control and TAC LiteThese similar modules both control access via taxonomy terms. Users have access to a node if they have access to a term that it is tagged with. Drupal 7 versions are still under development, however.
Other options
Another consideration is file access. In many cases nodes may be public, but uploaded files not. Drupal 7 has support for both public and private files, configurable per-filefield. For public files, there is no access control at all and files are downloaded directly without going through Drupal at all. For most files this is fine, and preferred, as it is the most performant option.
If a file is marked private, by default nothing changes. However, the file is then accessed only via a PHP callback, which checks another access hook, hook_file_download_access(). Drupal 7 core does not implement that hook. However, other modules are free to do so. One such module is Field Permissions, which allows an admin to expose a particular field to the field access system. That field then gets its own permissions on the permissions page, which in turn allows the admin to specify which users roles may or may not view that field, and download that file.
Although I am not aware of any modules that allow per-node file download control, one could certainly be written. (If you know of any good ones, please share in the comments!)
If you’re looking to build a Drupal site, check out the modules above and see if they would be helpful. If not, and you need to make your own access control module, watch for my article “Hooked on Security” in Issue #2 of Drupal Watchdog, coming soon to a DrupalCon London near you
– See more at: http://www.palantir.net/blog/controlling-nodes-drupal-7#sthash.fEaev0Nl.dpuf
Drupal 7 Node Access: Grants, Locks, and Keys
original source : http://www.phase2technology.com/blog/drupal-7-node-access-grants-locks-and-keys/
Node Access: Who wins?
While Drupal has always had a pretty robust access control mechanism, it was difficult in the past to handle multiple contributed modules who wanted to impose different types of access control. Who wins? If a node is within a private Organic Group, but is also in a public Forum, is the node private or public? In Drupal 6, multiple access control modules could conflict and had to take special care to co-exist. It was messy.
In Drupal 7 the access control API was cleaned up and now it is relatively easy to handle multiple access control systems. Let’s learn the best way to implement your own access control system in Drupal 7.
The Perils of hook_node_access
Drupal 7 added a cool new hook for developers:hook_node_access($node, $op, $account). On the surface, this seems like the ultimate hook to control access. You simply return NODE_ACCESS_ALLOW, NODE_ACCESS_DENY, or NODE_ACCESS_IGNORE. In reality, this hook can be very dangerous! It allows you to override the access control of any other modules on your site. For example:
This would deny access to all of your content regardless of any other access control. If it returned NODE_ACCESS_ALLOW it would *allow* access to all of your content! Unless some other module returns NODE_ACCESS_DENY, in which case access would still be denied.
Even worse, your custom hook_node_access function is ignored by Views, Menus, and other content queries on the site. Even though you have denied access to all content, you’ll still see all of your normal menu links, and will see your nodes listed in Views. Only when you click on a node to view it’s full detail page will you then be denied. You might be violating content privacy just by showing that certain content exists!
A “Deny” based approach
Drupal is a “deny-based” access control system. In other words, if anybody denies access to a node, then the node is blocked. This is similar to having multiple locks on your door: you need to open ALL the locks to enter your door. Using hook_node_access to return NODE_ACCESS_ALLOW access violates this convention and is generally a bad idea. Instead you should design your modules to DENY access when needed, and otherwise return NODE_ACCESS_IGNORE to allow other modules to decide if access should be granted. The hook_node_access results are the “last line of defense” for denying access and don’t stop Views or Menus from showing parts of the content anyway.
The correct approach is to use the Drupal “Grant” system. This API existed in previous versions, but in Drupal 7 it was cleaned up and works much better. The key hooks arehook_node_grants($account, $op) and.hook_node_access_records($node). The documentation can be hard to follow and talks about “realms” and “grant ids”. Instead, let me explain this API using the concepts of Locks and Keys.
hook_node_access_records are Locks
The hook_node_access_records is called to determine if a specific node should be locked. Your module has the opportunity to create a Lock with a specific “realm” and “id”. The “realm” is like the color of your lock and is typically the name of your module. This allows a single node to have multiple locks with different colors (multiple modules). To open the door, you would need keys that match each color of locks on the door.
Within a realm, you can have multiple locks with different “ids”. This is like giving the colored lock a specific serial number corresponding to a key with the same color and serial number. If you have a key with the correct color and serial number, than all of the locks of that color are opened. To summarize:
- Each lock Realm (color) must be opened to access the node
- Only one ID (serial number) within the Realm needs to be unlocked to open that entire Realm.
These node Locks are stored in the node_access database table, which means they are cached. This table is only rebuilt when you run the Rebuild Permissions in the Status Report area of your Drupal admin. When you save a node, hook_node_access_records is called only for the node being saved to allow it’s locks to be updated. If changing a node can affect the locks on other nodes, then you’ll want to call node_access_acquire_grants($node) to update the locks on the related nodes.
hook_node_grants are Keys
The hook_node_grants is called to create a “key-ring” for a particular user account. This is called dynamically at each page load to determine what keys the current user has. As mentioned above, a particular node can be accessed only if the user has the appropriate keys for each Realm (color) of locks on the node. Because this key-ring is not stored or cached, it is important to make your hook_node_grants function very fast and efficient.
When implementing hook_node_grants, you are typically only concerned about the Realm implemented by your module (remember that Realm is usually your module name). You probably don’t want to be messing with keys for other modules. Your hook just needs to decide if the user has any of *your* keys. Specifically, your hook needs to return a list of key IDs (lock serial numbers) within your Realm for the specified user account.
REAL Node Access!
The beauty of using the two Grant API hooks described above is that they are respected by Menus, Views, and optionally other queries within the database API. If the user does not have the proper keys to open the locks on a node, then the node will never display in any Menu or View. Unlike hook_node_access(), this properly protects the privacy of your content.
With Views, you can turn off the node access filtering in the Query Options of the Advanced section of the View. Turn on the “Disable SQL rewriting” option and now Views will return all results regardless of the keys and locks.
If you create your own database queries using the Drupal database API, you can also easily filter results based upon node access. Simply add a “tag” to the query called “node_access”. For example:
The above example would only return the nid and title of nodes the current user can access.
UPDATED: It is important to include this addTag(‘node_access’) for ANY query that you perform that returns node results to a user. Otherwise you’ll be introducing a security hole into your module. You can also use EntityFieldQuery which automatically filters results based upon node access.
An Example from Open Atrium 2
In Open Atrium 2, we implement a flexible node access system. All content is assigned to a specific “Section” within a normal Organic Group. Each Section can be locked based upon Organizations, Teams, and Users. For example, if Mike and Karen are assigned to the “Developer” Team, and the “Developer” Team is assigned to a specific Section, then only Mike or Karen can see the existence of that Section and the content within it. To accomplish this, we implement hook_node_access_records to assign locks, and hook_node_grants to assign keys.
First, let’s assign the locks for content within a Section:
For a Section node, we just grab the node ID. For pages within a section we grab the referenced section IDs. Once we have a list of section IDs, we loop through them and create a $grants Lock record giving our module name OA_ACCESS_REALM as the Realm (color), and the Section ID as the ID (serial number). This adds our colored Lock to the nodes that are protected within Sections, using the specific Section ID as the lock serial number.
Next, let’s build the key-ring for the user account (*Note, this is a non-optimized version of code for instructional purposes):
For each Section that the user is a member of, we return the Section ID for that Realm in the $grants array. If a particular node has Section locks, only users with a key to that Section will be granted access. For example, if a node has locks for $sid 1, 2, and 3, but the user only has a key for $sid 4, then access is denied. But if the user has a key for $sid 1, 2, or 3, then access is granted. You only need a single matching key within the Realm to grant access.
Conclusion
If you think about the Drupal node access system as a system of Locks and Keys, then it’s pretty easy to understand. It’s a very powerful system and one of the key strengths of Drupal. Try using this Grant API and only use the new hook_node_access as a last resort, especially when building other contributed modules where your hook_node_access might conflict with other modules.
Drupal 7 Node Access: Grants, Locks, and Keys
original source : http://www.phase2technology.com/blog/drupal-7-node-access-grants-locks-and-keys/
Node Access: Who wins?
While Drupal has always had a pretty robust access control mechanism, it was difficult in the past to handle multiple contributed modules who wanted to impose different types of access control. Who wins? If a node is within a private Organic Group, but is also in a public Forum, is the node private or public? In Drupal 6, multiple access control modules could conflict and had to take special care to co-exist. It was messy.
In Drupal 7 the access control API was cleaned up and now it is relatively easy to handle multiple access control systems. Let’s learn the best way to implement your own access control system in Drupal 7.
The Perils of hook_node_access
Drupal 7 added a cool new hook for developers:hook_node_access($node, $op, $account). On the surface, this seems like the ultimate hook to control access. You simply return NODE_ACCESS_ALLOW, NODE_ACCESS_DENY, or NODE_ACCESS_IGNORE. In reality, this hook can be very dangerous! It allows you to override the access control of any other modules on your site. For example:
This would deny access to all of your content regardless of any other access control. If it returned NODE_ACCESS_ALLOW it would *allow* access to all of your content! Unless some other module returns NODE_ACCESS_DENY, in which case access would still be denied.
Even worse, your custom hook_node_access function is ignored by Views, Menus, and other content queries on the site. Even though you have denied access to all content, you’ll still see all of your normal menu links, and will see your nodes listed in Views. Only when you click on a node to view it’s full detail page will you then be denied. You might be violating content privacy just by showing that certain content exists!
A “Deny” based approach
Drupal is a “deny-based” access control system. In other words, if anybody denies access to a node, then the node is blocked. This is similar to having multiple locks on your door: you need to open ALL the locks to enter your door. Using hook_node_access to return NODE_ACCESS_ALLOW access violates this convention and is generally a bad idea. Instead you should design your modules to DENY access when needed, and otherwise return NODE_ACCESS_IGNORE to allow other modules to decide if access should be granted. The hook_node_access results are the “last line of defense” for denying access and don’t stop Views or Menus from showing parts of the content anyway.
The correct approach is to use the Drupal “Grant” system. This API existed in previous versions, but in Drupal 7 it was cleaned up and works much better. The key hooks arehook_node_grants($account, $op) and.hook_node_access_records($node). The documentation can be hard to follow and talks about “realms” and “grant ids”. Instead, let me explain this API using the concepts of Locks and Keys.
hook_node_access_records are Locks
The hook_node_access_records is called to determine if a specific node should be locked. Your module has the opportunity to create a Lock with a specific “realm” and “id”. The “realm” is like the color of your lock and is typically the name of your module. This allows a single node to have multiple locks with different colors (multiple modules). To open the door, you would need keys that match each color of locks on the door.
Within a realm, you can have multiple locks with different “ids”. This is like giving the colored lock a specific serial number corresponding to a key with the same color and serial number. If you have a key with the correct color and serial number, than all of the locks of that color are opened. To summarize:
- Each lock Realm (color) must be opened to access the node
- Only one ID (serial number) within the Realm needs to be unlocked to open that entire Realm.
These node Locks are stored in the node_access database table, which means they are cached. This table is only rebuilt when you run the Rebuild Permissions in the Status Report area of your Drupal admin. When you save a node, hook_node_access_records is called only for the node being saved to allow it’s locks to be updated. If changing a node can affect the locks on other nodes, then you’ll want to call node_access_acquire_grants($node) to update the locks on the related nodes.
hook_node_grants are Keys
The hook_node_grants is called to create a “key-ring” for a particular user account. This is called dynamically at each page load to determine what keys the current user has. As mentioned above, a particular node can be accessed only if the user has the appropriate keys for each Realm (color) of locks on the node. Because this key-ring is not stored or cached, it is important to make your hook_node_grants function very fast and efficient.
When implementing hook_node_grants, you are typically only concerned about the Realm implemented by your module (remember that Realm is usually your module name). You probably don’t want to be messing with keys for other modules. Your hook just needs to decide if the user has any of *your* keys. Specifically, your hook needs to return a list of key IDs (lock serial numbers) within your Realm for the specified user account.
REAL Node Access!
The beauty of using the two Grant API hooks described above is that they are respected by Menus, Views, and optionally other queries within the database API. If the user does not have the proper keys to open the locks on a node, then the node will never display in any Menu or View. Unlike hook_node_access(), this properly protects the privacy of your content.
With Views, you can turn off the node access filtering in the Query Options of the Advanced section of the View. Turn on the “Disable SQL rewriting” option and now Views will return all results regardless of the keys and locks.
If you create your own database queries using the Drupal database API, you can also easily filter results based upon node access. Simply add a “tag” to the query called “node_access”. For example:
The above example would only return the nid and title of nodes the current user can access.
UPDATED: It is important to include this addTag(‘node_access’) for ANY query that you perform that returns node results to a user. Otherwise you’ll be introducing a security hole into your module. You can also use EntityFieldQuery which automatically filters results based upon node access.
An Example from Open Atrium 2
In Open Atrium 2, we implement a flexible node access system. All content is assigned to a specific “Section” within a normal Organic Group. Each Section can be locked based upon Organizations, Teams, and Users. For example, if Mike and Karen are assigned to the “Developer” Team, and the “Developer” Team is assigned to a specific Section, then only Mike or Karen can see the existence of that Section and the content within it. To accomplish this, we implement hook_node_access_records to assign locks, and hook_node_grants to assign keys.
First, let’s assign the locks for content within a Section:
For a Section node, we just grab the node ID. For pages within a section we grab the referenced section IDs. Once we have a list of section IDs, we loop through them and create a $grants Lock record giving our module name OA_ACCESS_REALM as the Realm (color), and the Section ID as the ID (serial number). This adds our colored Lock to the nodes that are protected within Sections, using the specific Section ID as the lock serial number.
Next, let’s build the key-ring for the user account (*Note, this is a non-optimized version of code for instructional purposes):
For each Section that the user is a member of, we return the Section ID for that Realm in the $grants array. If a particular node has Section locks, only users with a key to that Section will be granted access. For example, if a node has locks for $sid 1, 2, and 3, but the user only has a key for $sid 4, then access is denied. But if the user has a key for $sid 1, 2, or 3, then access is granted. You only need a single matching key within the Realm to grant access.
Conclusion
If you think about the Drupal node access system as a system of Locks and Keys, then it’s pretty easy to understand. It’s a very powerful system and one of the key strengths of Drupal. Try using this Grant API and only use the new hook_node_access as a last resort, especially when building other contributed modules where your hook_node_access might conflict with other modules.
An Introduction to Entities | Drupal.org
If you are looking for the documentation or the entity API in Drupal 8, click here. Maybe you’ve heard of “entities” in Drupal 7, wondered what they were, and wanted to learn the underlying concepts. Leveraging the Entity API lets you create more lightweight and flexible solutions. The Drupal community often compares site building through configuration to a favorite childhood toy: LEGO bricks. We can build Entity types, which can make Bundles, to which we can add Fields and then create Entities. This article explains the relationships between Entity types > Bundles > Fields > Entities. This was one of the most important changes of Drupal 7, and brought components from some well-loved contributed modules – such as CCK – into the core system. The illustration below shows some examples of Entity types included with Drupal 7, with some example entities: Let’s take a closer look at these concepts. It’s sort of a chicken-and-egg thing, one doesn’t exist without the other. Entity types
If you are looking for the documentation or the entity API in Drupal 8, click here.
Maybe you’ve heard of “entities” in Drupal 7, wondered what they were, and wanted to learn the underlying concepts. Leveraging the Entity API lets you create more lightweight and flexible solutions.
The Drupal community often compares site building through configuration to a favorite childhood toy: LEGO bricks. We can build Entity types, which can make Bundles, to which we can add Fields and then create Entities. This article explains the relationships between Entity types > Bundles > Fields > Entities. This was one of the most important changes of Drupal 7, and brought components from some well-loved contributed modules – such as CCK – into the core system.
The illustration below shows some examples of Entity types included with Drupal 7, with some example entities:
Let’s take a closer look at these concepts. It’s sort of a chicken-and-egg thing, one doesn’t exist without the other.
Entity types
In earlier versions of Drupal, the field system was only used on content types. Now, thanks to the Entity API, we can add fields to other things, like comments. Fieldable entities make Drupal eminently flexible. An entity type is a useful abstraction to group together fields. Let’s consider some examples of entity types:
- Nodes (content)
- Comments
- Taxonomy terms
- User profiles
You can also build new kinds of entity types where the options above don’t suit your needs. For more information, read further about using the hook_entity_info and extension by Entity API:entity_crud_hook_entity_info.
Bundles
Bundles are an implementation of an entity type to which fields can be attached. You can consider bundles as subtypes of an entity type. With content nodes (an entity type), for example, you can generate bundles (subtypes) like articles, blog posts, or products. Not all entity types have bundles, however. For example, users do not have separate bundles (subtypes). For the entity types that do allow bundles, you can create as many bundles (subtypes) as you want. Then, using the Field system, you can add different fields to each bundle. Examples include a file download field on Basic Pages and a subtitle field on Articles.
Fields
A field is a reusable piece of content. In technical terms, each field is a primitive data type, with custom validators and widgets for editing and formatters for display. You can read further for a developer’s guide to using the Drupal 7 Fields API.
What’s important to know as it relates to Entities is that Fields can be added to any of the bundles (or entity types) to help organize their data. Say, for example, you create a content type with an unstructured text field and use HTML to structure parts of it, like a summary section, or prices. That would make it more difficult, then, to control how these were displayed, or to make connections between different types of related content. This is where using fields is essential.
Entity
An entity would be one instance of a particular entity type such as a comment, taxonomy term or user profile or a bundle such as a blog post, article or product.
You can use entity_load to load any entity. Note, however, that the core does not provide a save or delete function, but thanks to Entity API module the missing pieces are added (entity_create(), entity_save(), entity_delete(), entity_view() and entity_access()).
Putting this in Object-Oriented Design/Programming terms…
If you come from an OOD/P background and are trying to better understand what these key D7 concepts are, the following suggested mapping might help (albeit not strictly true from a purist’s perspective) :-
- An entity type is a base class
- A bundle is an extended class
- A field is a class member, property, variable or field instance (depending on your naming preference)
- An entity is an object or instance of a base or extended class
All these four OOD/P concepts are special in that they are serialisable (stored – e.g. to a database or file). Serialisation takes place via the Entity API.
So what’s the big deal?
If you’re familiar with Drupal 6 and new to Drupal 7, this will sound like great news. In Drupal 6 and before, users and comments didn’t have the same power that nodes (content) had. They couldn’t have translations, fields, versioning, and so on. It also meant that systems such as Views, which relied on controlling the selection and listing of fields didn’t work as well with comments and users. Some experimentation was done with modules that turned comments or users into nodes. However, this meant that all the additional information in the node object was added to comments.
Instead, the community created this abstraction based on what was common between these different models of entity types. In this way, the Entity API allows for more lightweight and flexible solutions. There are many entity-aware modules, and more being developed with Drupal 7, which make it easier to relate content together, and gain a more flexible architecture.
Entity API module
The project Entity API extends the entity API of Drupal core in order to provide a unified way to deal with entities and their properties. Additionally, it provides an entity CRUD controller, which helps in simplifying the creation of new entity types.
Learn more about using the Entity API in your projects.
View a slideshow by jdleonard on entities and the Entity API.
http://www.slideshare.net/jdleonard/entities-in-drupal-7-the-entity-api