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.

DataObjectManager Module

Discuss the DataObjectManager module, and the related ImageGallery module.

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

error HasMethod in DataObjectDecorator and DOM


Reply

8 Posts   1142 Views

Avatar
hypnosis

27 August 2010 at 9:42pm Community Member, 5 Posts

Hello can you help to solve this problem?

Model Product

<?php
class Product extends DataObject {
   static $singular_name = 'Product';
   static $plural_name = 'Products';
   
   static $db = array(
      'Title' => 'Text',
      'Price' => 'Currency',
      'Description' => 'HTMLText',
      'TopProduct' => 'Boolean'
   );
public function getCMSFields_forPopup()   {
      return new FieldSet(
         new TextField('Title', 'Product Title'),
         new CurrencyField('Price', 'Price'),
         new SimpleWysiwygField ('Description', 'Product Description'),
         new CheckboxField('TopProduct', 'Top product')
      );
   }
}

model Trailer

<?php
class Trailer extends DataObjectDecorator {
   static $singular_name = 'Trailer';
   static $plural_name = 'Trailers';

   function extraStatics() {
      return array(
         'db' => array(
   
         ),
         'has_one' => array(
            'TrailerCategory' => 'TrailerCategory',
            'TrailerStuff' => 'TrailerStuff'
         )
      );
   }
            
   function updateCMSFields(FieldSet &$fields) {
      $trailerStuff = new DataObjectManager($this,'TrailerStuff','TrailerStuff');
      $fields->push($trailerStuff);
   }   
}

and page model

static $has_many = array('Trailers' => 'Trailer');

   static $singular_name = 'Trailer category';
   static $plural_name = 'Trailer categories';
   
   function getCMSFields() {
      $fields = parent::getCMSFields();
      $trailersTable = new DataObjectManager($this, 'Trailers','Trailer',array('Title' => 'Title'),
         'getCMSFields_forPopup');
      $fields->addFieldToTab('Root.Content.Trailers', $trailersTable);
      return    $fields;
   }


I use DataObjectDecorator for my extensible dataObject and when i try to add this to DataObjectManager i show error

Call to undefined method Trailer::hasMethod()

Avatar
UncleCheese

28 August 2010 at 2:50am 4085 Posts

Why are you using a decorator? That doesn't look like a proper decorator at all. You have some statics in extraStatics() and others are in the class definition. What is this object decorating? DOM manages DataObjects, not dataobject decorators.

Avatar
hypnosis

28 August 2010 at 6:42am Community Member, 5 Posts

I have common properties in Product Class like so Title, Description and Image List, and i want to extend some classes like Trailer or Trucks, that need to get common properties and to extend some individual properties.

DOM looks like

Title
Description

Property#1
Property#2
.....
Images

[Save to Add Images and Attaches]

Avatar
UncleCheese

28 August 2010 at 7:12am (Last edited: 28 August 2010 7:12am), 4085 Posts

What you're describing sounds like a subclass, not a decorator. I'm confused... why wouldn't you just create a subclass of Product?

Avatar
hypnosis

28 August 2010 at 9:16am (Last edited: 28 August 2010 9:24am), Community Member, 5 Posts

thanks for advise about DataObjectDecorator

Avatar
hypnosis

28 August 2010 at 9:18am (Last edited: 28 August 2010 9:22am), Community Member, 5 Posts

Ok. I wrote code like you suggest me.
TrailerCategory

class TrailerCategory extends Page {
   
   static $has_many = array('Trailers' => 'Trailer');

   static $singular_name = 'TrailerCategory';
   static $plural_name = 'TrailerCategories';
   
   function getCMSFields() {
      $fields = parent::getCMSFields();
      $trailersTable = new DataObjectManager($this, 'Trailers','Trailer',
         array('getThumbnail' => _t('ProductCategory.PREVIEW'),'Title' => _t('ProductCategory.TITLE')),'getCMSFields_forPopup');

      $trailersTable->setParentClass('TrailerCategory');

      $fields->addFieldToTab('Root.Content.Trailers', $trailersTable);
      $wheelType = new DataObjectManager($this,_t('WheelType.LABEL'),'WheelType');
      $fields->addFieldToTab('Root.Content.WheelType', $wheelType);
      return    $fields;
   }
}

class TrailerCategory_Controller extends Page_Controller {}

Product

class Product extends DataObject {
   static $singular_name = 'Product';
   static $plural_name = 'Products';
   
   static $db = array(
      'Title' => 'Text',
      'Price' => 'Currency',
      'Description' => 'HTMLText',
      'TopProduct' => 'Boolean'
   );

   static $has_one = array(
      'Image' => 'Image'
   );
   
   static $has_many = array(
      'ProductImages' => 'ProductImage'
   );
   
   public function getCMSFields_forPopup()
   {
      $fields = new FieldSet(
         new TextField('Title', 'Product Title'),
         new CurrencyField('Price', 'Price'),
         new SimpleWysiwygField ('Description', 'Product Description'),
         new CheckboxField('TopProduct', 'Top product')
      );
      
      $imageDataObject = new ImageDataObjectManager($this, 'ProductImages','ProductImage', 'Attachment');
      $imageDataObject->setAllowedFileTypes(array('jpg','gif','png'));
      $imageDataObject->setBrowseButtonText('Upload (JPG,GIF,PNG)');
      $imageDataObject->setPluralTitle('Images');
      
      $fields->push($imageDataObject);
      
      return $fields;
   }
   
   function getThumbnail(){
      if($images = DataObject::get_one("ProductImage", "ProductId = {$this->ID}"))
      return ($img = $images->Attachment()) ? $images->Thumbnail() : "no image";
      return "no image";
   }
}

class Product_Controller extends Page_Controller {
}

Trailer

class Trailer extends Product {
   static $singular_name = 'Trailer';
   static $plural_name = 'Trailers';

   static $has_one = array(   
      'TrailerStuff' => 'TrailerStuff',
      'TrailerCategory' => 'TrailerCategory'
   );

   public function getCMSFields_forPopup()   {
      $fields = parent::getCMSFields_forPopup();
      $trailerStuff = new DataObjectManager($this,'TrailerStuff','TrailerStuff');
      $fields->push($trailerStuff);
      return $fields;
   }
      
}
class Trailer_Controller extends Product_Controller {
}

... and stuff
TrailerStuff

class TrailerStuff extends DataObject {   
   static $db = array(
      'GrossWeight' => 'Int',
      'TrailerWeight' => 'Int',
      'LoadWeight' => 'Int',
      'Length' => 'Int',
      'Axels' => 'Int',
      'Brake' => 'Boolean',
      'TopProduct' => 'Boolean',
   );
   
   static $has_one = array(
      'Trailer' => 'Trailer',
      'WheelType' => 'WheelType'
   );   

   function getCMSFields() {      
      $wheelType = Dataobject::get("WheelType");
      if ($wheelType) {
         $wheelType = $wheelType->toDropdownMap('ID', 'Type');
      }
      
      $fields = new FieldSet(
         new NumericField('GrossWeight', 'Gross Weight'),
         new NumericField('TrailerWeigh', 'Trailer Weight'),
         new NumericField('LoadWeight', 'Load Weight'),
         new NumericField('Width', 'Width'),
         new NumericField('Length', 'Length'),
         new NumericField('Axels', 'Axels'),
         new CheckboxField('Brake', 'Brake'),         
         new DropdownField(
            'WheelTypeID',
            'Please choose a wheel type',
            $wheelType)
      );
      return $fields;
   }
}

for stuff WheelType
WheelType

class WheelType extends DataObject {   
   static $db = array(
      'Type' => 'Text',
   );
   
   
   static $has_one = array(
      'TrailerStuff' => 'TrailerStuff'
   );   

   function getCMSFields() {      
      $fields = new FieldSet(
         new TextField('Type', 'Wheel type')         
      );
      return $fields;
   }
}

I catch error Couldn't run query: SELECT "Product"."ClassName", "Product"."Created", "Product"."LastEdited", "Product"."Title", "Product"."Price", "Product"."Description", "Product"."TopProduct", "Product"."ImageID", "Trailer"."TrailerStuffID", "Trailer"."TrailerCategoryID", "Product"."ID", CASE WHEN "Product"."ClassName" IS NOT NULL THEN "Product"."ClassName" ELSE 'Product' END AS "RecordClassName" FROM "Product" LEFT JOIN "Trailer" ON "Trailer"."ID" = "Product"."ID" WHERE ("Product"."ClassName" IN ('Trailer')) AND ("TrailerCategoryID" = '35') ORDER BY Created DESC LIMIT 10 OFFSET 0 Column 'TrailerCategoryID' in where clause is ambiguous

What i get wrong?

Avatar
hypnosis

28 August 2010 at 9:23pm Community Member, 5 Posts

Problem solved

code wrote right, problem was in ghosted table CategoryTrailerID. I delete tables in DB and create it by /dev/build?flush=1.
Thanx for advise. Realy nicefull modul.

Avatar
UncleCheese

29 August 2010 at 3:35am 4085 Posts

Yup. Good work. That's exactly what I was going to tell you to do. Silverstripe will create new fields, but it never deletes them. So if you change your model around, the issue of legacy fields colliding happens very frequently.