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.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

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

Templates - Accessing an object within an object


Reply


3 Posts   490 Views

Avatar
Double-A-Ron

Community Member, 604 Posts

10 September 2013 at 11:12pm

So I have a TestimonialPage, which has Testimonial dataobject as a has_many relationship. The Tesitmonial also has a Tour page type as a has one relationship. This Tour page type already exists.

TestimonialPage.php

class TestimonialsPage extends SmartPage {

...
   static $has_many = array(
      'Testimonials' => 'Testimonial'
   );
...

}

Testimonial.php

class Testimonial extends DataObject {
...
   static $has_one = array(
      'Image' => 'Image',
      'TestimonialsPage' => 'TestimonialsPage',
      'Tour' => 'Tour'
   );
...
}

On the TestimonialPage template, I am looping Testimonials and displaying them. Works fine. Until I attempt to access any of the properties in the linked Tour object:

TestimonialPage.ss

<% if Testimonials %>
      <% control Testimonials %>

$Tour.Title // Doesn't display anything

<% end_control %>
<% end_if %>

Is that even possible? There is no relationship linking to the Testimonial object from Tour, as it's rather optional.

Avatar
Bereusei

Community Member, 94 Posts

11 September 2013 at 11:17pm

Did you try this?:

<% if Testimonials %>
<% control Testimonials %>

<% control Tour %>
$Title
<% end_control %>

<% end_control %>
<% end_if %>

Avatar
Double-A-Ron

Community Member, 604 Posts

12 September 2013 at 6:49pm

Cheers for the reply mate.

I did think about that, but I was worried about load, as I would be using that control block 6-7 times in various locations.

On top of that, I later realised that some of these Tour objects are VirtualPages, and hence not returning true data of the ContentSource. (this may be a 2.4.5 way of thinking, I have no idea if 2.4.11, which I just upgraded to, fixed that issue since I found another solution)

So I created a static helper method to work this out for me:

TourAdapter.php

class TourAdapter extends ViewableData {
public static function getRealTour($TourID = null) {
      
      $object = DataObject::get_by_id("SiteTree", $TourID);

      if($object->ClassName == "VirtualPage") {
         $realId = $object->ContentSource()->ID;
         return DataObject::get_by_id("SiteTree", $realId);
      } else {
         return $object;
      }
   }
}

Then, I created a getTour method in the Testimonial DataObject:

Testimonial.php

class Testimonial extends DataObject {
static $cachedTour = null;
   
   public function getTour() {
      
      // Only call the helper once. Store in object state for later use
      if(is_null(self::$cachedTour)) {
         self::$cachedTour = TourAdapter::getRealTour($this->TourID);
      }
      
      return self::$cachedTour;
   }
}

Note that it only calls the helper once. And everything is perfect in the template when I call $getTour.Title etc. Right withing the <% control Testimonials %> loop.

Although I am wondering if I just re-invented the wheel after your suggestion. I really have no idea on load if I call <% control Tour %> multiple times, or if it would sort out the VirtualPage's content source. Haven't had time to test.

But thanks