1. DataObject::get() returns a traditional DataObjectSet, where .
DataList::create() will access the new ORM. The disadvantage of this
approach is that it won't be consistently - it won't apply to relation
methods and other places where you get DataObjects without explicitly
calling DataObject::get().
2. Use dependency injection to replace all DataLists, with something
like LegacyHybridList, that acts as a DataList until merge() is called
for the first time, at which point the DataList is "realised" and the
merge() function called.
3. Provide an easy hack - for example, new
DataObjectSet(DataObject::get('SiteTree')) - that will turn a DataList
into a traditional DataObjectSet that you can use merge(), etc, on.
Further to this...
- An abstract base class of all lists, implementing ArrayAccess,
IteratorAggregate, Countable, with no actual implementation itself.
(Presumably, getIterator and count() would be left abstract, an the
ArrayAccess methods have a default implementation with the use of
getRange()).
- A specific implementation of a list based on an internal array.
(like DataObjectSet is)
If SS_List were an abstract base class then we would need to create a
subclass of this called SS_ArrayList, SS_RealList, SS_SimpleList, or
something else, that implemented the current DataObjectSet functions.
The advantage of that is that we wouldn't need to stub out merge(),
insertFirst(), etc, on DataList, and we could instead leave them out
of the SS_List implementation. Instead, we would provide those
methods *only* on the SS_ArrayList class.
OK, cool.
> 3. Provide an easy hack - for example, new
> DataObjectSet(DataObject::get('SiteTree')) - that will turn a DataList
> into a traditional DataObjectSet that you can use merge(), etc, on.
> I assume that should read "DataObjectSet(DataList::create('SiteTree'))", right?
Well, DataObject::get('SiteTree') and DataList::create('SiteTree') do the same thing, given the above recommendation. But, do you think we should deprecate DataObject::get()?
Speaking of which, do we want to further refine the creation of DataLists?
We've seen these two:
- DataObject::get('SiteTree')
- DataList::create('SiteTree')
But we could make it a function (rather than a static method) for brevity:
- data('SiteTree')
We could also make it a method available on critical objects (to stop us from accessing a global)
- $this->data('SiteTree')
Or we could make it an object that had one property for each data type. This would make it easy to use DI to set $this->data.
- $this->data->SiteTree
Of all of those, I quite like the final one, but it's quite a shift. Here's an example:
function MenuItems() {
return $this->data->SiteTree->filter(array('ParentID' => 0, 'ShowInMenus' => true));
}
> +1 - lets keep it simple for now. I don't think we'll need to make $dataList1->merge($dataList2)
> work for now if we allow $dataList1->toArray()->merge($dataList2->toArray()).
It would probably be toArraylist() (because toArray() would return an actual array).
So, SS_ArrayList is a name that makes sense to everyone?
--
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.
Yeah, I think that there would still need to be a global data access layer, injected where appropriate.
In effect, these two statements might be equivalent:
model()->SiteTree->filter("URLSegment", "about-us");
$this->model->SiteTree->filter("URLSegment", "about-us");
The object returned by model() / $this->model of these would represent the data model in its entirety, rather than a single DataObject class.
The simplest implementation of this object would be something like this:
class DataModel {
function __call($func, $args) {
$this->modelByName($func);
}
function __get($property) {
$this->modelByName($proprety);
}
function modelByName($name) {
return DataList::create($name);
}
}
I think we need to make this decision in context of PHP 5.3, which will at some point become a minimum requirement.I don't want to go off-topic, but did we make a firm decision on that already or is it worth starting a new thread?
Specifically, late static binding could make for a lot less typing:DataList::create('Member') becomes Member::all()DataList::create('Member')->byId(5) becomes Member::by_id(5)DataList::create('Member')->find('Name', 'Elmo') becomes Member::find('Name', 'Elmo') or even Member::find_by_name('Elmo')Yes, it looks an awful lot like Rails, but thats not a bad thing per se, right? :)
For a PHP 5.2 compat solution: I like the idea of making the model access injectable via $this->data,
but struggle to come up with a use case where you'd want to inject a different datamodel wrapper globally(as opposed to using a different mapper based on model) - do you guys have an example?
Both $this->model and $this->data are very common property names, which isn't ideal,and can lead to weird situations when redefining them unknowingly.
Definetly prefer it over global methods - yes, it is shorter, but it sends the wrong message for suchan integral part of an OOP framework.
On 6 April 2011 21:52, Ingo Schommer <in...@silverstripe.com> wrote:
I think we need to make this decision in context of PHP 5.3, which will at some point become a minimum requirement.I don't want to go off-topic, but did we make a firm decision on that already or is it worth starting a new thread?The decision we previously made on 5.3 was "not yet", and I think that still holds. I we could potentially add 5.3-only features to the API that you could optionally use, but we couldn't use them in the CMS
Looking like Rails isn't a bad thing, but all those static methods are... ;-) Static methods share almost all the problems of functions.
You can still inject the implementation with static getters though, right?
I *do*, however, like the idea of being able to define custom filter methods like byName()...Using the property name "find" rather than "model" gives you a fluenty kind of syntax, although I think the 'punctucation volume'$this->find->SiteTree->byID(5);$this->find->SiteTree->withURLSegment('about-us');
For a PHP 5.2 compat solution: I like the idea of making the model access injectable via $this->data,but struggle to come up with a use case where you'd want to inject a different datamodel wrapper globally(as opposed to using a different mapper based on model) - do you guys have an example?- It means that you can inject the full data model as a whole, rather than needing to inject each model class separately.
Yeah, I guess you're right. I might be getting a little carried away in pursuit of semantic purity... I think it's probably best to actually wait until someone (me?) has succeeded in implementing a project or 2 without reference to statics before pitching it as the Next Big Thing. I am keen to explore it, however.
> DataList::create('SiteTree')->withURLSegment(...) isn't as expressive.
> I prefer findBy*() over with*(). For the sake of consistency, I'd also prefer findByID() over byID().
> We could then also have the current filter() method renamed to find()?
Yeah, maybe. To be honest I don't really have strong opinions and I'd be happy to go with consensus on the exact naming.
However, it should be clear whether something is returning a DataList or a DataObject.
> I see per-model (not per-class-context) injection as desireable though - e.g., how would you see support for certain models in legacy databases (with different database drivers) otherwise?
Not *exactly* sure, but it would come down to how you construct the DataModel object. Or, more to the point, how you specify its construction in the DI config.
For example:
$model = new DataModel(array(
"Member" => "DataList('Member', array('database' => 'shared_auth_db')"),
"Group" => "DataList('Group', array('database' => 'shared_auth_db')"),
"Permission" => "DataList('Permission', array('database' => 'shared_auth_db')"),
));
It's an open question as to whether the arguments of this array should be a kind of parameter list or object construction strings.
For example, you could do this instead, which is simpler but less flexible.
$model = new DataModel(array(
"Member" => array('database' => 'shared_auth_db'),
"Group" => array('database' => 'shared_auth_db'),
"Permission" => array('database' => 'shared_auth_db'),
));
But it does open the door for a YAML config like this:
DataModel :
Member:
database: shared_auth_db
Group:
database: shared_auth_db
Permission:
database: shared_auth_db