Sam Minnée, Chief Executive Officer and co-founder of SilverStripe, has shaped the SilverStripe Suite and is part of its success story as an internationally respected Open Source CMS.
One of the parts of SilverStripe 3 that I was most heavily involved with was the development of the new ORM. ORM stands for “Object-relational mapper” and it’s the part of the system that turns your DataObject::get() calls into SQL queries, and constructs relevant DataObjects with the results. In other words, it maps our PHP objects to a relational database for storage.
The biggest change we’ve made to the ORM in SilverStripe 3 is how it fetches sets of records. In SilverStripe 2, if you wanted to query some fields you would call this:
$pages = DataObject::get(‘SiteTree’, ‘“ParentID” = 5’);
The query would be executed straight away. On the face of it, this might not be such a problem, and for simple cases it works okay.
But what about if I just want to get the number of records that match that query? Maybe I would call this:
$pages = DataObject::get(‘SiteTree’, ‘“ParentID” = 5’); $count = $pages ? $pages->Count() : 0;
However, in SilverStripe 2 what that would do is query every single matching record from the database, create a DataObject for them, get the size of, and then throw all of those objects away. This is very inefficient.
As a result, a more common way to get the number of records was to run something like this:
$count = DB::query(‘SELECT COUNT(*) FROM “SiteTree” WHERE
“ParentID” = 5’)->value();
This is more efficient, but it bypasses the ORM and is really just an admission that the ORM isn’t giving us what we need.
In SilverStripe 3, a DataObject::get() call won’t query the database immediately. Instead, it will create an internal representation of that ORM query and save it for later. There is a new class for storing these, called DataList. It will only call the query once a result is needed. For example:
// Query isn’t executed here $pages = DataObject::get(‘SiteTree’, ‘“ParentID” = 5’); // Query is executed here foreach($pages as $page) echo “<li>$page->Title</li>”;
As part of these changes, we have made a new API better indicate that you are creating an option that represents the query, rather than querying straight away. The old syntax still works:
DataObject::get(‘SiteTree’, ‘“ParentID” = 5’);
But, going forward, we recommend this new syntax:
DataList::create(‘SiteTree’)->where(‘“ParentID” = 5’);
Another advantage of this syntax is that you don’t need to remember the order of all the DataObject::get() arguments.
What’s more, when you call the Count() method, it won’t call the full query at all. Instead it will create a suitable “SELECT COUNT(*) …” query based on the original query. As a result, this code is now much more efficient:
$count = DataList::create(“SiteTree”)->where(‘“ParentID” = 5’)->Count();
So, efficiency is a benefit, but the new ORM also lets us make our code more loosely coupled and easier to maintain. We can pass DataLists to other parts of the system, without needing to explain how that DataList has been created. For example, ComplexTableField has a large number of configuration fields for specifying the data that should be displayed. In SilverStripe 3, we are replacing ComplexTableField with GridField, which takes one parameter for specifying data: a DataList. GridField doesn’t need to know the query behind that DataList. Instead, it can just call limit(), sort(), and filter() to limit the query to the appropriate page of results.
There’s more to the new ORM than what I can cover in a single blog post. You can find out more on the doc site. If you would like to try this out right now, you can download SilverStripe 3.0.0-alpha1.
useful blog. Thank you sam for posting it.
Posted by mike, 1 year ago @carribean
In the past I've been using the dataobjectManager plugin to input has_one has_many etc data in CMS. I'm just wondering how to manage the data within the CMS in version 3
Posted by Jon, 1 year ago
I totally agree the new ORM also lets us make our code more loosely coupled and easier to maintain. Thank you for the post, Jason!
Posted by Morgan Homes, 2 years ago
The new ORM is certainly superior than the previous ways. I can't way to check out the stuff!
Posted by Trish Homes, 2 years ago @anitttta123yahoocom
Hi Jason,
Thanks for the feedback about the method name. We're trying not to change the API too much post-alpha but it's not set in stone. silverstripe-dev@groups.google.com is the place where we discuss this kind of thing, feel free to chime in there!
Thanks,
Sam
Posted by Sam, 2 years ago
Hrmmm, don't like the "create", replacing "get"... I understand it's creating a datalist but... :(
Posted by Jason, 2 years ago
Hi Sam,
our whole firm is looking forward to work with SS3. As our web applications deal with large amounts of data these performance advantages of the new ORM are very promising.
Thanks for sharing the results of your hard work with us!
Posted by Roland Lehmann, 2 years ago
Sounds great. I always forget the order of those DataObject::get() arguments!
Posted by Jono, 2 years ago
The new ORM of SS3 is definitely a more elegent way to solve Dataobject looping with improved proformance!
Thumb up guys!
Posted by alex, 2 years ago
Thanks for the post. Was already wondering where that DataList would fit in.
Posted by Stijn De Lathouwer, 2 years ago @dendeffe
RSS feed for comments on this page | RSS feed for all comments
Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com
Comments on this website? Please give feedback.