3373 Posts in 998 Topics by 712 members
|Go to End|
15 July 2010 at 6:11pm
Has anyone done any work towards supporting non-integer identifiers in the datamodel, or through RestfulServer?
A bit of background. The data objects I'm working with all have natural string-like keys, similar to Member::Email or Group::Code. Particularly for API access I'm keen to be able to use these as identifiers, rather than requiring an extra round-trip to obtain the ID and the extra client-side housekeeping involved in remembering it. It's also nice for inter-system communication and sharing URLs to have a human-readable identifier present.
Given how heavily the guts of DataObject depend on integer IDs I don't mind these remaining in the database, but I'm trying to come up with a nice way of providing alternative access by the string-like natural key.
The approach I'm toying with at the moment is uniformly using a field with a unique index on all such objects -- at the moment this is Name (perhaps Code would be better? Am I better off not using Name?). Common functionality to all the DataObjects enforces normalisation of the name on creation, and disallows any changes after creation. This all works quite nicely.
The next step is to alter URL handling in RestfulServer so that /api/v1/(ClassName)/(ID) (and descendants) will look up the object based on the Name column if ID is not an integer (if it wasn't for descendants, I could do this with a RewriteRule). This is straightforward enough -- I haven't seen any deep dependencies that will break in RestfulServer if I simply intercept the URL dispatch to behave like this. Perhaps overloading /api/v1/ like this is is a bad idea though?
Foreign keys present a bit more of a problem. I'm currently accepting create and update with related objects specified by Name by handling it in the validate() method on the DataObject -- this seems to work well, and has already simplified forms, testing and some client-side code. Presenting relations by foreign key is obviously more sensitive, and I still haven't come up with a neat way to do this that's not going to lead to brittle code and difficulty tracking future Silverstripe releases.
This is mostly a brain dump, but I'm looking for ideas .. at some point I'm going to have to cross this bridge, so any input I can get on how others have or might approach this problem (or if they just think I'm crazy!) would be useful. Any thoughts?
27 July 2010 at 1:35pm
Thanks for the reply, some useful pointers in there.
I don't think the search interface will suffice (?Name=test), because I want to be able to call published methods on the objects and/or access their relations. The get_by_name and RelationFieldName methods will be useful though.
At this point I'm leaning towards forking RestfulServer and publishing on a different URL, as there are some other behaviour changes I'm after which "should" be backwards-compatible but I don't want to risk conflicting with the core. In particular, I want to be able to call methods by methods other than POST and have them return data to the client (see http://open.silverstripe.org/ticket/5814).
Your feedback is helpful and gives me some more sapphire code to read. Thanks, I'll update this thread as my approach stabilises; hopefully the community can benefit from my efforts.
|Go to Top|