What is best practice for modules to create new node types in Drupal 7?
In Drupal 6, I have a module that uses hook_schema to define a new mymodule_node table on installation.
This table does nothing more than define the additional fields for my new node type, keyed by nid. I then use hook_load to load these fields in whenever a node of that nodetype is loaded, together with hook_update, hook_delete, hook_insert etc. to keep this table in sync with alterations to the underlying node. This is the same approach I used in D5 and works very well.
However, looking at the node_example in the "Examples for Developers" module, I notice that the approach now taken there is to use the Fields API to define the new node type in hook_install(), creating fields and then attaching them directly to a new node type using field_create_field, field_create_instance, etc. hook_schema is not used at all, and no new tables are created relating to the node type. Furthermore, all the view formatting has changed to define the widgets associated with each field etc.
Just wondered, what are the benefits of switching to use the Fields approach rather than hook_schema for storing custom node type information?
The node_example.module file has a comment
"We no longer need an external database table to store this content types information."
But I find this comment slightly misleading, because what the field API does when you define new node types in this way is to create a new table for every field used in defining the new content type. So whereas before I created one new "external" table: mymodule_node, I now have five "internal" tables - one for each field in my nodetype: field_data_myfield1, field_data_myfield2, field_data_myfield3, etc.
And I'm not sure why it is implicitly assumed to be a good thing not to have "external" database tables anyway (as in, not created by core).
From a very limited profiling of database queries issued under each, it seems that the 'old' method is slightly more efficient for most types of node operations, and it seems to be perfectly functional under D7 even if it is not considered the "Drupally" way to do it.
Any comments gratefully received! Thanks
Comments
Multiple tables in Drupal 7 for Custom Fields
tanoshimi,
I have the same understanding about the custom fields making a table per field type. It seems that all fields are shareable across content types, requiring such a table in order to allow joins. In Drupal 6 CCK I believe the design was that this was an option, and not the default. If the CCK field was to be shared across multiple content types it would get its own table, else it would not.
I am building a private Drupal 7 site now with three interrelated custom content types. Each one has several fields, and I can't help but count the number of underlying joins when I think about accessing them. Like all frameworks though, these are tradeoffs we need to make. Here the tradeoffs seem to be among
- the need to have first class nodes in the system, and thus leverage Drupal features and add-ons;
- the need to scale and minimize database joins in heavy load dynamic access usage patterns;
- the speed at which one wants to develop;
My current project, in the wildest of dreams, might grow to 1,000 users (it's very niche). So I will just go with the default setup. Then I can use the References module to handle inter-node dependencies, and leverage the taxonomy system in other requirements. In addition it's probably the quickest way to get my work done.
Were I expecting heavy peak load on my site I might write my own tables, my own joins, and implement menu callbacks to handle custom queries and joins. Essentially, for frequently accessed data structures, I'd bypass the Node API all together. This would allow me to reduce the joins and improve response time to the user. The cost would be that I would step outside the Drupal node system, and thus lose ability to leverage some of the Drupal framework.
In my mind this is a standard software engineering choice, where we try to balance the various tradeoffs of our tools against our current and anticipated requirements. I would have preferred the Node API to let me chose whether to group common fields in a single table, but its not a big enough deal for me to bring it up formally in the Drupal Community and try to rally support for the idea. How often is it really going to be an issue after all?
--
John Storey
Binary Feline, LLC
john@binaryfeline.com