Search code examples
phpsilverstripedata-objects

Silverstripe 3.0 return dataobjects and page url's in one function


I am using Silvertripe 3.0 and currently have a simple page setup that has a couple children pages. The children pages have data objects that contain images, I am trying to get both the images and the url of the children page to appear on the parent page. I have the following code in my template:

<% loop $Children %>
    <a href="$Link">$Title</a>
<% end_loop %>

<div id="whiskyMainGallery">

    <% control WhiskyGallery %>
        <div class="item">

            <a href="$WhiskyPageID">$Slide.SetRatioSize(220,178)</a>

        </div>

    <% end_control %>

</div>

Both of these controls work as expected, but I am try to combine them so I get the data object image from WhiskyGallery control as well as the URL so i can call something like the following in my template:

<% control JoinedStuff %>
    <a href="$ChildPageUrl">$DataObjectImage</a>
<% end_control%>

Any help would be greatly appreciated!

Here is my whiskyPage class:

class WhiskyPage extends Page {

    public static $db = array(
        'ABV'       => 'Text',
        'Colour'    => 'Text',
        'Aroma'     => 'HTMLText',
        'Taste'     => 'HTMLText',
        'Finish'    => 'HTMLText'
    );

    public static $has_many = array(
        'TastingAwards' => 'TastingAward',
        'WhiskyImages'  => 'WhiskyImage'
    );

   public function getCMSFields() {

        $fields = parent::getCMSFields();

        $gridFieldConfig = GridFieldConfig_RecordEditor::create(); 
        $gridFieldConfig->addComponent(new GridFieldBulkEditingTools());
        $gridFieldConfig->addComponent(new GridFieldSortableRows('SortOrder'));   

        $gridfield = new GridField("TastingAwards", "Tasting Awards", $this->TastingAwards()->sort("SortOrder"), $gridFieldConfig);

        $gridFieldConfig2 = GridFieldConfig_RecordEditor::create(); 
        $gridFieldConfig2->addComponent(new GridFieldBulkEditingTools());
        $gridFieldConfig2->addComponent(new GridFieldBulkImageUpload());   
        $gridFieldConfig2->addComponent(new GridFieldSortableRows('SortOrder'));  

        $gridfield2 = new GridField("WhiskyImages", "Whisky Images", $this->WhiskyImages()->sort("SortOrder"), $gridFieldConfig2);

        $fields->addFieldToTab('Root.Tasting Notes', new TextField('ABV', 'ABV'));
        $fields->addFieldToTab('Root.Tasting Notes', new TextField('Colour', 'Colour'));
        $fields->addFieldToTab('Root.Tasting Notes', new HTMLEditorField('Aroma', 'Aroma'));
        $fields->addFieldToTab('Root.Tasting Notes', new HTMLEditorField('Taste', 'Taste'));
        $fields->addFieldToTab('Root.Tasting Notes', new HTMLEditorField('Finish', 'Finish'));

        $fields->addFieldToTab('Root.Tasting Awards', $gridfield);
        $fields->addFieldToTab('Root.WhiskyImages', $gridfield2);

        return $fields;

    }

}

My WhiskyImage DataObject

class WhiskyImage extends DataObject {

    public static $db = array(  
      'SortOrder'   => 'Int',
      'Title'       => 'Varchar',
      'Featured'    => 'Boolean'
    );

    // One-to-one relationship with whisky page
    public static $has_one = array(
    'Slide'         => 'Image',
    'WhiskyPage'    => 'WhiskyPage'
    );

    // tidy up the CMS by not showing these fields
    public function getCMSFields() {
        $fields = parent::getCMSFields();
        $fields->removeFieldFromTab("Root.Main","WhiskyPageID");
        $fields->removeFieldFromTab("Root.Main","SortOrder");

        $fields->addFieldToTab('Root.Main', new CheckboxField('Featured', 'Featured'));

        return $fields;
    }

    // Tell the datagrid what fields to show in the table
    public static $summary_fields = array( 
       'ID'         => 'ID',
       'Title'      => 'Title',
       'Thumbnail'  => 'Thumbnail'
    );

    // this function creates the thumbnail for the summary fields to use
    public function getThumbnail() { 
        if ($Image = $this->Slide()->ID) { 
            return $this->Slide()->SetWidth(80); 
        } else {
            return '(Please upload an image)'; 
        }
    }

}

The WhiskyLandingPage has it's own class, but nothing interesting in it, except a custom function to return the Images

public function GetWhiskyGallery() {
    return WhiskyImage::get()->filter(array('Featured' => 1))->sort("SortOrder");
}

Hope that makes a bit more sense!


Solution

  • first, you should use loop instead of control in the templates

    second, joining dataobjects and pages seems like a rather bad idea and you will probably run into problems. why not just loop the pages and then loop the dataobjects?

    like so:

    <% loop $Children %>
        <a href="$Link">$Title</a>
        <ul>
           <% loop $WhiskyImages %>
               <a href="$Top.Link" title="link to the whisky page">Image: $Title</a>
               <a href="$WhiskyPage.Link">this link will also link to the wisky page</a>
               $Slide.SetRatioSize(220,178)
           <% end_loop %>
        </ul>
    <% end_loop %>
    

    // EDIT:

    in your example where you just loop a list of all WhiskyImage objects, you can do this:

    <div id="whiskyMainGallery">
        <% loop WhiskyGallery %>
            <div class="item">
                <a href="$WhiskyPage.Link">$Slide.SetRatioSize(220,178)</a>
            </div>
        <% end_loop %>
    </div>