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.

DataObjectManager Module /

Discuss the DataObjectManager module, and the related ImageGallery module.

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

DOM - object seems to be empty?


Go to End


3 Posts   1472 Views

Avatar
richard-ward

Community Member, 31 Posts

14 August 2010 at 2:24am

Edited: 14/08/2010 2:24am

Hi,

I am struggling with the following - I am trying to get a list of Related Links onto my page. I have created a RelatedLink object and used the DOM to add it to my admin page. This has worked exactly as expected and I am able to add data objects as i would expect. The issue comes when trying to view them on the page. It appears the RelatedLinks object is empty for some reason?! If i try to access a count on the page (see snippet below) it fails with the error Fatal error: Call to a member function Count() on a non-object in...

Any help very gratefully received!

Richard

	function RelatedLinks() {
		return $this->RelatedLinks->Count();
	}

Page.php

class Page extends SiteTree {
	
	static $db = array(
		'HighlightPage' => 'Boolean',
		'FeaturedText' => 'HTMLText'
	);
	
	static $has_one = array(
		"WidgetBar" => "WidgetArea"
	);
	
	static $has_many = array(
		"RelatedLinks" => "RelatedLink"
	);
	
	function getCMSFields() {
		$fields = parent::getCMSFields();

		$fields->addFieldToTab("Root.Content.FeaturedText", new CheckboxField(
			$name = "HighlightPage", 
			$title = "Highlight this page"));
		
		$fields->addFieldToTab("Root.Content.FeaturedText", new HtmlEditorField(
			$name = "FeaturedText",
			$title = "Add content to the Featured Box on this page"));
		
		$fields->addFieldToTab("Root.Content.RelatedLinks", new DataObjectManager(
			$this,
			'RelatedLinks',
			'RelatedLink',
			array('LinkTitle' => 'LinkTitle', 'LinkURL' => 'LinkURL')
		));
		
		if (Permission::check('ADMIN')) {
			$fields->addFieldToTab("Root.Content.WidgetBar", new WidgetAreaEditor("WidgetBar"));
		} else {
			$fields->removeFieldFromTab("Root","Access");
			$fields->removeFieldFromTab("Root","Behaviour");
			
			$fields->removeFieldFromTab("Root.Content","Google Sitemap");
			$fields->removeFieldFromTab("Root.Content","Metadata");
			
			$fields->removeFieldFromTab("Root.Content","Widgets");
		}
		
		return $fields;
	}
	
	function highlightPage() {
		return $this->HighlightPage ? "highlight" : null;
	}

	function RelatedLinks() {
		return $this->RelatedLinks->Count();
	}
}

class Page_Controller extends ContentController {
	
	public function init() {
		parent::init();
	}
}

RelatedLink.php

class RelatedLink extends DataObject {
	static $db = array(
		'LinkTitle' => 'Varchar',
		'LinkURL' => 'Text'
	);
  
	static $has_one = array(
		'Page' => 'Page'
	);
	
	function getCMSFields_forPopup() {
		$fields = new Fieldset();
		$fields->push(new TextField('LinkTitle', 'Link title'));
		$fields->push(new TextField('LinkURL', 'Link URL'));
		return $fields;
	}
}

Avatar
UncleCheese

Forum Moderator, 4102 Posts

14 August 2010 at 2:58am

Edited: 14/08/2010 2:59am

Yikes. There's a lot wrong with that. First, let's look at your "RelatedLinks" function:

return $this->RelatedLinks->Count();

First, RelatedLinks is not a property of the object the way that native db fields are. That relation has to be called as a function. Second, don't daisy chain a function like that unless the previous function is guaranteed to return an object. RelatedLinks could return false if there are no links.

Something like this would work better:

return $this->RelatedLinks() ? $this->RelatedLinks()->Count() : 0;

But that seems like an unnecessary function to add to your controller. I would just do it on the template, unless you have some extraordinary reason for using it in your code.

$RelatedLinks.Count

Lastly, the much bigger issue, you've overloaded the function "RelatedLinks" which is given to you as a wrapper method to get your RelatedLinks component. This is going to break all kinds of stuff, because now, "RelatedLinks" which is supposed to return a DataObjectSet now returns an integer.

So don't overload RelatedLinks. Get rid of that function all together unless you have some really custom stuff you want to do to get those related objects. Change your current "RelatedLinks" function to "RelatedLinksCount", or, as I said above, just handle that on the template.

Avatar
richard-ward

Community Member, 31 Posts

14 August 2010 at 3:07am

Thanks for the reply.

I did wonder about the RelatedLinks not being a property of the object in that I am using this elsewhere and had been calling it as an function - my mistake. As for the daisy chaining - have no fear - i would not have left it like that in the finished app - as a professional Java developer I am all too aware of the risk of Null Pointer Exceptions!!

I was certain I had tried without the function at all and it did not seem to work, so I am not sure what I must have done, but it is indeed working without!

As for the overloading of the method - rest assured that was originally just return $this->RelatedLinks; without the count - I only added that to work out why nothing was being returned, but accept I should have changed the method name in the example.

In any case - having embarrassed myself with a load of mistakes etc. in the example, it is not working!

Kind regards UncleCheese,

Richard