Fields 7 API - Drupalcon DC

05 Mar 2009
Posted by jcfiala

Fields 7 API

Barry Jaspan, Acquia, Inc.
D6: CCK with hook_nodeapi, Many field types,
But tied to nodeapi, not users or comments.

D7: Field Attach API - Field module
Node calls field everywhere it would call nodeapi, but first.

Effectively, field is a nodeapi that gets called first. nodeapi still there
Just like cck calls to field modules to cool stuff - the fields module calls the same, some in core and some like date, image go into contrib.

field.module is the field attach api
Then, the field type api is what provides the fields for nodes and such
Creating fields in D7 Field uses a CRUD API that's in the CCK UI. CCK UI creates fields, but doesn't automatically attach only to nodes.

Anyone can use field attach - Users, Nodes, Comments and maybe fields in time.

But it could even be non-core objects, like a module the creates a flickr object which we could then attach the field to. The item doesn't actually have to persist in the db - if flickr image 1286 is in memory, then we can attach a comment text field to it - text field lives in db, flickr image lives on flickr website.

This presentation is no more than half the session time and then will handle questions.

per-field storage - pluggable in some way - field_sql_storage which does per-field storage, but could replace it, and hooks allow you to take over storage of any other field, or even copy a field off and allow the default storage to handle it as well. Very easy to mix and match field storage solutions. (example of putting huge image into s3 for storage instead of letting it go into db.)

fields - base types, 'name = subtitle, type = text'
field instances - A field attached to a particular bundlej (Article subtitle widget = text area)
bundles - Group of fields that make up a larger entity (Name = article, type = node, name = user, type = user)

Maybe change fields for roles on users - 'bundle' is sort of a content type, but it could be a node type, a role, a user..., a user with role...
Currently only one type - user, though.

What goes where?
- field api
- field type modules
* text, number
* list
* node & User reference
* options
- field storage

- cck ui
- field permissions
- field groups
- field storage options
- integration
* view, token, etc

List is now simpler, and handles lists of options you can choose from. has field documentation - going to show demo now.

Demo is off of head, and he apologizes if something goes nuts.
node body and teaser could become fields, unsure?
Showing that he can add a 'favorite saying' to the user.

Can have single line field with Text formats.

Asking if title could be a field and option? So far, no.
There's a ton of code that assumes that $node->title is very much it.
Question about screwing contrib by using title as a field - he's open for it.
Issue in queue on fields on files.

Long term design goal is to make node into a thin wrapper around fields - taxonomy into field, etc.
"A node is a basic unit of content whose master location is in the drupal sql database"

Node defined by a table saying "Node 13 created by user 27" <- that's the node, plus fields.
The fields may not be stored locally, but the node is.

question - developers tend not to use cck - that's something the admin does, not the programmer, because no api for it. But now you can create fields programatically, which may lead to more nodes in modules with fields.

Question - will there be a mass import function in core - response is that it does not part of fields, and so he can't say. Probably not be in core, most likely as contrib first.
CCK will move data from cck into core.

"What's left to get rid of profile module"?
Profile module will change to use fields as data storage instead of current stuff, but in his opinion is very useful and not just field api.

Question - export/import of fields?
There is nothing in fieldapi that specificly addresses that, but it will be easier to solve that problem in fields. So, could write a module to find all the updates to fields, record them to memory, and write them out for reading into another db.

question about fields being stored and overridden, like views have defaults and overrides. Response is that fields are set up, and then the instance is separate. as much as possible is in instance, so when you push a field into a bundle it's different. They have not seen a need for inheriting data from another field.

question - would that allow object oriented inheritance between node types. It's not implemented right now, but the fields system as it is now that it has no concept of content types, only of bundles. Any inheritance scheme that was inheritable would have to allow users to inherit from nodes or something like that - use cases not compelling yet, better to maybe clone a bundle into another, which could be handled by contrib.
(Like an address group of fields - there's just not a good way of having that 'inherit' from user to node.)

split into two things. A) imagefield derivied from filefield, that's implementation detail for image module. B) I've created a field, and I want to derive another field from it at the operational level.
A) - That could be handled by using object orientation.
B) - don't see a use of that.

New example - creating 'Favorite Band' field on users. showing database structure now. All the field related table start with field_... field_data_field_saying
first five columns - etid (numeric representation of type - node, user,), bundle, deleted, entity_id (nodeid, uid), revision_id (node_vid, null for users)
Delta: If cck, indicates which value it is on multi-value fields.
And then the columns of data - in field_saying it's field_saying_value and field_saying_format

for speed, 'field_data_field_saying' stores only most recent revision of data - field_data_revision_field_saying' holds the older revisions.
This lets you use a different table format for the older revisions storage.

"bundle" - indicates bundle type - used for deleting content types. So, if we want to delete all the article fields, we can delete where bundle = 'article' instead of a more complex query.

primary key right now is etid, entity_id, deleted, delta
want to make autoincrement primary key and push etid, entity_id, delta to unique key

shared fields are no longer a problem - shows adding 'favorite band' to a node.

plenty of more to do!
* Use Field API for core object properties
node body/teaser
user profile
user profile/taxonomy/simple comments? Comment module needs to be revised to work with fields.

* finish intiial functinoality
- field types: node reference & user reference

code sprint on saturday

field api code sprint team picture

D6 cck uses hybrid storage, which we are told is impossible to maintain
d7 core field storage uses per-field tables
- much simpler to implement correctly
- higher write overhead, but read cost is similar due to caching.
- node_field_caching holds all the data, and invalidates/updates only when the node is changed.
- massive joins just generally don't happen.
jeff eaton pointed out that if you save a node with 100 fields - but humans can't create that many that fast - so the write cost won't be that heavy. This is good enough for practically all sites.

$100 for the first counter-example. :)
PBS module - per bundle storage
- re-implements hybrid field storage via hooks
- handles n-value and shared fields. - 5 values, then you get five repeats of the field. And shared fields are stored both in per-field and per-bundle tables.
- all the benefits of cck 6, plus better.
- also simpler.

* Materialized Views
- Merges field and non-field data for expensive selects into a single wide, fast table.
- Currently live on d.o now to speed up d6

Question - response was that they haven't included new indexes that cck didn't, but they can be added. MV addresses the question of consolidating and indexing data as you like. It copies and indexes the data, and allows you to specify things exactly like you want.

Core vs. contrib decisions TBD - a lot of the code is done and works.

per bundle storage - field_pbs_article - just like in cck for d6. If a field is shared, then it it stored in pbs and also let's it go get stored in field_data_blah
But if it's not shared, the pbs tells fields that the data is already handled and it is only stored in field_pbs_user or whichever.

Barry Jaspan