Jump to:

7935 Posts in 1536 Topics by 943 members

DataObjectManager Module

SilverStripe Forums » DataObjectManager Module » ManyManyDataObjectManager to manage two subclasses of DataObject

Discuss the DataObjectManager module, and the related ImageGallery module.

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

Page: 1 2
Go to End
Author Topic: 1673 Views
  • Bright Eyes David
    Avatar
    Community Member
    26 Posts

    ManyManyDataObjectManager to manage two subclasses of DataObject Link to this post

    I'm new to SilverStripe (and OO PHP) and am hoping someone can pick out what's wrong with or what I need to do to the code I currently have.

    Requirements:

    A parts list.
    A bundles list.
    Recording which bundles contain which parts.

    I've got so far as successfully creating the CMS fields for the two lists, but am stuck on controlling which parts are in which bundles.

    After a /dev/build, I get this in the admin:

    [User Warning] I could not find the relation PartsBundles in PartsHolder or any of its ancestors.
    GET /admin
    Line 54 in /data/htdocs/ac/dataobject_manager/code/ManyManyDataObjectManager.php

    I think I may need to change '$this' in the '$manager_parts_bundles' DOM subclass in PartsHolder.php to something else to let SilverStripe know that it needs to look into one of the other two files to establish the relationship, but I'm not sure how to go about this.

    Here are my files:

    PartsHolder.php

    class PartsHolder extends Page {
       
       static $has_many = array(
          'Parts' => 'Part',
          'Bundles' => 'PartsBundle'
       );
       
       public function getCMSFields() {
          $fields = parent::getCMSFields();
          
          $manager_parts = new DataObjectManager(
             $this,
             'Parts',
             'Part'
          );
          $fields->addFieldToTab('Root.Content.Parts', $manager_parts);
          
          $manager_bundles = new DataObjectManager(
             $this,
             'Bundles',
             'PartsBundle'
          );
          $fields->addFieldToTab('Root.Content.Bundles', $manager_bundles);
          
          $manager_parts_bundles = new ManyManyDataObjectManager(
             $this,
             'PartsBundles',
             'PartsBundle'
          );
          $fields->addFieldToTab('Root.Content.Bundles', $manager_parts_bundles);
          
          return $fields;
       }
       
    }

    class PartsHolder_Controller extends Page_Controller {
       
    }

    Part.php

    class Part extends DataObject {
       
       static $db = array(
          'PartNumber' => 'Varchar',
          'Description' => 'Text',
          'PurchasePrice' => 'Varchar',
          'SupplierPartNumber' => 'Varchar',
          'SupplierDescription' => 'Text',
          'SupplierTerms' => 'Text',
          'SalesPrice' => 'Varchar'
       );
       
       static $has_one = array(
          'PartsHolder' => 'PartsHolder',
          'Image' => 'Image'
       );
       
       static $belongs_many_many = array(
          'Bundles' => 'PartsBundle'
       );
       
       static $summary_fields = array(
          'PartNumber' => 'PartNumber',
          'Description' => 'Description',
          'PurchasePrice' => 'PurchasePrice',
          'SalesPrice' => 'SalesPrice'
       );
       
       function getCMSFields() {
          return new FieldSet(
             new TextField('PartNumber'),
             new TextAreaField('Description'),
             new NumericField('PurchasePrice'),
             new TextField('SupplierPartNumber'),
             new TextAreaField('SupplierDescription'),
             new TextAreaField('SupplierTerms'),
             new NumericField('SalesPrice'),
             new ImageField('Image')
          );
       }

    }

    PartsBundle.php

    class PartsBundle extends DataObject {
       
       static $db = array(
          'Description' => 'Text',
          'SalesPrice' => 'Varchar'
       );
       
       static $has_one = array(
          'PartsHolder' => 'PartsHolder'
       );
       
       static $many_many = array(
          'Parts' => 'Part'
       );
       
       static $summary_fields = array(
          'Description' => 'Description',
          'SalesPrice' => 'SalesPrice'
       );
       
       function getCMSFields() {
          return new FieldSet(
             new TextAreaField('Description'),
             new NumericField('SalesPrice')
          );
       }
       
    }

    Many thanks!

  • Bright Eyes David
    Avatar
    Community Member
    26 Posts

    Re: ManyManyDataObjectManager to manage two subclasses of DataObject Link to this post

    Friendly bump as I still haven't sorted this. Let me know if I need to clarify anything. Thanks.

  • Bright Eyes David
    Avatar
    Community Member
    26 Posts

    Re: ManyManyDataObjectManager to manage two subclasses of DataObject Link to this post

    Any pointers on this still appreciated.

  • Puppy
    Avatar
    Community Member
    10 Posts

    Re: ManyManyDataObjectManager to manage two subclasses of DataObject Link to this post

    I am having a similar problem using ModelAdmin to show editable relations between Organisations and Persons.

    Organisation.php

    class Organisation extends DataObject {
          static $db = array(
                "Name" => "Varchar",
                "Type" => "Enum('Registered Business, Freelancer, Sole Trader, Charity, Public Sector')",
                "RegNum" => "Varchar(100)",
                "Website" => "Varchar",
                "Phone" => "Varchar",
                'Email' => 'Varchar',
                'Address' => 'Varchar',
                'Postcode' => 'Varchar(10)'
                   );
          
          static $has_one = array(
                );
          
          static $belongs_many_many = array(
             "Persons" => "Person"
           );
          
          static $summary_fields = array(
          'Name' => 'Name',
          'Phone' => 'Phone',
          'Email' => 'Email'
          );
          
          static $searchable_fields = array (
          'Name',
          'Type'
       );
          
          function getCMSFields() {
                   
             $fields = new Fieldset();
             $fields->push(new TextField('Name', 'Name'));
             $fields->push(new DropdownField("Type", "Type of Organisation", $this->dbObject('Type')->enumValues()));
             $fields->push(new TextField('RegNum', 'Company/Charity Number'));
             
             $fields->push(new TextField('Email', 'Email'));
             $fields->push(new TextField('Phone', 'Phone'));
             $fields->push(new TextField('Website', 'Website'));
             
             $fields->push(new TextareaField('Address', 'Address'));
             $fields->push(new TextField('Postcode', 'Postcode'));
             
             return $fields;
          
          }

    Person.php

    class Person extends DataObject {
       
          static $db = array(
                "Title" => "Enum('Mr, Mrs, Ms, Dr')",
                "FirstName" => "Varchar",
                "Surname" => "Varchar",
                "FullName" => "Varchar",
                'Email' => 'Varchar',
                'Phone' => 'Varchar',
                'Mobile' => 'Varchar',
                'Address' => 'Varchar',
                'Postcode' => 'Varchar(10)'
                   );
          static $has_one = array(
                "User" => "Member"
                );
          
          static $many_many = array(
                "Organisations" => "Organisation"
                );
          
          static $defaults = array(
                            
           );
          
          static $summary_fields = array(
          'FullName' => 'Full Name',
          'Member' => 'Member',
          'Phone' => 'Phone',
          'Email' => 'Email'
          );
          
          static $searchable_fields = array (
          'FullName',
          'Surname',
          'FirstName'
       );
          
          function getCMSFields() {
             
             $userManager = new HasOneDataObjectManager($this, 'User', 'Member');
             $userManager->setPermissions(
                   array(
                      "show",
                      "edit"
                   ));
             
             $organisation = new ManyManyDataObjectManager($this, 'Organisation', 'Organisation');
             
    $fields = parent::getCMSFields();          
    $fields->addFieldToTab("Root.Main", new ReadonlyField('FullName', 'Full Name'));

    $fields->addFieldToTab("Root.Main", new DropdownField("Title", "Title", $this->dbObject('Title')->enumValues()));
    $fields->addFieldToTab("Root.Main", new TextField('FirstName', 'First Name'));
    $fields->addFieldToTab("Root.Main", new TextField('Surname', 'Surname'));

    $fields->addFieldToTab("Root.Main", new TextField('Email', 'Email'));
    $fields->addFieldToTab("Root.Main", new TextField('Phone', 'Phone'));
    $fields->addFieldToTab("Root.Main", new TextField('Mobile', 'Mobile'));

    $fields->addFieldToTab("Root.Main", new TextareaField('Address', 'Address'));
    $fields->addFieldToTab("Root.Main", new TextField('Postcode', 'Postcode'));

    $fields->addFieldToTab("Root.UserAccount", $userManager);

    $fields->addFieldToTab("Root.Organisations", $organisation);

             return $fields;
          
          }

    Looking into, have you found anything else?

  • BoWa
    Avatar
    Community Member
    2 Posts

    Re: ManyManyDataObjectManager to manage two subclasses of DataObject Link to this post

    Hi,

    didnt see the flaw per ce, but heres an alternative way to do this,

    for the PartsBundle change the getCMSFields to inlcude the ManyManyDataObjectManager for the parts

    eg

    function getCMSFields() {
    return new FieldSet(
    new TextAreaField('Description'),
    new NumericField('SalesPrice'),
    new ManyManyDataObjectManager(
    $this,
    'Parts',
    'Part'
    )
    );
    }

    and for the PartsHolder comment out the two other editors and just leave the one for the bundles,

    $manager_bundles = new DataObjectManager(
    $this,
    'Bundles',
    'PartsBundle'
    );
    $fields->addFieldToTab('Root.Content.Bundles', $manager_bundles);

    this way youll get one tab for bundles and when adding creating a bundle you can select existing to it or add new ones.

    Cheers,
    BoWa

  • Bright Eyes David
    Avatar
    Community Member
    26 Posts

    Re: ManyManyDataObjectManager to manage two subclasses of DataObject Link to this post

    Thanks Bowa,

    Funnily enough, this is about what I have now after I chatted to you on IRC (it was you, wasn't it?), but now I've come across the issue where Parts that are ticked are not saved by the ManyManyComplexTableField because it's in a pop-up which is something many are finding (seemingly for about a year or more).

    I'm now trying to figure out how to get the ManyManyComplexTableField not to be in a pop-up so that it works.

  • BoWa
    Avatar
    Community Member
    2 Posts

    Re: ManyManyDataObjectManager to manage two subclasses of DataObject Link to this post

    Cheers,

    And im a fraid it was me , selection at the admin end seemed to work for the inner "manymanyeditor" for me at least.

    But if you have an issue with it theres a nifty workaround, instead of the inner editor use the CheckboxSetField to manage the selections.

    Below a snipped of a working idea, wont copy the whole thing here ;P

    $doTravellerTag = DataObject::get("TravellerTag");
    $mapTravellerTag = $doTravellerTag ? $mapTravellerTag = $doTravellerTag->toDropdownMap('ID','Name') : array();
    $fields->push(new CheckboxSetField('TravellerTags','TravellerTags', $mapTravellerTag));

    TravellerTag is a many_many relation for that Data Object. Off course with this you need one tab were you "build" the bundles packages but the relations are managed with a simple checkboxlist.

    Or just crate a site tree with pages to hide the underliying "datamodel" it really depents how "politically correct" you want to be with your relations ;)

    Cheers,
    Olli

  • Bright Eyes David
    Avatar
    Community Member
    26 Posts

    Re: ManyManyDataObjectManager to manage two subclasses of DataObject Link to this post

    Got this sorted now. I made another Holder class for the bundles and separated them out. Not what I was hoping for, but it works.

    I think the issue may be that DOM is not supposed to handle relationships between DataObjects and DataObjects (only Pages and DataObjects)?

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