[silverstripe-dev] Multivalue fields

159 views
Skip to first unread message

Marcus Nyeholt

unread,
May 13, 2010, 1:53:55 AM5/13/10
to silverst...@googlegroups.com
Is there a field type or configuration option to provide multivalue fields for things like storing arrays of values against an object, even if it's serialised and not queryable? I've noticed the 'arrayValue' property on some field classes, but I'm not sure exactly of its purpose and can't see any example usage that does what I'm after.

Something like

static $db = array('Information' => 'MultiValue');
$obj->Information = array('One', 'Two', 'Three');

// Information is serialised on write for storage
$obj->write(); 


$obj = DataObject::get()
// Information is deserialised
foreach ($obj->Information as $val) {

}

Marcus

--
You received this message because you are subscribed to the Google Groups "SilverStripe Core Development" group.
To post to this group, send email to silverst...@googlegroups.com.
To unsubscribe from this group, send email to silverstripe-d...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/silverstripe-dev?hl=en.

Sam Minnee

unread,
May 13, 2010, 6:25:22 AM5/13/10
to SilverStripe Core Development
On May 13, 5:53 pm, Marcus Nyeholt <nyeh...@gmail.com> wrote:
> Is there a field type or configuration option to provide multivalue fields
> for things like storing arrays of values against an object, even if it's
> serialised and not queryable? I've noticed the 'arrayValue' property on some
> field classes, but I'm not sure exactly of its purpose and can't see any
> example usage that does what I'm after.

I don't think so, the closest thing is MultiEnum, which maps to a SET
field in MySQL.

How would you envisage such a field was stored in the database?

The arrayValue thing refers to the configuration syntax, not to the
data storage.

Sam Minnee

unread,
May 13, 2010, 6:31:01 AM5/13/10
to SilverStripe Core Development
You could do something like this:

$db = array(
"InfoPacked" => "Text",
);

function getInfo() {
return unserialize($this->InfoPacked);
}
function onBeforeWrite() {
$this->InfoPacked = serialize($this->Info);
parent::onBeforeWrite();
}

....

$myObj = new ObjClass();
$myObj->Info = array('a' => 1, 'b' => 2, 'c' => 3);
$myObj->Info['b']++;
$myObj->write();

I'd recommend using onBeforeWrite() rather than setInfo(), because
otherwise I don't think "$myObj->Info['b']++;" would work.

You could probably make a class, SerializedField..

class SerializedField extends DBField implements CompositeDBField { }

Except then you'd probably be looking to do something like this,
because $myObj->Info would return a SerializedField instance.

$myObj->Info->data = array('a' => 1, 'b' => 2, 'c' => 3)

Marcus Nyeholt

unread,
May 13, 2010, 11:52:42 AM5/13/10
to silverst...@googlegroups.com
I'd actually whipped up a quick implementation a couple of weeks or so ago in a time of need, but came across MultiEnum and thought there might be something that already did what I was after written by someone who knows more about DBFields :). It's a DB field type that serializes and unserializes at appropriate times, though as you mention, you need to work with the fact that sometimes it's an object returned by $this->Info when implementing CompositeDBField. 

http://github.com/nyeholt/silverstripe-multivaluefield for anyone playing along at home and wants to try it out (check the tests for usage) - there's also a UI field for inputting values that dynamically adds and removes rows as needed. 

And a quick disclaimer for everyone - don't use this as a way around doing proper normalisation of database tables or to just "stick stuff in there for now, I'll do it properly later". Once data is stored in this manner, it is not queryable by normal means. The usecase I have for this is > 20 fields for a document that all could have multiple values per field (think ultra metadata - check http://github.com/nyeholt/silverstripe-alchemiser/blob/master/code/extensions/Alchemisable.php for what I mean). Imagine how many additional joins would be required to load a complete representation of your page :). Additionally, for searching purposes all of this metadata is being indexed by another system that does searching on multivalued fields without a problem, so the big downfall of serialisation is avoided. 
Reply all
Reply to author
Forward
0 new messages