Developer Notes

jayallen edited this page Aug 23, 2011 · 13 revisions
Clone this wiki locally

Field Day Developer Notes

Value Storage

Field Day values are stored as FieldDay::Value objects. FieldDay::Value is an MT::Object subclass that uses the mt_fdvalue table as its datasource.

Values are stored using a narrow table implementation: one row holds a single instance of a single field value.

The class has the following columns:

  • id: The unique ID of the value object. Normally you will not use this directly.
  • object_type: The type (not the MT:: class) of object to which the value belongs: entry, user, page, system, etc.
  • object_id: The ID of the object to which the value belongs.
  • blog_id: For objects that belong to a blog (i.e., everything but User and System), the ID of the blog containing the object. Note that for Blog fields, this should contain the blog's ID (which is redundant with the object ID, but may cause problems if not populated because of the way things are currently coded).
  • key: The name of the field, as defined in the Field Day settings.
  • value: The stored value. For Linked Object fields, this is simply the ID of the linked object.
  • value_text: The stored value if over 255 characters; Field Day automatically saves a value into either this column or the value column based on its length.
  • instance: For field groups that allow multiple instances, the 1-based instance number of this value. If multiple instances are allowed, this must be populated or the value will not show up on the object editing screen.


MT::Object's utility get_by_key() and set_by_key() methods are often useful when dealing with Field Day values. These will load an existing object matching the specified terms if one already exists, or create one and populate it if it does not already exist.

To loop through all extra field values for the entry with ID 332:

my %terms = (
    object_type => 'entry',
    object_id => 332,
for my $val_obj (MT->model('fdvalue')->load(\%terms)) {
    my $value = $val_obj->value;
    # ...

To set the value for the field footnotes for the page object $page:

my %terms = (
    object_type => 'page',
    object_id => $page->id,
    blog_id => $page->blog_id,
    key => 'footnotes',
my $val_obj = MT->model('fdvalue')->get_by_key(\%terms);
# calling value() will automatically use the value_text column where appropriate
$val_obj->save || die $val_obj->errstr;

To loop through all instances of the blog-level Linked Asset field logo for the blog object $blog:

my %terms = (
    object_type => 'blog',
    object_id => $blog->id,
    key => logo,
my %args = (
    sort => 'instance',
    direction => 'ascend',
for my $val_obj (\%terms, \%args) {
    # value might be null
    next unless $val_obj->value;
    # value is the object ID
    my $asset = MT->model('asset')->load($val_obj->value);
    # make sure asset still exists in system
    next unless $asset;
    # ...

To populate the multi-instance system-level Linked Entry field featured_entry with the entry objects in the array @featured:

# instance counter
my $i = 0;
for my $entry (@featured) {
    my %terms = (
        object_type => 'system',
        key => 'featured_entry',
        instance => $i,
    my $val_obj = MT->model('fdvalue')->get_by_key(\%terms);
    $val_obj->save || die $val_obj->errstr;
# now need to remove any pre-existing values with higher instance numbers
    object_type => 'system',
    key => 'featured_entry',
    instance => { '>' => $i },

It'd be great to add a feature to the Plugin Settings, where the Linked Assets attribute Overwrite Existing Files [x] could be set to default to CHECKED on either a blog-specific or system-wide basis.