Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Two DataObjects in one form


Go to End
Reply


9 Posts   3287 Views

Avatar
Judge

Community Member, 79 Posts

4 March 2010 at 1:55am

Edited: 04/03/2010 2:27am

This answers one of my questions:

http://doc.silverstripe.org/doku.php?id=datamodel#batch_update

$Desk->castedUpdate(
ArrayLib::filter_keys(
$_REQUEST,
array('DeskName', 'Floor')
)
);

This snippet is used to load submitted form items directly into a DataObject.

-- Jason

Edit: yes, this is the solution I was looking for.

Firstly, make sure the two DataObjects do not have fields with the same name, otherwise they will clash.

Define the master and detail objects (as before):

Employee.php

class Employee extends DataObject {
static $db = array(
'Name' => 'Varchar(255),
'Position' => 'Varchar(255)'
);

static $has_one = array(
'Desk' => 'Desk'
);
}

Desk.php
Remember we do not want a Desk to have many Employees. A Desk will have one Employee *or* one DeskPlant *or* one PersonalComputer (these cannot be modelled in SS at the moment).

class Desk extends DataObject {
static $db = array(
'DeskName' => 'Varchar(255),
'Floor' => 'Varchar(255),
);
}

DataModelAdmin EmployeeAdmin.php:

class EmployeeAdmin extends ModelAdmin {

public static $managed_models = array(
'Employee' // Not Desk
);

static $url_segment = 'employee';
static $menu_title = 'Employees';

}

In the getCMSFields() method, define the Desk fields in the second tab (the first tab will be populated with the Employee record):

class Employee extends DataObject {
...
function getCMSFields()
{
$fields = parent::getCMSFields();

// There has to be a way to create a bunch of form fields in bulk, from the DataObject?
$desk = $this->getComponent('Desk');
$fields->addFieldToTab('Root.Table', new TextField('DeskName', 'Desk Name', $desk->TableName));
$fields->addFieldToTab('Root.Table', new TextField('Floor', 'Floor', $desk->Floor));

return $fields;
}
}

Now handle the submission of the desk along with the Employee, linking the new desk record to the employee record when the employee is first created. We could be a little more clever and only create the desk in the database if (or when) actual data is submitted.

class Employee extends DataObject {
...
function onBeforeWrite()
{
$fields = parent::getCMSFields();

$desk = $this->getComponent('Desk');

$desk->castedUpdate(
ArrayLib::filter_keys(
$_REQUEST,
array('DeskName', 'Floor')
)
);

$desk->write();

if (!$this->ID) {
// New employee record; link the desk to the employee.
$this->DeskID = $desk->ID;
}
}
}

Seems to work great. In summary this is what we have achieved:

* A one-to-one relationship between Employee and Desk.
* When a new Employee is created, a Desk is created and linked to it.
* When we edit an Employee, a second tab allows us to edit the Desk at the same time.

I don't know if I am misusing getComponent() here. It returns the linked Desk if one exists, or a blank Desk otherwise. I *think* that is what it is meant to do...?

Go to Top