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_many editor


Go to End


15 Posts   8240 Views

Avatar
jam13

121 Posts

26 September 2007 at 1:46am

I'm trying to create a has_many relationship between a page type (PortfolioPage) and a dataobject (PortfolioImage) such that a PortfolioPage can have many PortfolioImages. So far I have set up:

class PortfolioPage extends Page {
  static $db = array(
    );
  static $has_many = array(
    'PortfolioImages' => 'PortfolioImage'
  );
}

class PortfolioImage extends DataObject {
  static $db = array(
    'Title' => 'Varchar',
    'Filename' => 'Varchar'
  );
  static $has_one = array(
    'PortfolioPage' => 'PortfolioPage'
  );
}

This has created the correct tables in the database, and the PortfolioImage table has the PortfolioPageID field. What I'm stuck on is how to use the CMS to edit the content of this table.

I want to add an editable table to PortfolioPage which allows PortfolioImages to be added to that particular page. I tried using TableField:

  function getCMSFields() {
    $fields = parent::getCMSFields();
    $portfolioImageTable = new TableField('Images', 'PortfolioImage', PortfolioImage::$field_names, PortfolioImage::$field_types);
    $fields->addFieldToTab('Root.Content.Images', $portfolioImageTable);
    return $fields;
  }

($field_names and $field_types are defined in the PortfolioImage class), but although this provides the required editable table it isn't using the PortfolioPageID field, so every page shows the same images.

Can anyone give me some guidance because the documentation for this is very sketchy and mostly geared towards many_many relationships.

Thanks.

Avatar
Sneddo

16 Posts

26 September 2007 at 4:16am

Any help would be great im having a problem doing this exact same thing, got the same same stage. although Im trying to do it for a different page.

Please help us!! :-)

Cheers

Avatar
Ingo

Forum Moderator, 801 Posts

26 September 2007 at 2:53pm

$portfolioImageTable = new TableField(
  'Images', 
  'PortfolioImage',
  PortfolioImage::$field_names, 
  PortfolioImage::$field_types
  "PortFolioID = {$this->ID}"
); 
$portfolioImageTable->setExtraData(array(
  "PortFolioID" => $this->ID
));

tablefield is used in many situations, a distinct has_many-relationship is one of them.
you have to set your relation manually for now.

i don't think you're gonna get very far with an ImageUploadField inside a TableField though, just thinking about it gives me a headache ;) you might wanna consider a ComplexTableField, where the upload can be handled in an isolated iframe-popup:
http://doc.silverstripe.com/doku.php?id=hasmanycomplextablefield
http://doc.silverstripe.com/doku.php?id=complextablefield

Avatar
jam13

121 Posts

26 September 2007 at 9:12pm

Edited: 26/09/2007 9:15pm

I did work this out eventually, but as you suggested it doesn't work with an ImageField. I also had a go with hasmanycomplextablefield and complextablefield, but the problem with those are that they seem to require the child class to be descended from SiteMap which I was trying to avoid.

Think I'm going to end up creating a separate subpage for each image :(

(Edited because post got mangled somehow)

Avatar
Ingo

Forum Moderator, 801 Posts

26 September 2007 at 11:47pm

> but the problem with those are that they seem to require the child class to be descended from SiteMap which I was trying to avoid.
they don't - where did you get that impression? "parent"-class just relates to the other side of a has_many or many_many relations. its usually auto-detected, but if in doubt use $myCTF->setParentClass()

Avatar
jam13

121 Posts

27 September 2007 at 1:48am

Edited: 27/09/2007 1:51am

I'm obviously doing something wrong then, because it fails when it can't find a getCMSFields function which is part of SiteMap isn't it?

Avatar
Ingo

Forum Moderator, 801 Posts

27 September 2007 at 2:36am

aaah, now i see your point (assuming you're referring to SiteTree, not SiteMap):
the DataObject-class doesn't have getCMSFields() by default, but nothing prevents you from adding it to your subclass :) just don't call parent::getCMSFields() in this case.
we're doing that all the time, no problem

Avatar
jam13

121 Posts

27 September 2007 at 3:31am

Edited: 27/09/2007 3:32am

Oops, yes SiteTree not SiteMap.

Ok - got it working now with HasManyComplexTableField. I assumed that because it was looking for getCMSFields() that there would be further dependencies, so I didn't bother pursuing it! Here's what I ended up with (in case anyone's interested):

class PortfolioPage extends Page {
  static $db = array(
    );
  static $has_many = array(
    'Images' => 'PortfolioImage'
  );
  function getCMSFields() {
    $fields = parent::getCMSFields();
    $portfolioImageTable = new HasManyComplexTableField(
      $this,
      'Images',
      'PortfolioImage',
      PortfolioImage::$field_names,
      new FieldSet(
        new TextField('Title'),
        new ImageField('Image')
      ),
      "PortFolioID = {$this->ID}"
    );
    $portfolioImageTable->setParentClass('PortfolioPage');
    $fields->addFieldToTab('Root.Content.Images', $portfolioImageTable);
    return $fields;
  }

}

class PortfolioImage extends DataObject {
  static $db = array(
    'Title' => 'Varchar',
    );
  static $has_one = array(
    'Portfolio' => 'PortfolioPage',
    'Image' => 'Image'
    );
  static $field_names = array(
    'Title' => 'Title'
    );
}

I passed a FieldSet directly because I was trying to keep it simple for testing, but I guess it's neater to add the getCMSFields() function to the child class as you suggested.

This works Ok save for a few little niggles:

1) Is it easy to get rid of the checkboxes (as I am filtering the source they are always checked)? Maybe subclass and override the function?

2) I'd like to show values from the Image class in the table somehow (e.g. filename).

3) The ImageField control seems to require that the record is added before the image can be selected. This is a pain because you have to add a PortfolioImage and then edit it to choose an image.

Thanks for all your help BTW.

Go to Top