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

has_one relation in DataObjectManager


Go to End


9 Posts   4159 Views

Avatar
martimiz

Forum Moderator, 1391 Posts

15 May 2009 at 11:54pm

Hi all,
I have this page where I'm using the DataObjectManager to manage a dataobject that in its turn has a has_one relation to another dataobject. I've created a dropdown within the getCMSFields_forPopup() function and that works very well, no probs here.

Now I'd like to show the content of one of the fields (let's say the Name) of the selected relation in the DataObjectManagers list. The selection query that collects the fields for the listing doesn't acknowledge that the managed object has this has_one relation, so no join is executed.

Can anybody think of a way around this - or am I missing something obvious here?

Avatar
UncleCheese

Forum Moderator, 4102 Posts

16 May 2009 at 3:21am

Looks like you need a custom getter, no?

class MyDataObject extends DataObject
{
function getRelatedDataObjectTitle()
{
return $this->RelatedDataObject()->Title;
}
}

new HasOneDataObjectManager(
$this,
'MyDataObjects',
'MyDataObject',
array('Foo' => 'Foo', 'Bar' => 'Bar' => 'RelatedDataObjectTitle' => 'Title of related object'),
'getCMSFields_forPopup'
);

or..

I think this will work

array('Foo' => 'Foo', 'Bar' => 'Bar' => 'RelatedObject.Title' => 'Title of related object'),

Avatar
martimiz

Forum Moderator, 1391 Posts

17 May 2009 at 12:49am

Thanx UncleCheese,

I'm not shure yet how this is going to work, but I'm going to give it a try :-)

Avatar
martimiz

Forum Moderator, 1391 Posts

17 May 2009 at 2:55am


... and it works like a charm, thanks a million :-)

I did use DataObjectManager though, replacing it by HasOneDataObjectManager for some reason throws the following error:

Missing argument 1 for DataObject::get(), called in XXXXXXXX/sapphire/core/ViewableData.php

Avatar
timwjohn

Community Member, 98 Posts

22 March 2010 at 11:01am

Hi,

Never thought of using a custom getter. It does indeed work in order to create and populate this extra column - except that when you do a column sort, it breaks. The SQL query executed is trying to sort using a field that doesn't exist.

Same goes with your second suggestion of using 'Table.Field', as the SELECT clause doesn't include the field automatically. I stuck a LEFT JOIN in the $sourceJoin param and somehow that fixed it. Can't say I fully understand how!

What this seems to have done is disable sorting of that field. Any idea how to get sorting working?

Avatar
UncleCheese

Forum Moderator, 4102 Posts

22 March 2010 at 12:25pm

You'll see that the IsSortable logic in DataObjectManager is simply to check if the field exists:

	      "IsSortable" => singleton($this->sourceClass)->hasField($fieldName),

Apparently, hasField() returns true for custom getters. Go figure.

Latest rev uses hasDatabaseField() instead. Should take care of that for you.

Avatar
timwjohn

Community Member, 98 Posts

22 March 2010 at 1:19pm

Ahh, I see! That at least prevents sorting of fields using a getter. I haven't switched to the latest rev yet. Got to check a bug and get back to you on it first!

I've gone for the join clause option - and probably will do from now on as, even though you can't sort the column, you can create working filters that refer to the joined field. For those interested, I did so using

		$category_manager->setFilter(
			'Sector.Name',
			'Filter by Sector',
			DataObject::get('Sector')->toDropDownMap('Name', 'Name')
		);

A word of warning - there isn't a lot of flexibility when dealing with fields of the same name in this case. I had to change Category.Name to Category.CategoryName to prevent Sector.Name appearing in both columns.

Avatar
UncleCheese

Forum Moderator, 4102 Posts

22 March 2010 at 2:29pm

Edited: 22/03/2010 2:31pm

Just a heads up, never run a ->toDropdownMap() directly off a DataObject::get(), because if the query fails, you'll get a fatal error. Write up some logic to return an empty array if the query fails.

As far as the naming collisions, that's just bad practice. You should be using aliases when doing joins to avoid that.

Go to Top