It's quite easy to achieve with ComplexTableField.
I have an ImageAttachment class that has a name, image and a thumbnail image:
class ImageAttachment extends DataObject {
static $db = array(
'Name' => 'Text'
);
static $has_one = array(
'ImageThumbnail' => 'Image',
'Image' => 'Image'
);
static $field_names = array('Name' => 'Name');
function getCMSFields_forPopup() {
$fields = new FieldSet();
$fields->push(new TextField('Name', 'Name'));
$fields->push(new ImageField('ImageThumbnail', 'Thumbnail'));
$fields->push(new ImageField('Image', 'Image'));
return $fields;
}
}
In the page I add a new tab with ComplexTableField that allows me edit all the related images:
class PageWithImages extends Page {
static $has_many = array(
'ImageAttachments' => 'ImageAttachment'
);
function getCMSFields() {
$fields = parent::getCMSFields();
$imagetable = new ComplexTableField(
$this,
'ImageAttachments', // relation name
'ImageAttachment', // object class
ImageAttachment::$field_names, // fields to show in table
ImageAttachment::getCMSFields_forPopup(), // form that pops up for edit
"PageID = {$this->ID}", // a filter to only display item associated with this page
"Name ASC" // Sort by name
);
$fields->addFieldToTab('Root.Content.ImageAttachments', $imagetable);
return $fields;
}
}
I use this successfully for file attachments as well.
You may also use HasManyComplexTableField if you have a set of images and want to associate a set of images with each page but possibly one image to multiple pages. With ComplexTableField as above each ImageAttachment may be added to one page only.