Jump to:

17452 Posts in 4473 Topics by 1971 members

Archive

SilverStripe Forums » Archive » $has_one / $has_many and getCMSFields

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

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

Page: 1
Go to End
Author Topic: 3718 Views
  • julian
    Avatar
    Community Member
    17 Posts

    $has_one / $has_many and getCMSFields Link to this post

    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)

  • julian
    Avatar
    Community Member
    17 Posts

    Re: $has_one / $has_many and getCMSFields Link to this post

    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!

  • Ingo
    Avatar
    Forum Moderator
    801 Posts

    Re: $has_one / $has_many and getCMSFields Link to this post

    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 ;)

  • julian
    Avatar
    Community Member
    17 Posts

    Re: $has_one / $has_many and getCMSFields Link to this post

    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

  • Ingo
    Avatar
    Forum Moderator
    801 Posts

    Re: $has_one / $has_many and getCMSFields Link to this post

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

  • julian
    Avatar
    Community Member
    17 Posts

    Re: $has_one / $has_many and getCMSFields Link to this post

    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 );
          }
       }

    3718 Views
Page: 1
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.