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've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

DataObjectManager Module /

Discuss the DataObjectManager module, and the related ImageGallery module.

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

New Feature: Intelligent Constructor


Go to End


3 Posts   2367 Views

Avatar
UncleCheese

Forum Moderator, 4102 Posts

11 September 2009 at 4:11am

Many times when using a DOM on your page, you're forced to feed the object a lot of information that is repetitive and redundant. The DataObjectManager and all of its children will now make assumptions about the name, source class, headings, and popup fields. In the following example, I have a very simple DataObject with a very simple relation to its page:

Product.php

class Product extends DataObject
{
  static $db = array (
    'Title' => 'Varchar(50)',
    'Description' => 'Text',
    'Price' => 'Decimal',
    'OutOfStock' => 'Boolean'
    
  );
  
  static $has_one = array (
    'StorePage' => 'StorePage',
    'ProductImage' => 'Image'
  );
  
  function getCMSFields()
  {
    return new FieldSet(
      new TextField('Title'),
      new TextareaField('Description'),
      new NumericField('Price'),
      new CheckboxField('OutOfStock','This product is out of stock'),
      new ImageField('ProductImage')
    );
  }
}

StorePage.php

class StorePage extends Page
{
	static $has_many = array (
	 'Products' => 'Product'
	);
	
	public function getCMSFields()
	{
		$fields = parent::getCMSFields();
    $fields->addFieldToTab("Root.Content.Products", new DataObjectManager($this));		
		return $fields;
	}
}

class StorePage_Controller extends Page_Controller
{
}

Notice that we have greatly reduced the amount of data we need to feed the DataObjectManager function. Even though we have only passed the controller ($this), it still produces the following result:

Without the intelligent constructor, the code would look like this:

new DataObjectManager(
$this,
'Products',
'Product',
array(
'Title' => 'Title',
'Description' => 'Description',
'Price' => 'Price',
'OutOfStock' => 'Out Of Stock'
),
'getCMSFields'
);

If we want to customize the table headings, we can define in the DataObject:

  static $summary_fields = array (
    'Title' => 'Title',
    'Description' => 'Description'
  );

This produces the following:

How it works

It's not rocket science. :)

- If the name AND source class are left undefined, it will take the first has_many relationship off your controller. In this case, my controller $has_many Products, so it uses that. Right now, relation DOMs will not be able to use intelligent constructors.

- If the headings are left undefined, it loops through your $db array, and formats your fields with a friendly string. (OutOfStock becomes Out Of Stock).

- If the popup fields are left undefined, it uses getCMSFields(). This has always been true with DOM and CTF alike. Very handy.

That's it! For more complex pages, you'll obviously still have to use the full constructor, but if you're like me, you get into a lot of situations where feeding the DOM a bunch of data it should be able to figure out on its own is a bit tedious.

Enjoy!

Avatar
bummzack

Community Member, 904 Posts

23 September 2009 at 12:30am

Nice feature UncleCheese. Reduces setup time and avoids common mistakes.
When a DataObject has been set to sortable, the "Sort Order" Column also shows up in the automatically generated table headers. I would probably prevent that from happening.. apart from this, another sweet new feature! Thanks.

Avatar
UncleCheese

Forum Moderator, 4102 Posts

23 September 2009 at 1:00am

Great catch. Thanks, Banal.