2011-04-15 11:35:30 +02:00
# DataExtension
2011-02-07 07:48:44 +01:00
## Introduction
2011-04-15 11:35:30 +02:00
Extensions allow for adding additional functionality to a `[api:DataObject]` .
2011-02-07 07:48:44 +01:00
In some cases, it can be easier to completely replace the used class throughout the core with your custom
implementation. Have a look at `[api:Object->useCustomClass()]` .
## Usage
2013-03-16 05:15:50 +01:00
Your extension will need to be a subclass of `[api:DataExtension]` or the `[api:Extension]` class.
2011-02-07 07:48:44 +01:00
:::php
< ?php
2013-03-27 12:06:57 +01:00
// mysite/code/MyMemberExtension.php
class MyMemberExtension extends DataExtension {}
2011-02-07 07:48:44 +01:00
This defines your own extension where you can add your own functions, database fields or other properties you want.
After you create this extension however it does not yet apply it to your object. Next you need to tell SilverStripe what
class you want to extend.
2011-04-15 11:35:30 +02:00
### Adding a extension to a built-in class
2011-02-07 07:48:44 +01:00
2013-03-27 12:06:57 +01:00
Sometimes you will want to add extension to classes that you can't cleanly subclass.
For example, you might want to add a `MyMemberExtension` class to the `[api:Member]` object.
2011-02-07 07:48:44 +01:00
2013-03-27 12:06:57 +01:00
In order to active this extension, you'd add the following to your [config.yml ](/topics/configuration ).
2011-02-07 07:48:44 +01:00
2013-03-27 12:06:57 +01:00
:::yml
Member:
extensions:
- MyMemberExtension
2011-02-07 07:48:44 +01:00
2013-03-27 12:06:57 +01:00
Alternatively, you can add extensions through PHP code as well (in your `config.php` file),
which means they can be used in conditional configuration.
2011-02-07 07:48:44 +01:00
:::php
2013-03-27 12:06:57 +01:00
// Preferred notation: Through the Config API
Config::inst()->update('Member', 'extensions', array('MyMemberExtension'));
// Legacy notation: Through static class access
Member::add_extension('MyMemberExtension');
2011-02-07 07:48:44 +01:00
## Implementation
### Adding extra database fields
2012-06-28 11:43:56 +02:00
Extra database fields can be added with a extension in the same manner as if they
were placed on the `DataObject` class they're applied to. These will be added to the table of the base object - the extension will actually edit the $db, $has_one, etc static variables on load.
2011-02-07 07:48:44 +01:00
The function should return a map where the keys are the names of the static variables to update:
:::php
2011-04-15 11:35:30 +02:00
class CustomMember extends DataExtension {
2013-03-21 19:48:54 +01:00
private static $db = array(
2012-06-28 11:43:56 +02:00
'AvatarURL' => 'Varchar',
);
2013-03-21 19:48:54 +01:00
private static $has_one = array(
2012-06-28 11:43:56 +02:00
'RelatedMember' => 'Member',
);
2011-02-07 07:48:44 +01:00
}
### Modifying CMS Fields
2012-06-28 11:43:56 +02:00
The member class demonstrates an extension that allows you to update the default CMS fields for an
object in an extension:
2011-02-07 07:48:44 +01:00
:::php
public function getCMSFields() {
2012-06-28 11:43:56 +02:00
// ...
$this->extend('updateCMSFields', $fields);
return $fields;
2011-02-07 07:48:44 +01:00
}
2012-06-28 11:43:56 +02:00
The `$` fields parameter is passed by reference, as it is an object.
2011-02-07 07:48:44 +01:00
:::php
2011-10-28 03:37:27 +02:00
public function updateCMSFields(FieldList $fields) {
2012-06-28 11:43:56 +02:00
$fields->push(new TextField('Position', 'Position Title'));
$fields->push(new UploadField('Image', 'Profile Image'));
2011-02-07 07:48:44 +01:00
}
### Custom database generation
2011-04-15 11:35:30 +02:00
Some extensions are designed to transparently add more sophisticated data-collection capabilities to your data object.
2011-03-08 22:05:51 +01:00
For example, `[api:Versioned]` adds version tracking and staging to any data object that it is applied to. To do this,
you need to be able to create additional database tables and fields to keep your state stored in.
2011-02-07 07:48:44 +01:00
2011-04-15 11:35:30 +02:00
To do this, define an **augmentDatabase()** method on your extension. This will be called when db/build is visited.
2011-02-07 07:48:44 +01:00
2011-03-08 22:05:51 +01:00
* You can query ``$this->owner`` for information about the data object, such as the fields it has
2011-02-07 07:48:44 +01:00
* You can use **DB::requireTable($tableName, $fieldList, $indexList)** to set up your new tables. This function takes
care of creating, modifying, or leaving tables as required, based on your desired schema.
### Custom write queries
If you have customised the generated database, then you probably want to change the way that writes happen. This is
2011-03-08 22:05:51 +01:00
used by `[api:Versioned]` to get an entry written in ClassName_versions whenever an insert/update happens.
2011-02-07 07:48:44 +01:00
To do this, define the **augmentWrite(&$manipulation)** method. This method is passed a manipulation array representing
the write about to happen, and is able to amend this as desired, since it is passed by reference.
### Custom relation queries
The other queries that you will want to customise are the selection queries, called by get & get_one. For example, the
Versioned object has code to redirect every request to ClassName_live, if you are browsing the live site.
To do this, define the **augmentSQL(SQLQuery &$query)** method. Again, the $query object is passed by reference and can
be modified as needed by your method. Instead of a manipulation array, we have a `[api:SQLQuery]` object.
### Additional methods
2011-04-15 11:35:30 +02:00
The other thing you may want to do with a extension is provide a method that can be called on the `[api:DataObject]` that is
being extended. For instance, you may add a publish() method to every `[api:DataObject]` that is extended with `[api:Versioned]` .
2011-02-07 07:48:44 +01:00
2011-04-15 11:35:30 +02:00
This is as simple as defining a method called publish() on your extension. Bear in mind, however, that instead of
2011-02-07 07:48:44 +01:00
$this, you should be referring to $this->owner.
2011-04-15 11:35:30 +02:00
* $this = The `[api:DataExtension]` object.
2011-03-08 22:05:51 +01:00
* $this->owner = The related `[api:DataObject]` object.
2011-02-07 07:48:44 +01:00
2011-04-15 11:35:30 +02:00
If you want to add your own internal properties, you can add this to the `[api:DataExtension]` , and these will be referred
to as `$this->propertyName` . Every `[api:DataObject]` has an associated `[api:DataExtension]` instance for each class that it is
extended by.
2011-02-07 07:48:44 +01:00
:::php
class Customer extends DataObject {
2013-03-21 19:48:54 +01:00
private static $has_one = array('Account'=>'Account');
2011-02-07 07:48:44 +01:00
2013-03-21 19:48:54 +01:00
private static $extensions = array(
2011-02-07 07:48:44 +01:00
'CustomerWorkflow'
);
}
class Account extends DataObject {
2013-03-21 19:48:54 +01:00
private static $db = array(
2011-02-07 07:48:44 +01:00
'IsMarkedForDeletion'=>'Boolean'
);
2013-03-21 19:48:54 +01:00
private static $has_many = array('Customers'=>'Customer');
2011-02-07 07:48:44 +01:00
}
2011-04-15 11:35:30 +02:00
class CustomerWorkflow extends DataExtension {
2011-02-07 07:48:44 +01:00
2012-01-30 23:13:42 +01:00
public function IsMarkedForDeletion() {
2011-02-07 07:48:44 +01:00
return ($this->owner->Account()->IsMarkedForDeletion == 1) ? true : false;
}
}
## API Documentation
2013-03-16 05:15:50 +01:00
`[api:DataExtension]`