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   1167 Views

Avatar
hypnosis

Community Member, 5 Posts

27 August 2010 at 9:42pm

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

Forum Moderator, 4094 Posts

28 August 2010 at 2:50am

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

Community Member, 5 Posts

28 August 2010 at 6:42am

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

Forum Moderator, 4094 Posts

28 August 2010 at 7:12am

Edited: 28/08/2010 7:12am

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

Community Member, 5 Posts

28 August 2010 at 9:16am

Edited: 28/08/2010 9:24am

thanks for advise about DataObjectDecorator

Avatar
hypnosis

Community Member, 5 Posts

28 August 2010 at 9:18am

Edited: 28/08/2010 9:22am

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

Community Member, 5 Posts

28 August 2010 at 9:23pm

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

Forum Moderator, 4094 Posts

29 August 2010 at 3:35am

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.