Jump to:

7938 Posts in 1541 Topics by 945 members

DataObjectManager Module

SilverStripe Forums » DataObjectManager Module » Newbie: Retrieving first of 'has many' image items in frontend.

Discuss the DataObjectManager module, and the related ImageGallery module.

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

Page: 1
Go to End
Author Topic: 1658 Views
  • timwjohn
    Avatar
    Community Member
    98 Posts

    Newbie: Retrieving first of 'has many' image items in frontend. Link to this post

    Hi all,

    Firstly, I'd like to say how exciting SilverStripe is in its possibilities and can't wait to become a fully fledged developer & contributor to the community.

    My understanding of PHP is limited, and maybe that is why I'm finding it hard to make the penny drop with SilverStripe, but I'm an advanced AS3 developer, so I know when it all falls into place in my head I can build some momentum (and websites). I'm just going round in silly logical circles at the mo.

    I'm a little stuck with a very simple task. Just wanted to know the best way to do it.

    It's for my portfolio website. I've got Page subclasses PortfolioList & PortfolioItem and a DataObject subclass PortfolioImage. PorfolioItem is a child of PortfolioList and PortfolioItem 'has many' PortfolioImages, which I'm successfully managing in the CMS using ImageDataObjectManager, which I admit is the only reason I'm posting in this particular forum.

    What I would like to do in the PortfolioList template is output each PortfolioItem in a box with its first PortfolioImage as a thumbnail of a certain width.

    Here're my PortfolioItem & PortfolioioImage classes:

    class PortfolioItem extends Page
    {
       static $db = array(
          'categoryWeb' => 'Boolean',
          'categoryFlash' => 'Boolean'
       );
       
       static $has_one = array(
       );
       
       static $has_many = array(
          'Images' => 'PortfolioImage'
       );
       
       function getCMSFields()
       {
          $fields = parent::getCMSFields();
          
          $manager = new ImageDataObjectManager(
             $this, // Controller
             'Images', // Source name
             'PortfolioImage', // Source class
             'Image', // File name on DataObject
             array('ImageTitle' => 'ImageTitle'), // Headings
             'getCMSFields_forPopup' // Detail fields (function name or FieldSet object)
             // Filter clause
             // Sort clause
             // Join clause
          );
          
          $fields->addFieldToTab('Root.Content.Main', new CheckboxField($name = 'category_web', $title = 'Web'), 'Content');
          $fields->addFieldToTab('Root.Content.Main', new CheckboxField($name = 'category_flash', $title = 'Flash'), 'Content');
          $fields->addFieldToTab('Root.Content.Images', $manager);
             
          return $fields;
       }
    }

    class PortfolioImage extends Image
    {
       static $db = array(
          'ImageTitle' => 'Text'
       );
       
       static $has_one = array(
          'Image' => 'Image',
          'PortfolioItem' => 'PortfolioItem'
       );
       
       public function getCMSFields_forPopup()
       {
          return new FieldSet(
             new TextField('ImageTitle', 'Image Title')
          );
       }
    }

    This is what I've got so far in the PortfolioList template. For now I'm just outputting the PortfolioImage URLs to see that it's working, and it is:

    <% control Children %>
       <div class="box box-portfolio">
          <div class="box-element box-tl"></div><div class="box-element box-tc"></div><div class="box-element box-tr"></div>
          <div class="box-element box-middle">
             <% control Images %><p>$Link</p><% end_control %>
             <!--<a href="$Link"><img src="" alt="Screenshot" /></a>-->
             <h2><a href="$Link">$Title</a></h2>
          </div>
          <div class="box-element box-bl"></div><div class="box-element box-bc"></div><div class="box-element box-br"></div>
       </div><!--/box-portfolio-->
    <% end_control %>

    So, would I create a function in PortfolioItem to get the first image? Also would I create a function in PortfolioImage generate a set thumbnail size? Or is there a better way?

    Would sopmeone be able to provide some real code examples of how I could achieve this, with some basic explanation? Maybe this will help me understand the structure of SilverStripe just that bit more and I can move on to the next notch.

    My sincere thanks and apologies!

    Tim

  • UncleCheese
    Avatar
    4085 Posts

    Re: Newbie: Retrieving first of 'has many' image items in frontend. Link to this post

    First, if you're using ImageDOM, you should be managing DataObject subclasses, not an Image subclass. If you're going to manage an Image class directly, you can use ImageAssetManager, but since your PortfolioImage object has a custom field (ImageTitle) you need to do it as a dataobject. If you think about it, it doesn't make too much sense to have the self-referential relation here:

    static $has_one = array(
    'Image' => 'Image',
    'PortfolioItem' => 'PortfolioItem'
    );

    You have an image that has_one image. Sometimes that's what you want, but not in this case.

    class PortfolioImage extends DataObject
    {
    static $db = array(
    'ImageTitle' => 'Text'
    );

    static $has_one = array(
    'PortfolioItem' => 'PortfolioItem',
    'Image' => 'Image'
    );

    public function getCMSFields()
    {
    return new FieldSet(
    new TextField('ImageTitle', 'Image Title')
    );
    }
    }

    If you're on the absolute latest SVN checkout of DOM (as of this morning) you can clean up your function using the intelligent constructor feature

    $manager = new ImageDataObjectManager($this);

    but otherwise, use

    $manager = new ImageDataObjectManager(
    $this, // Controller
    'Images', // Source name
    'PortfolioImage', // Source class
    'Image', // File name on DataObject
    array('ImageTitle' => 'ImageTitle'), // Headings
    );

    And on your template, first image and thumbnail:

    <div class="box-element box-middle">
    <% control Images.First %>
    <% control Image %>
    $CroppedImage(100,100)
    <% end_control %>
    <h2>$ImageTitle</h2>
    </div>

  • timwjohn
    Avatar
    Community Member
    98 Posts

    Re: Newbie: Retrieving first of 'has many' image items in frontend. Link to this post

    Thanks UncleCheese! I felt myself levelling up as I read your reply. Of course extending DataObject makes more sense anyway, and now my popups are popping automatically after all the items have uploaded.

    Can you think why the Drag & Drop Reordering option has now disappeared?!

  • UncleCheese
    Avatar
    4085 Posts

    Re: Newbie: Retrieving first of 'has many' image items in frontend. Link to this post

    Ahh... right. You need to add that in manually. It just so happens that DOM makes all File descendants sortable on its own, but in the interest of keeping your tables uncluttered, you have to opt into sorting in your _config.php.

    SortableDataObject::add_sortable_class("MyDataObject");

    For multiple objects, you can pass an array of names to add_sortable_classes();

    Glad it's working for you. Happy to help out.

  • timwjohn
    Avatar
    Community Member
    98 Posts

    Re: Newbie: Retrieving first of 'has many' image items in frontend. Link to this post

    Thanks UncleCheese! I do remember you mentioning that in your YouTube video. Silly me.

  • vancouverWill
    Avatar
    Community Member
    121 Posts

    Re: Newbie: Retrieving first of 'has many' image items in frontend. Link to this post

    Hi Guys

    Once again I'm really impressed by SilverStripe. It works great the way the image dataobjectoperator can be used within the popup. Really intuitive it is. One thing I noticed is that once the images are uploaded there is no way that I can see of simply deleting the images already there. Wondering how you guys approaced this. I was thinking of adding a ConfirmedFormAction button and putting a delete action on it, that works fine to delete the file but then you are left in an empty popup box. Thanks again

    Will

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