MillyMonster
MillyMonster

Reputation: 556

One to one relationship in Silverstripe

I'll try and put this as simply as possible but basically what I am trying to achieve is this.

There are two page types with a one to one relationship, car and owner. I want to be able te be able to select an owner through a dropdown on the car page. If an owner is already linked to another car I don't want it to appear in the dropdown.

I know that I'll need an if statement but I I'm finding it hard to puzzle out how it should go. I followed this tutorial to create the dropdown and it worked quite well.

Thanks in advance.

Upvotes: 1

Views: 1161

Answers (2)

schellmax
schellmax

Reputation: 6094

Benjamin Smith' answer is perfectly valid for the dropdown you were asking for, just wanted to point to another approach: instead of taking care of the one-to-one relation yourself, there's the 'HasOneComplexTableField' handling this for you.

use the following code for your Car class:

class Car extends Page {
    public static $has_one = array(
        'Owner' => 'Owner'
    );
    function getCMSFields() {
        $fields = parent::getCMSFields();
        $tablefield = new HasOneComplexTableField(
            $this,
            'Owner',
            'Owner',
            array(
                'Title' => 'Title'
            )
        );
        $tablefield->setParentClass('Car');
        $tablefield->setOneToOne();
        $tablefield->setPermissions(array());
        $fields->addFieldToTab('Root.Content.Owner', $tablefield);
        return $fields;
    }
}

note the 'setOneToOne()' call, telling the tablefield to only let you select Owners which aren't already selected on another car.

you'll find more information on this in the silverstripe tutorial: http://doc.silverstripe.org/framework/en/tutorials/5-dataobject-relationship-management

Upvotes: 1

Benjamin Smith
Benjamin Smith

Reputation: 887

You can modify the function that gives you the dropdown values. Your DataObject::get() call can have a filter for the second argument. Simply select all owners that have a CarID of 0.

So, from the tutorial you provided, you can use this modified code:

new DropdownField(
    'OwnerID',
    'Please choose an owner',
    Dataobject::get("Owner","CarID='0'")->map("ID", "Title", "Please Select")
);

2 things to note:

  • This assumes your DataObjects are called Car and Owner (change as necessary, but keep the ID at the end of the name as it is written above)

  • This may not work depending how you set up the relationships with the $has_one assignments on your DataObjects. If there is no CarID field on the Owner table, then this code won't help you (you may have it set up vice-versa). In that case, you'll have to create a function that loops through all cars, and then removes the DataObjects from that DataObjectSet that have an OwnerID of 0. Add a comment if this isn't making sense.

Upvotes: 2

Related Questions