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

[SOLVED] Finding and filtering multiple related data objects


Go to End


18 Posts   4240 Views

Avatar
Ryan M.

Community Member, 309 Posts

29 October 2010 at 12:59pm

Edited: 07/11/2010 2:18pm

I've been at this for a few hours already and my brain's starting to feel burnt out. All the dev work I've been doing lately sure isn't helping! So I need a fresh programmer's analytical mind for this.

Anyway, I have three classes and data object types: ClientCategory, Profile and Video. Video and ClientCategory are data objects, Profile is a page. I'm building a category page that features certain profiles and videos (selected via a checkbox in the admin). It displays only one of each at a time. The intention is to display featured video & profile that are within that category.

I have the featured profile one down, all it really is, is this:

$profile = DataObject::get_one("Profile", "ProfilePictureID != 0 AND Featured = true AND ClientCategoryID = $ccid");

This bit of code gets the first profile that matches the current category. Straight forward.

The next part, the video, is a bit harder for me to wrap my head around. The Profile page has a has_one relationship with ClientCategory, however, the video does not. So what I'm trying to build is a function that will search profiles with a particular category id, return them, then search these profiles for videos marked as featured, and then return the first one of them.

Does anybody have any ideas?

SOLVED: Final code posted at end of thread.

Avatar
cuSSter

Community Member, 56 Posts

3 November 2010 at 2:05am

Why not create a relationship between Video and ClientCategory? Since you want to display feature video and profile that are within that ClientCategory? Just a thought. :)

Avatar
Ryan M.

Community Member, 309 Posts

4 November 2010 at 12:46pm

Because it was originally programmed without that in mind, and as a result there are hundreds of videos already created without the relationship. It'd be a pain in the butt to go and edit every one of them.

Avatar
cuSSter

Community Member, 56 Posts

4 November 2010 at 7:25pm

Edited: 04/11/2010 7:30pm

Yeah, I agree. Hmmm. So Videos don't have to fall under some ClientCategory? You just need to get a video that is tagged as featured? What I'm thinking is something like:

First, add a db field in your CategoryPage for that will store the featured video ID, e.g. FeaturedVideoID. Then a function like:

private function getAllVideos( &$fields ) {
	$videos = DataObject::get( 'Videos' );
	if( $videos->Count() > 0 ) {
		$checkboxFieldSet = new OptionsetField( 'FeaturedVideoID', 'Featured Video', $videos->toDropdownMap( 'ID', 'Title' ) );
		$fields->addFieldToTab( 'Location', $checkboxFieldSet );
	}
}

Then,

function getCMSFields() {
	$fields = parent::getCMSFields();
	...
	$this->getAllVideos( $fields );
}

I don't know if this is what you're looking for. Just my two cents. :)

/C

Avatar
Ryan M.

Community Member, 309 Posts

4 November 2010 at 8:00pm

What I'm looking for is more like:

$profiles = DataObject::get('Profile', 'ClientCategoryID = $ccid');
$vids = new DataObjectSet();
foreach($profiles as $profile => $data) {
   foreach($data->Videos() as $video) {
      $record = array('VideoID' => $video->ID);
      $vids->push(new ArrayData($record));
   }
}
return $vids;

Avatar
Ryan M.

Community Member, 309 Posts

4 November 2010 at 9:06pm

Edited: 04/11/2010 9:09pm

Been working on it a bit now... this is what I have so far:

public function FeaturedVideo() {
		$vid = null;
		if($ClassName = "ProfileHolder" && $cat = $this->urlParams['ID']) {
			$catname = $cat;
			$cat = str_replace('-', ' ', $cat);
			$cat = ucwords($cat);
			$ccid = DataObject::get_one("ClientCategory", "Name = '{$cat}'")->ID;
			$profiles = DataObject::get("Profile", "ClientCategoryID = $ccid");
			$videoIDs = array();
			foreach($profiles as $profile => $data) {
				foreach($data->Videos() as $video) {
					$videoIDs[] = $video->ID;
				}
			}
			$vids = new DataObjectSet();
			foreach($videoIDs as $id) {
				$record = DataObject::get_by_id("Video", $id);
				$vids->push(new ArrayData($record));
			}
			$vids->sort('Created', 'DESC');
			$videos = $vids->find('Featured', 'true');
			print_r($videos); die();
			$vid = $vids->First();
			print_r($vid); die();
		}
		if($vid) {
			return DataObject::get_by_id("Video", $vid->ID);
		} else
			return DataObject::get_one("Video", "Featured = true");
	}

Problem is, at the first print_r, I get a blank screen. There's no data to display. However, if I move the print_r up one line for $vids, it prints all the data objects retrieved. For some reason, the find() feature isn't working as expected on the DataObjectSet.

Avatar
cuSSter

Community Member, 56 Posts

4 November 2010 at 9:07pm

So you'll just call it straight ahead from the template and get the first vid? I thought you want to set it in the CMS admin?

Avatar
Ryan M.

Community Member, 309 Posts

4 November 2010 at 9:10pm

Pinoy_SS, it's meant to select the first featured video in that particular category.

Go to Top