Jump to:

23001 Posts in 11854 Topics by 2828 members

General Questions

SilverStripe Forums » General Questions » Two DataObjects in one form

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

Page: 1 2
Go to End
Author Topic: 2860 Views
  • Judge
    Avatar
    Community Member
    79 Posts

    Re: Two DataObjects in one form Link to this post

    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...?

    2860 Views
Page: 1 2
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.