I have a few DataObjects
that have a price tier associated to them. I could build this relationship in another DataObject
however these tiers aren't going to change and I thought the best way was to define them in config.yml
.
Ideally I'd like to define the DataObject
like:
private static $db = array(
'Price' => 'Enum(array("Tier 1", "Tier 2"))'
)
However I can't think of a way to do this properly in SilverStripe having a single point of maintenance like a yaml
. I also thought of just making it a Varchar
and checking to make sure it's in the array before setting it however this won't allow things like populating lists and so forth via the enum (probably should call the config anyway I guess). I could also just write out the array however there would be at least two places for it which would be harder to maintain.
What's the best way to do what I'm trying to achieve which is several objects referencing an array set in a single place?
As shown by other answers, you can accomplish that in many ways. In a project I worked on for example I have something similar to the following:
// You need to put this into a _config.php. It copies the definition
// of DataObject2.Field2 into DataObject1.Field1.
$cfg = Config::inst();
$db = $cfg->get('DataObject1', 'db');
$db['Field1'] = $cfg->get('DataObject2', 'db')['Field2'];
$db = $config->update('DataObject1', 'db', $db);
But in my opinion the most elegant solution would be to define a new class, something like:
class MyEnum extends Enum
{
/**
* Enum values.
* @config
*/
private static $values;
public function __construct($name = null, $default = null)
{
parent::__construct($name, $this->config()->get('values'), $default);
}
}
After that you could define the values in plain YAML:
MyEnum:
values:
- First
- Second
...
I'm not 100% sure what you're asking, but if it's like the title and you're asking whether you can define Enum DB field values in YAML, yes - you can:
MyDataObject:
db:
Price: Enum("Tier 1,Tier 2")
What you can't do is add more values to the Enum from other configuration sources (including private statics), because the enum value is treated as a string literal rather than a YAML array.
If your question is "Can I define a common configuration for $db
and use it for multiple DataObjects", then the YAML approach (config in general) won't work, since configuration values are tied to a class and are parsed earlier in the process than when DataObject::database_fields
tells the DB schema what to do.
Of course you can add and overwrite $db
keys in your config yml like:
MyDataObject:
db:
Price: "Enum('Tier 1,Tier 2,Tier 3', 'Tier 3')"
Just be sure to use the right syntax for Enum, it's easier with the old comma seperated syntax. In the example above "Tier 3" is default.
With defining it in yml it might break the order when you use scaffolding, haven't tested this yet.
You might also think about using a has_one relation to a simple dataobject instead. You can manage that in a ModelAdmin and which might be easier to translate later on. Also the QuickAddNew module is a good helper to add new DOs on the fly beneath a dropdown field.
You could apply the same db fields to multiple DataObjects by creating a DataExtension and applying it to all the DataObjects you want to add the fields to.