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.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Archive /

Our old forums are still available as a read-only archive.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo

$has_one / $has_many and getCMSFields


Go to End


6 Posts   5202 Views

Avatar
julian

Community Member, 17 Posts

7 March 2007 at 11:10am

Edited: 10/03/2007 1:24pm

Hi guys,

ok so I've set up these relationships: "A Museum can have many Exhibitions". I want to link Exhibitions to Museums in the admin gui but I'm a little lost?

Exhibition.php:

class Exhibition extends Page {
...
static $has_one = array(
...
'Museum' => 'Museum'
);

Then in Museum.php:

class Museum extends Page {
...
static $has_many = array(
'Exhibitions' => 'Exhibition'
);
}

... any ideas what magic I have to do to change getCMSFields so that under an Exhibition I get a dropdown to choose which Museum it belongs to, and under a Museum it lists / enables changing of Exhibitions?

Yes I could make Exhibitions children of Museums but there are reasons why I don't want to do this, and besides, it wouldn't work for many_many -- and so I have a similar question for that..

It looks like RelatedDataEditor is the way to do this but when I tried this it crashed because it enforced 1..* not 0..* ?

thanks very much!

Julian (Kiwi in Wimbledon)

Avatar
julian

Community Member, 17 Posts

8 March 2007 at 9:26pm

hello... anyone out there? It looks like the entire silverstripe community has gone on holiday? looking forward to any guidance you can help with... thanks!

Avatar
Ingo

Forum Moderator, 801 Posts

9 March 2007 at 12:40am

Edited: 09/03/2007 12:41am

function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main',new DropdownField('MuseumID','Museum'));
return $fields;
}

Thats the simplest solution for a has_one. If your relation is SiteTree-based (rather than extending DataObject), have a look at TreeDropdownField (or TreeMultiSelectField for has_many).
TableListField, TableField and ComplexTableField basically do the same thing as RelatedDataEditor for has_many-Relationsships. They are very versatile ways to display relationship, unfortunately quite poorly documented ;)

Avatar
julian

Community Member, 17 Posts

9 March 2007 at 10:14am

Thanks Ingo! That whole 'MuseumID' thing... where can I find out more about this? I'm always keen to read docs / code etc so I don't pester you guys but I did get a little stuck on this to be honest...

thanks!
J

Avatar
Ingo

Forum Moderator, 801 Posts

9 March 2007 at 12:07pm

Edited: 09/03/2007 12:11pm

We've got a very brief documentation on http://doc.silverstripe.com/doku.php?id=datamodel.

We're using Object Relational Mapping (http://en.wikipedia.org/wiki/Object-relational_mapping) and basically the same conventions as Ruby on Rails to build automatic database-relations. Hence, when you write something like
static $has_one = array("Museum"=>"Museum");
our db-builder adds a MuseumID-column to the table.

I forgot an important chunk of code that possibly confused you:
function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab(
'Root.Main',
new DropdownField(
'MuseumID',
'Museum',
DataObject::get('Museum')->toDropDownMap()
)
);
return $fields;
}
This adds an actual value-map to the dropdown (see DataObjectSet for more info on this).

Avatar
julian

Community Member, 17 Posts

14 March 2007 at 11:35am

ok I'll update the wiki at some stage, but just for the sake of preventing others spend their entire saturdays on this, this is how $has_many works. I wanted Artworks to be favourited by users. So this is what I did:

class Artwork extends SiteTree {
...
static $many_many = array (
'MemberFavourites' => 'Member'
);
...

/** Used for the admin GUI to enable users to create content */
function getCMSFields() {
...
$this->populateMemberFavourites( $fields );
...
return $fields;
}
}

// Some explanation of the Checkbox as it's not clear from dox.
// 'MemberFavourites' -- this should be the name of the property you want the checkbox field to update when you change. Get this wrong and your values won't be saved.
// $idList -- this should be the list of the values that have been chosen. Get this wrong and the values won't reflect the database when they're created.
// NOTE that 'toDropDownMap()' is nothing special -- it's a map designed for dropdown lists but equally works well for checkbox lists etc.

/** create a GUI for showing those members who chose this item as a favourite */
function populateMemberFavourites( $pFields ) {
$components = $this->getManyManyComponents('MemberFavourites');
$idList = $components->getIdList();

$dataSet = DataObject::get('Member');
if( $dataSet ) {
$theCheckboxFieldSet = new CheckboxSetField('MemberFavourites','Members who marked this artwork as a fave',$dataSet->toDropDownMap(), $idList);
$pFields->addFieldToTab( 'Root.Content.MemberFavourites', $theCheckboxFieldSet );
}
}