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.

Data Model Questions /

Enumerated types - implement as lookups?


Reply


3 Posts   2283 Views

Avatar
Judge

Community Member, 79 Posts

22 February 2010 at 11:29pm

Edited: 23/02/2010 12:27am

Say I have a data type that contains a range of values:

'DocumentType' => "Enum('CV,Supporting information,Certificate,Other','')"

Those enumerated types are used for both labels in drop-down lists (or radio buttons) *and* to define the enumerated values in the database. I would prefer to use something less "natural language" in the database to make it easier to code around, e.g. to put together custom queries, to program business logic using values such as "CV", "SUPP" and "CERT".

What would be the usual way to do this in SilverStripe? Would I use the international/translations feature, for example, to map the codes onto English phrases (CERT => Certificate) in the front end? Would this be automatic once it is set up? Would I need to use my own lookup table to do the translation, and code that translation myself?

Or would I need to hard-code a lookup table into the model in some way?

I guess this would equally apply if the module were to support multiple languages. Seeing as SS provides a lot of functionality for free, I'm just wondering if this is already covered in the core.

-- Jason

Edit: I think [url url="http://doc.silverstripe.org/doku.php?id=i18n"]this page[/url] is saying that I cannot use the built-in translations for the form drop-down lists, so that discounts that approach.

Avatar
Judge

Community Member, 79 Posts

23 February 2010 at 1:12am

Edited: 23/02/2010 1:32am

Maybe something like this is the way to handle it:

class MyClass extends DataObject {
static $db = array('MyField' => "Enum('KEY1,KEY2,KEY3', 'KEY1')");

function getCMSFields() {
// Get all the fields.
$fields = parent::getCMSFields();

// Get just the field we are interested in (the enum type)
$myfield = $fields->dataFieldByName('MyField');

// Get the list of key/values
$source = $myfield->getSource();

// Translate each key/value
foreach($source as $key => $value) $src[$key] = _t('MyContext.' . $key, $value);

// Put the key/values back into the field.
$myfield->setSource($source);

// Put the field back into the dropdown list.
$fields->replaceField('MyField', $myfield);

// Return the modified fieldset.
return $fields;
}

then in the language file (lang/en_GB.php):

$lang['en_GB']['MyContext']['KEY1'] = 'Natural language 1'; // Possibly run this through _t()
$lang['en_GB']['MyContext']['KEY2'] = 'Natural language 2';
$lang['en_GB']['MyContext']['KEY3'] = 'Natural language 3';

This certainly works, in that the enumerated values set for the data field are displayed in translated form in the default admin forms. It has the disadvantage of exposing the user to the underlying keys if there happens not be a translation in their language, rather than dropping back to English. It is probably overkill for what I want to achieve, and I'll probably just hard-code the drop-down list translation as a public array property in the data model and reference that anywhere that the values or keys are needed, i.e.

public $myfield_values array(
'KEY1' => ''Natural language 1',
'KEY2' => ''Natural language 2',
'KEY3' => ''Natural language 3',
);

static $db = array('MyField' => "Enum('" .implode(',',array_keys(MyClass::$myfield_values)). "', 'KEY1')");

etc.

Edit: of course, I can't use implode with a static variable declaration; just use whatever the functional equivalent is. The aim is to define all data just once, and once only.

Avatar
Ingo

Forum Moderator, 801 Posts

21 March 2010 at 9:30am

There's DataObject->fieldLabels() for the equivalent on $db, but thats just for the actual field labels, not their enumerated values.
I think your approach is valid, I'd just change all the _t() calls to be performed in provideI18nEntities() calls to make them work with i18nTextCollectorTask. This means you don't have to write the $lang files yourself. This isnt well documented at the moment, but you'll get the idea when you look through the core code.