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

[SOLVED] Finding and filtering multiple related data objects


Go to End
Reply


18 Posts   2716 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