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're retiring the forums!

The SilverStripe forums have passed their heyday. They'll stick around, but will be read only. We'd encourage you to get involved in the community via the following channels instead:

General Questions /

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

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

Templates - Accessing an object within an object


Go to End


3 Posts   1095 Views

Avatar
Double-A-Ron

Community Member, 607 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, 96 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, 607 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