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

How can I manually join 2 DataObjects?


Reply

5 Posts   1790 Views

Avatar
andy_steel

2 March 2010 at 1:28am Community Member, 31 Posts

I've tried doing the following, but it does not work.

$products = DataObject::get('Product'); // Product has a has_one relationship to Image
$images= DataObject::get('Image');

foreach ($products as $product) {
   
   foreach ($images as $image) {
      
      if ($product->ImageID == $image->ID) {
         
         $product->setComponent('Image', $image);
         break;
      }
   }
}

// even though an image has been assigned, it still queries the database.
$products->First()->Image();

Has anyone else had this issue?

Avatar
Pigeon

2 March 2010 at 1:42pm (Last edited: 2 March 2010 2:18pm), Community Member, 243 Posts

Hey Andy,

What debugging have you done? Does $products->First()->getComponent('Image') return it?

I had a dig in the [url=http://api.silverstripe.org/sapphire/core/DataObject.html]DataObject[/url] class and what you're doing does seem right; although I cant find where the Image() function is created and thus whether it is likely to call [url=http://api.silverstripe.org/sapphire/core/DataObject.html#getComponent]getComponent()[/url].

Ok, i did some more digging; i think that its a bit more complex than just setting components. You might be able to just use the [url=http://api.silverstripe.org/sapphire/core/DataObject.html#getComponent]getComponent[/url] method as a quick fix, but you might need to seriously investigate how the [url=http://api.silverstripe.org/sapphire/core/DataObject.html]DataObject[/url] class works. Looks like you might need to [url=http://api.silverstripe.org/default/Object.html#methodaddWrapperMethod]addWrapperMethod()[/url] or [url=http://api.silverstripe.org/default/Object.html#createMethod]createMethod()[/url] on the object. It seems that [url=http://api.silverstripe.org/sapphire/core/DataObject.html#methoddefineMethods]defineMethods()[/url] is only called on instantiation of the product data object, rather than on a call to a method.

Hope that helps.

Avatar
andy_steel

2 March 2010 at 10:26pm (Last edited: 2 March 2010 10:31pm), Community Member, 31 Posts

Hi Pigeon,

Thanks for looking into this. I've had a closer look at DataObject and I think the reason why its not returning an object is because an MD5 sum is used to take into account joins, filters, limits etc. Since no MD5 is added when adding the object via setComponent(), getComponent() doesn't work since it calculates an MD5 sum.

I'll report this as a bug on the issue tracker.

Avatar
Pigeon

3 March 2010 at 1:58am (Last edited: 3 March 2010 1:58am), Community Member, 243 Posts

Hi Andy,

I dont think that's right. [url=http://api.silverstripe.org/sapphire/core/DataObject.html#getComponents]getComponents()[/url] appends a MD5 string, but [url=http://api.silverstripe.org/sapphire/core/DataObject.html#getComponent]getComponent()[/url] doesn't.

DataObject.php Line 1036:

public function getComponent($componentName) {
      if(isset($this->components[$componentName])) {
         return $this->components[$componentName];
      }

Avatar
andy_steel

3 March 2010 at 2:12am Community Member, 31 Posts

I've managed to fix it by adding the following lines 3 lines to getComponent() in DataObject.php:

   public function getComponent($componentName) {
      
      if(isset($this->componentCache[$componentName])) {
         return $this->componentCache[$componentName];
      }

It wasn't checking the componentCache array.