Fixed usage of DataList etc in docs (fixes #7518)

This commit is contained in:
Ingo Schommer 2012-06-23 00:32:43 +02:00
parent cb145a0094
commit 868d3697fd
28 changed files with 249 additions and 262 deletions

View File

@ -193,6 +193,15 @@ The abstract `RelationList` class and its implementations `ManyManyList` and `Ha
are replacing the `ComponentSet` API, which is only relevant if you have instanciated these manually.
Relations are retrieved through the same way (e.g. `$myMember->Groups()`).
### New ORM: DataObjectSet->groupBy() changed to GroupedList decorator
:::php
$members = Member::get();
// before
$grouped = $members->groupBy('Surname');
// after
$grouped = GroupedList::create($members)->groupBy('Surname');
### Aggregate changes for partial caching in templates ###
`DataObject::Aggregate()` and `DataObject::RelationshipAggregate()` are now deprecated. To replace your deprecated aggregate calls

View File

@ -184,9 +184,7 @@ Sample implementation of a custom loader. Assumes a CSV-file in a certain format
$obj->LastName = $parts[1];
}
public static function getTeamByTitle(&$obj, $val, $record) {
$SQL_val = Convert::raw2sql($val);
return DataObject::get_one(
'FootballTeam', "Title = '{$SQL_val}'"
return FootballTeam::get()->filter('Title', $val)->First();
);
}
}

View File

@ -115,7 +115,7 @@ Add the following code to a new file `zzz_admin/code/BookmarkedLeftAndMainExtens
<?php
class BookmarkedPagesLeftAndMainExtension extends LeftAndMainExtension {
public function BookmarkedPages() {
return DataList::create('Page')->where('"IsBookmarked" = 1');
return Page::get()->filter("IsBookmarked", 1);
}
}

View File

@ -1,15 +1,22 @@
# Grouping Data Object Sets
# Grouping lists of records
The [api:DataObjectSet] class has a number of methods useful for grouping objects by fields. Together with sorting this
can be used to break up long lists of data into more manageable sub-sections.
The [api:SS_List] class is designed to return a flat list of records.
These lists can get quite long, and hard to present on a single list.
[Pagination](/howto/pagination) is one way to solve this problem,
by splitting up the list into multiple pages.
The [api:DataObjectSet->groupBy()] method takes a field name as the single argument, and breaks the set up into a number
of arrays, where each array contains only objects with the same value of that field. The [api:DataObjectSet->GroupedBy()]
method builds on this and returns the same data in a template-friendly format.
In this howto, we present an alternative to pagination:
Grouping a list by various criteria, through the `[api:GroupedList]` class.
This class is a `[api:SS_ListDecorator]`, which means it wraps around a list,
adding new functionality.
It provides a `groupBy()` method, which takes a field name, and breaks up the managed list
into a number of arrays, where each array contains only objects with the same value of that field.
Similarly, the `GroupedBy()` method builds on this and returns the same data in a template-friendly format.
## Grouping Sets By First Letter
This example deals with breaking up a [api:DataObjectSet] into sub-headings by the first letter.
This example deals with breaking up a [api:SS_List] into sub-headings by the first letter.
Let's say you have a set of Module objects, each representing a SilverStripe module, and you want to output a list of
these in alphabetical order, with each letter as a heading; something like the following list:
@ -23,31 +30,27 @@ these in alphabetical order, with each letter as a heading; something like the f
* Database Plumber
* ...
The first step is to set up the basic data model, along with a method that returns the first letter of the title. This
The first step is to set up the basic data model,
along with a method that returns the first letter of the title. This
will be used both for grouping and for the title in the template.
:::php
class Module extends DataObject {
public static $db = array(
'Title' => 'Varchar(255)'
'Title' => 'Text'
);
// ...
/**
* Returns the first letter of the module title, used for grouping.
*
* @return string
*/
public function getTitleFirstLetter() {
return $this->Title[0];
}
}
The next step is to create a method or variable that will contain/return all the Module objects, sorted by title. For
this example this will be a method on the Page class.
The next step is to create a method or variable that will contain/return all the objects,
sorted by title. For this example this will be a method on the `Page` class.
:::php
class Page extends SiteTree {
@ -56,23 +59,22 @@ this example this will be a method on the Page class.
/**
* Returns all modules, sorted by their title.
*
* @return DataObjectSet
* @return GroupedList
*/
public function getModules() {
return DataObject::get('Module', null, '"Title"');
public function getGroupedModules() {
return GroupedList::create(Module::get()->sort('Title'));
}
}
The final step is to render this into a template. The [api:DataObjectSet->GroupedBy()] method breaks up the set into
a number of sets, grouped by the field that is passed as the parameter. In this case, the getTitleFirstLetter method
defined earlier is used to break them up.
The final step is to render this into a template. The `GroupedBy()` method breaks up the set into
a number of sets, grouped by the field that is passed as the parameter.
In this case, the `getTitleFirstLetter()` method defined earlier is used to break them up.
:::ss
// Modules list grouped by TitleFirstLetter
<%-- Modules list grouped by TitleFirstLetter --%>
<h2>Modules</h2>
<% control Modules.GroupedBy(TitleFirstLetter) %>
<% control GroupedModules.GroupedBy(TitleFirstLetter) %>
<h3>$TitleFirstLetter</h3>
<ul>
<% control Children %>
@ -83,61 +85,63 @@ defined earlier is used to break them up.
## Grouping Sets By Month
Grouping a set by month is a very similar process. The only difference would be to sort the records by month name, and
then create a method on the DataObject that returns the month name, and pass that to the [api:DataObjectSet->GroupedBy()]
call.
Grouping a set by month is a very similar process.
The only difference would be to sort the records by month name, and
then create a method on the DataObject that returns the month name,
and pass that to the [api:GroupedList->GroupedBy()] call.
Again, the first step is to create a method on the class in question that will be displayed in a list. For this example,
a [api:DataObject] called NewsItem will be used. This will have a method which returns the month it was posted in:
We're reusing our example `Module` object,
but grouping by its built-in `Created` property instead,
which is automatically set when the record is first written to the database.
This will have a method which returns the month it was posted in:
:::php
class NewsItem extends DataObject {
public static $db = array(
'Title' => 'Varchar(255)',
'Date' => 'Date'
);
class Module extends DataObject {
// ...
/**
* Returns the month name this news item was posted in.
*
* @return string
*/
public function getMonthPosted() {
return date('F', strtotime($this->Date));
public function getMonthCreated() {
return date('F', strtotime($this->Created));
}
}
The next step is to create a method that will return all the News records that exist, sorted by month name from
January to December. This can be accomplshed by sorting by the Date field:
The next step is to create a method that will return all records that exist,
sorted by month name from January to December. This can be accomplshed by sorting by the `Created` field:
:::php
class Page extends SiteTree {
// ...
/**
* Returns all news items, sorted by the month they were posted
*
* @return DataObjectSet
* @return GroupedList
*/
public function getNewsItems() {
return DataObject::get('NewsItem', null, '"Date"');
public function getGroupedModulesByDate() {
return GroupedList::create(Module::get()->sort('Created'));
}
}
The final step is the render this into the template using the [api:DataObjectSet->GroupedBy()] method.
The final step is the render this into the template using the [api:GroupedList->GroupedBy()] method.
:::ss
// Modules list grouped by the Month Posted
<h2>Modules</h2>
<% control NewsItems.GroupedBy(MonthPosted) %>
<h3>$MonthPosted</h3>
<% control GroupedModulesByDate.GroupedBy(MonthCreated) %>
<h3>$MonthCreated</h3>
<ul>
<% control Children %>
<li>$Title ($Date.Nice)</li>
<li>$Title ($Created.Nice)</li>
<% end_control %>
</ul>
<% end_control %>
<% end_control %>
## Related
* [Howto: "Pagination"](/howto/pagination)

View File

@ -8,7 +8,7 @@ the language and functions which are used in the guides.
* [Import CSV Data](csv-import). Build a simple CSV importer using either [api:ModelAdmin] or a custom controller
* [Dynamic Default Fields](dynamic-default-fields). Pre populate a [api:DataObject] with data.
* [Grouping DataObjectSets](grouping-dataobjectsets). Group results in a [api:DataObjectSet] to create sub sections.
* [Grouping Lists](grouping-dataobjectsets). Group results in a [api:SS_List] to create sub sections.
* [PHPUnit Configuration](phpunit-configuration). How to setup your testing environment with PHPUnit
* [Extend the CMS Interface](extend-cms-interface).
* [How to customize CMS Tree](customize-cms-tree).

View File

@ -1,11 +1,11 @@
# Paginating A List
Adding pagination to a `[api:DataList]` or `[DataObjectSet]` is quite simple. All
Adding pagination to a `[api:SS_List]` is quite simple. All
you need to do is wrap the object in a `[api:PaginatedList]` decorator, which takes
care of fetching a sub-set of the total list and presenting it to the template.
In order to create a paginated list, you can create a method on your controller
that first creates a `DataList` that will return all pages, and then wraps it
that first creates a `SS_List` that will return all pages, and then wraps it
in a `[api:PaginatedList]` object. The `PaginatedList` object is also passed the
HTTP request object so it can read the current page information from the
"?start=" GET var.
@ -18,8 +18,7 @@ information.
* Returns a paginated list of all pages in the site.
*/
public function PaginatedPages() {
$pages = DataList::create('Page');
return new PaginatedList($pages, $this->request);
return new PaginatedList(Page::get(), $this->request);
}
## Setting Up The Template
@ -72,3 +71,7 @@ list will already contain only the items that you wish to display on the current
page. In this situation the automatic limiting done by `[api:PaginatedList]`
will break the pagination. You can disable automatic limiting using the
`[api:PaginatedList->setLimitItems()]` method when using custom lists.
## Related
* [Howto: "Grouping Lists"](/howto/grouping-dataobjectsets)

View File

@ -403,7 +403,7 @@ Example:
* This method returns something cool. {@link MyParentMethod} has other cool stuff in it.
*
* @param string $colour The colour of cool things that you want
* @return DataObjectSet A list of everything cool
* @return DataList A list of everything cool
*/
public function myMethod($foo) {}
@ -429,7 +429,7 @@ If you have to use raw SQL, make sure your code works across databases make sure
with the column or table name escaped with double quotes and values with single quotes.
:::php
DataObject::get("MyClass", "\"Title\" = 'my title'");
MyClass::get()->where("\"Title\" = 'my title'");
Use [ANSI SQL](http://en.wikipedia.org/wiki/SQL#Standardization) format where possible.

View File

@ -2,53 +2,67 @@
## Introduction
A single database record & abstract class for the data-access-model.
The `[api:DataObject]` class represents a single row in a database table,
following the ["Active Record"](http://en.wikipedia.org/wiki/Active_record_pattern) design pattern.
## Usage
## Defining Properties
* [datamodel](/topics/datamodel): The basic pricinples
* [data-types](/topics/data-types): Casting and special property-parsing
* `[api:DataObject]`: A "container" for DataObjects
Properties defined through `DataObject::$db` map to table columns,
and can be declared as different [data-types](/topics/data-types).
## Basics
## Loading and Saving Records
The call to `DataObject->getCMSFields()` is the centerpiece of every data administration interface in SilverStripe,
which returns a `[api:FieldList]`''.
The basic principles around data persistence and querying for objects
is explained in the ["datamodel" topic](/topics/datamodel).
## Defining Form Fields
In addition to defining how data is persisted, the class can also
help with editing it by providing form fields through `DataObject->getCMSFields()`.
The resulting `[api:FieldList]` is the centrepiece of many data administration interfaces in SilverStripe.
Many customizations of the SilverStripe CMS interface start here,
by adding, removing or configuring fields.
Example getCMSFields implementation
:::php
class MyPage extends Page {
class MyDataObject extends DataObject {
$db = array(
'IsActive' => 'Boolean'
);
public function getCMSFields() {
return new FieldSet(
new CheckboxField('IsActive')
);
}
}
There's various [form field types](/references/form-field-types), for editing text, dates,
restricting input to numbers, and much more.
## Scaffolding Form Fields
The ORM already has a lot of information about the data represented by a `DataObject`
through its `$db` property, so why not use it to create form fields as well?
If you call the parent implementation, the class will use `[api:FormScaffolder]`
to provide reasonable defaults based on the property type (e.g. a checkbox field for booleans).
You can then further customize those fields as required.
:::php
class MyDataObject extends DataObject {
// ...
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Content',new CheckboxField('CustomProperty'));
$fields->fieldByName('IsActive')->setTitle('Is active?');
return $fields;
}
}
The `[ModelAdmin](/reference/modeladmin)` class uses this approach to provide
data management interfaces with very little custom coding.
## Scaffolding Formfields
These calls retrieve a `[api:FieldList]` for the area where you intend to work with the scaffolded form.
### For the CMS
:::php
$fields = singleton('MyDataObject')->getCMSFields();
### For the Frontend
Used for simple frontend forms without relation editing or `[api:TabSet] behaviour. Uses `scaffoldFormFields()` by
default. To customize, either overload this method in your subclass, or extend it by `DataExtension->updateFormFields()`.
:::php
$fields = singleton('MyDataObject')->getFrontEndFields();
## Customizing Scaffolded Fields
This section covers how to enhance the default scaffolded form fields from above. It is particularly useful when used
in conjunction with the `[api:ModelAdmin]` in the CMS to make relevant data administration interfaces.
You can also alter the fields of built-in and module `DataObject` classes through
your own `[DataExtension](/reference/dataextension)`, and a call to `[api:DataExtension->updateCMSFields()]`.
### Searchable Fields

View File

@ -1,98 +0,0 @@
# DataObjectSet
## Introduction
This class represents a set of `[api:DataObject]`s, such as the results of a query. It is the base for all
[datamodel](/topics/datamodel)-related querying. It implements the [Iterator
interface](http://php.net/manual/en/language.oop5.iterations.php) introduced in PHP5.
Relations (`has_many`/`many_many`) are described in `[api:ComponentSet]`, a subclass of `[api:DataObjectSet]`.
## Usage
### Getting the size
:::php
$mySet->Count();
### Getting an single element
:::php
$myFirstDataObject = $mySet->First();
$myLastDataObject = $mySet->Last();
### Getting multiple elements
:::php
$mySpecialDataObjects = $mySet->find('Status', 'special');
$startingFromTen = $mySet->getOffset(10);
$tenToTwenty = $mySet->getRange(10, 10);
### Getting one property
:::php
$myIDArray = $mySet->column('ID');
### Grouping
You can group a set by a specific column. Consider using `[api:SQLQuery]` with a *GROUP BY* statement for enhanced
performance.
:::php
$groupedSet = $mySet->groupBy('Lastname');
### Sorting
Sort a set by a specific column.
:::php
$mySet->sort('Lastname'); //ascending
$mySet->sort('Lastname', 'DESC'); //descending
This works on the object itself, so do NOT do something like this:
:::php
$sortedSet = $mySet->sort('Lastname'); //ascending
## Merge with other `[api:DataObjectSet]`s
:::php
$myFirstSet->merge($mySecondSet);
// $myFirstSet now contains all combined values
### Mapping for Dropdowns
When using `[api:DropdownField]` and its numerous subclasses to select a value from a set, you can easily map
the records to a compatible array:
:::php
$map = $mySet->toDropDownMap('ID', 'Title');
$dropdownField = new DropdownField('myField', 'my label', $map);
### Converting to array
:::php
$myArray = $mySet->toArray();
### Checking for existence
It is good practice to check for empty sets before doing any iteration.
:::php
$mySet = DataObject::get('Players');
if($mySet->exists()) foreach($mySet as $player)
### Paging
`[api:DataObject]`s have native support for dealing with **pagination**.
See *setPageLimits*, *setPageLength*, etc.
FIXME Complete pagination documentation
## API Documentation
`[api:DataObjectSet]`

View File

@ -48,17 +48,14 @@ mod_rewrite works.
## main.php
All requests go through main.php, which sets up the environment and then hands control over to Director.
All requests go through `main.`php, which sets up the environment and then hands control over to `Director`.
**See:** The API documentation of `[api:Main]` for information about how main.php processes requests.
## Director and URL patterns
main.php relies on `[api:Director]` to work out which controller should handle this request. `[api:Director]` will instantiate that
controller object and then call `[api:Controller::run()]`.
**See:** The API documentation of `[api:Director]` for information about how Director parses URLs and hands control over to a controller object.
In general, the URL is build up as follows: page/action/ID/otherID - e.g. http://www.mysite.com/mypage/addToCart/12.
In general, the URL is build up as follows: `page/action/ID/otherID` - e.g. http://www.mysite.com/mypage/addToCart/12.
This will add an object with ID 12 to the cart.
When you create a function, you can access the ID like this:
@ -67,7 +64,7 @@ When you create a function, you can access the ID like this:
public function addToCart ($request) {
$param = $r->allParams();
echo "my ID = ".$param["ID"];
$obj = DataObject::get("myProduct", $param["ID"]);
$obj = MyProduct::get()->byID($param["ID"]);
$obj->addNow();
}

View File

@ -9,7 +9,6 @@ Reference articles complement our auto-generated [API docs](http://api.silverstr
* [Database Structure](database-structure): Conventions and best practices for database tables and fields
* [DataObject](dataobject): Base class for database records
* [DataExtension](dataextension): A "mixin" system allowing to extend core classes
* [DataObjectSet](dataobjectset): The base collection of database records in the ORM
* [Director](director): Routes URLs and handles HTTP requests
* [Execution Pipeline](execution-pipeline): Detailed look on the way an HTTP request takes through the system
* [Form Field Types](form-field-types): Highlevel overview of field classes
@ -32,8 +31,4 @@ Reference articles complement our auto-generated [API docs](http://api.silverstr
* [TableListField](tablelistfield): View and delete records in the CMS
* [Typography](typography): CSS file to enable WYSIWYG previews in the CMS
* [urlvariabletools](urlvariabletools): Debug and maintenance switches
* [Versioned](versioned): Extension for SiteTree and other classes to store old versions and provide "staging"
## Feedback
If you have a topic you would like covered in these section please ask for it on our [Bug Tracker](http://open.silverstripe.org)
* [Versioned](versioned): Extension for SiteTree and other classes to store old versions and provide "staging"

View File

@ -57,7 +57,7 @@ something like this:
public function LatestUpdates() {
// 10 is the number of pages
return DataObject::get("Page", "", "LastEdited DESC", "", 10);
return Page::get()->sort("LastEdited", "DESC")->limit(10);
}
}

View File

@ -64,7 +64,7 @@ CustomSideReport.php
public function records() {
// the data the report returns all the dataobjects of type Page and sorted by title. See datamodel for more info
return DataObject::get("Page", "", "Title");
return Page::get()->sort("Title");
}
public function fieldsToShow() {

View File

@ -23,7 +23,7 @@ might consist of more than one *URLSegment*).
:::php
// wrong
$mypage = DataObject::get_one('SiteTree', '"URLSegment" = \'<mylink>\'');
$mypage = SiteTree::get()->filter("URLSegment", '<mylink>')->First();
// right
$mypage = SiteTree::get_by_link('<mylink>');
@ -114,7 +114,8 @@ it is a good starting point, for choosing your customisation.
public function canCreate() {
//here is a trick to only allow one (e.g. holder) of a page
return !DataObject::get_one($this->class);
$class = $this->class;
return !$class::get()->Count();
}
public function canDelete() {

View File

@ -32,7 +32,7 @@ publisher to generate folders and HTML-files.
$urls = array();
// memory intensive depending on number of pages
$pages = DataObject::get("SiteTree");
$pages = SiteTree::get();
foreach($pages as $page) {
$urls = array_merge($urls, (array)$page->subPagesToCache());
@ -78,7 +78,7 @@ you can also add an exclusion
:::php
public function allPagesToCache() {
$urls = array();
$pages = DataObject::get("SiteTree");
$pages = SiteTree::get();
// ignored page types
$ignored = array('UserDefinedForm');
@ -93,12 +93,12 @@ you can also add an exclusion
return $urls;
}
You can also pass the filtering to the original DataObject::get("SiteTree");
You can also pass the filtering to the original `SiteTree::get()`;
:::php
public function allPagesToCache() {
$urls = array();
$pages = DataObject::get("SiteTree", "ClassName != 'UserDefinedForm'");
$pages = SiteTree::get()->where("ClassName != 'UserDefinedForm'");
...
## Single server Caching

View File

@ -82,7 +82,7 @@ For more information on each of the features used in the example, you can read b
);
// custom DataObjectSet
$myProducts = DataObject::get('Product','Code = "MyCode"');
$myProducts = Product::get()->filter('Code', "MyCode");
$myTableListField->setCustomSourceItems($myProducts);
// custom SQL

View File

@ -54,7 +54,6 @@ incomplete - please add to it** *Try to keep it in alphabetical order too! :)*
| Security::encrypt_passwords($encrypt_passwords); | | Specify if you want store your passwords in clear text or encrypted (for more details see [security](/topics/security)) |
| Security::set_password_encryption_algorithm($algorithm, $use_salt);| | If you choose to encrypt your passwords, you can choose which algorithm is used to and if a salt should be used to increase the security level even more (for more details see [security](/topics/security)). |
| Security::setDefaultAdmin('admin','password'); | | Set default admin email and password, helpful for recovering your password |
| SSAkismet::setAPIKey(string $key) | | Enables use of the Akismet spam filter. The key must be a valid WordPress API key. |
| SSViewer::set_theme(string $themename) | | Choose the default theme for your site |
## Constants

View File

@ -1,26 +1,87 @@
# Data Types
# Data Types and Casting
These are the data-types that you can use when defining your data objects. They are all subclasses of `[api:DBField]`
for introducing their usage.
Properties on any SilverStripe object can be type casted automatically,
by transforming its scalar value into an instance of the `[api:DBField]` class,
providing additional helpers. For example, a string can be cast as
a `[api:Text]` type, which has a `FirstSentence()` method to retrieve the first
sentence in a longer piece of text.
## Types
## Available Types
* `[api:Varchar]`: A variable-length string of up to 255 characters, designed to store raw text
* `[api:Text]`: A variable-length string of up to 2 megabytes, designed to store raw text
* `[api:HTMLVarchar]`: A variable-length string of up to 255 characters, designed to store HTML
* `[api:HTMLText]`: A variable-length string of up to 2 megabytes, designed to store HTML
* `[api:Enum]`: An enumeration of a set of strings
* `[api:Boolean]`: A boolean field.
* `[api:Int]`: An integer field.
* `[api:Decimal]`: A decimal number.
* `[api:Currency]`: A number with 2 decimal points of precision, designed to store currency values.
* `[api:Percentage]`: A decimal number between 0 and 1 that represents a percentage.
* `[api:Date]`: A date field
* `[api:Decimal]`: A decimal number.
* `[api:Enum]`: An enumeration of a set of strings
* `[api:HTMLText]`: A variable-length string of up to 2 megabytes, designed to store HTML
* `[api:HTMLVarchar]`: A variable-length string of up to 255 characters, designed to store HTML
* `[api:Int]`: An integer field.
* `[api:Percentage]`: A decimal number between 0 and 1 that represents a percentage.
* `[api:SS_Datetime]`: A date / time field
* `[api:Text]`: A variable-length string of up to 2 megabytes, designed to store raw text
* `[api:Time]`: A time field
* `[api:Varchar]`: A variable-length string of up to 255 characters, designed to store raw text
## HTMLText vs. Text, and HTMLVarchar vs. Varchar
## Casting arbitrary values
On the most basic level, the class can be used as simple conversion class
from one value to another, e.g. to round a number.
:::php
DBField::create_field('Double', 1.23456)->Round(2); // results in 1.23
Of course that's much more verbose than the equivalent PHP call.
The power of `[api:DBField]` comes with its more sophisticated helpers,
like showing the time difference to the current date:
:::php
DBField::create_field('Date', '1982-01-01')->TimeDiff(); // shows "30 years ago"
## Casting ViewableData
Most objects in SilverStripe extend from `[api:ViewableData]`,
which means they know how to present themselves in a view context.
Through a `$casting` array, arbitrary properties and getters can be casted:
:::php
class MyObject extends ViewableData {
static $casting = array(
'MyDate' => 'Date'
);
function getMyDate() {
return '1982-01-01';
}
}
$obj = new MyObject;
$obj->getMyDate(); // returns string
$obj->MyDate; // returns string
$obj->obj('MyDate'); // returns object
$obj->obj('MyDate')->InPast(); // returns boolean
## Casting DataObject
The `[api:DataObject]` class uses `DBField` to describe the types of its
properties which are persisted in database columns, through the `[$db](api:DataObject::$db)` property.
In addition to type information, the `DBField` class also knows how to
define itself as a database column. See the ["datamodel" topic](/topics/datamodel#casting) for more details.
<div class="warning" markdown="1">
Since we're dealing with a loosely typed language (PHP)
as well as varying type support by the different database drivers,
type conversions between the two systems are not guaranteed to be lossless.
Please take particular care when casting booleans, null values, and on float precisions.
</div>
## Casting in templates
In templates, casting helpers are available without the need for an `obj()` call.
Example: Flagging an object of type `MyObject` (see above) if it's date is in the past.
:::ss
<% if MyObjectInstance.MyDate.InPast %>Outdated!<% end_if %>
## Casting HTML Text
The database field types `[api:HTMLVarchar]` and `[api:Varchar]` are exactly the same in the database. However, the
templating engine knows to escape the `[api:Varchar]` field and not the `[api:HTMLVarchar]` field. So, it's important you
@ -29,6 +90,7 @@ use the right field if you don't want to be putting $FieldType.XML everywhere.
If you're going to put HTML content into the field, please use the field type with the HTML prefix. Otherwise, you're
going to risk double-escaping your data, forgetting to escape your data, and generally creating a confusing situation.
## Usage
## Related
* See [datamodel](/topics/datamodel) for information about **database schemas** implementing these types
* ["datamodel" topic](/topics/datamodel)
* ["security" topic](/topics/security)

View File

@ -3,21 +3,20 @@
SilverStripe uses an [object-relational model](http://en.wikipedia.org/wiki/Object-relational_model) that assumes the
following connections:
* Each database-table maps to a php-class
* Each database-row maps to a php-object
* Each database-column maps to a property on a php-object
* Each database-table maps to a PHP class
* Each database-row maps to a PHP object
* Each database-column maps to a property on a PHP object
All data tables in SilverStripe are defined as subclasses of `[api:DataObject]`. Inheritance is supported in the data
model: seperate tables will be linked together, the data spread across these tables. The mapping and saving/loading
logic is handled by SilverStripe, you don't need to worry about writing SQL most of the time.
The advanced object-relational layer in SilverStripe is one of the main reasons for requiring PHP5. Most of its
customizations are possible through [PHP5 Object
Most of the ORM customizations are possible through [PHP5 Object
Overloading](http://www.onlamp.com/pub/a/php/2005/06/16/overloading.html) handled in the `[api:Object]`-class.
See [database-structure](/reference/database-structure) for in-depth information on the database-schema.
## Generating the database-schema
## Generating the Database Schema
The SilverStripe database-schema is generated automatically by visiting the URL.
`http://<mysite>/dev/build`
@ -28,14 +27,13 @@ Note: You need to be logged in as an administrator to perform this command.
## Querying Data
Every query to data starts with a `DataList::create($class)` or `$class::get()` call. For example, this query would return
all of the Member objects:
Every query to data starts with a `DataList::create(<class>)` or `<class>::get()` call. For example, this query would return all of the `Member` objects:
:::php
$members = Member::get();
The ORM uses a "fluent" syntax, where you specify a query by chaining together different methods. Two common methods
are filter() and sort():
are `filter()` and `sort()`:
:::php
$members = Member::get()->filter(array('FirstName' => 'Sam'))->sort('Surname');
@ -83,19 +81,18 @@ If you have constructed a query that you know should return a single record, you
Quiet often you would like to sort a list. Doing this on a list could be done in a few ways.
If would like to sort the list by FirstName in a ascending way (from A to Z).
If would like to sort the list by `FirstName` in a ascending way (from A to Z).
:::php
$member = Member::get()->sort('FirstName');
// Or the more expressive way
$member = Member::get()->sort('FirstName', 'ASC');
$member = Member::get()->sort('FirstName'); // Ascending is implied
To reverse the sort
:::php
$member = Member::get()->sort('FirstName', 'DESC');
However you might have several entries with the same FirstName and would like to sort them by FirstName and LastName
However you might have several entries with the same `FirstName` and would like to sort them by `FirstName` and `LastName`
:::php
$member = Member::get()->sort(array(
@ -395,7 +392,7 @@ Note: Alternatively you can set defaults directly in the database-schema (rather
Properties defined in *static $db* are automatically casted to their [data-types](data-types) when used in templates.
You can also cast the return-values of your custom functions (e.g. your "virtual properties").
Calling those functions directly will still return whatever type your php-code generates,
Calling those functions directly will still return whatever type your PHP code generates,
but using the *obj()*-method or accessing through a template will cast the value according to the $casting-definition.
:::php
@ -594,6 +591,9 @@ This functionality is provided by the `SS_Map` class, which can be used to build
$members = Member::get();
$map = new SS_Map($members, 'ID', 'FirstName');
Note: You can also retrieve a single property from all contained records
through `[api:SS_List->column()]`.
## Data Handling
When saving data through the object model, you don't have to manually escape strings to create SQL-safe commands.

View File

@ -166,7 +166,7 @@ Objects can be searched through an input field (partially matching one or more f
Selecting from the results will add the object to the relation.
:::php
$group = DataObject::get_one('Group');
$group = Group::get()->First();
$config = GridFieldConfig::create()->addComponent(new GridFieldAddExistingAutocompleter(array('FirstName', 'Surname', 'Email'));
$gridField = new GridField('Members', 'Members', $group->Members(), $config);

View File

@ -386,8 +386,7 @@ PHP:
:::php
class MyController {
function autocomplete($request) {
$SQL_title = Convert::raw2sql($request->getVar('title'));
$results = DataObject::get("Page", "Title = '$SQL_title'");
$results = Page::get()->filter("Title", $request->getVar('title'));
if(!$results) return new HTTPResponse("Not found", 404);
// Use HTTPResponse to pass custom status messages

View File

@ -150,7 +150,7 @@ and [tutorial:3-forms](/tutorials/3-forms).
## Updating a page:
:::php
$page = DataObject::get_one("Page", "ParentID = 18");
$page = Page::get()->filter("ParentID", 18)->First();
$page->Title = "More Serious";
$page->writeToStage('Stage');
$page->Publish('Stage', 'Live');

View File

@ -24,6 +24,7 @@ For `[api:MySQLDatabase]`, this will be `[mysql_real_escape_string()](http://de3
* DataObject::castedUpdate()
* DataObject->Property = 'val', DataObject->setField('Property','val')
* DataObject::write()
* DataList->byID()
* Form->saveInto()
* FormField->saveInto()
* DBField->saveInto()
@ -65,7 +66,7 @@ Example:
class MyForm extends Form {
public function save($RAW_data, $form) {
$SQL_data = Convert::raw2sql($RAW_data); // works recursively on an array
$objs = DataObject::get('Player', "Name = '{$SQL_data[name]}'");
$objs = Player::get()->where("Name = '{$SQL_data[name]}'");
// ...
}
}
@ -80,7 +81,7 @@ Example:
class MyController extends Controller {
public function myurlaction($RAW_urlParams) {
$SQL_urlParams = Convert::raw2sql($RAW_urlParams); // works recursively on an array
$objs = DataObject::get('Player', "Name = '{$SQL_data[OtherID]}'");
$objs = Player::get()->where("Name = '{$SQL_data[OtherID]}'");
// ...
}
}
@ -314,8 +315,8 @@ Below is an example with different ways you would use this casting technique:
// cast the 'category' GET variable as an integer
$categoryID = (int)$_GET['category'];
// perform a get_by_id, ensure the ID is an integer before querying
return DataObject::get_by_id('CaseStudy', $categoryID);
// perform a byID(), which ensures the ID is an integer before querying
return CaseStudy::get()->byID($categoryID);
}

View File

@ -30,7 +30,7 @@ but rather just the returned collection,
:::php
$myPage = $this->objFromFixture('Page', 'mypage');
$myOtherPage = $this->objFromFixture('Page', 'myotherpage');
$pages = DataObject::get('Page');
$pages = Page::get();
// Bad: Assumptions about IDs and their order
$this->assertEquals(array(1,2), $pages->column('ID'));
// Good: Uses actually created IDs, independent of their order

View File

@ -406,8 +406,8 @@ control. We can get the data for the news articles by implementing our own funct
:::php
...
public function LatestNews($num=5) {
$holder = DataObject::get_one("ArticleHolder");
return ($holder) ? DataList::create('ArticlePage')->where('"ParentID" = '.$holder->ID)->sort('Date DESC')->limit($num) : false;
$holder = ArticleHolder::get()->First();
return ($holder) ? ArticlePage::get()->filter('ParentID', $holder->ID)->sort('Date DESC')->limit($num) : false;
}
...

View File

@ -321,7 +321,7 @@ then create our graph using a page control in the template. Create the function
:::php
public function BrowserPollResults() {
$submissions = DataObject::get('BrowserPollSubmission');
$submissions = BrowserPollSubmission::get();
$total = $submissions->Count();
$doSet = new DataObjectSet();
@ -341,7 +341,7 @@ then create our graph using a page control in the template. Create the function
This introduces a few new concepts, so let's step through it.
:::php
$submissions = DataObject::get('BrowserPollSubmission');
$submissions = BrowserPollSubmission::get();
First we get all of the *BrowserPollSubmission*s from the database. This returns the submissions as a

View File

@ -703,7 +703,7 @@ it *MyProject* for instance.
...
public function MyProject() {
return DataObject::get( 'Project', "`MyStudentID` = '{$this->ID}'" );
return Project::get()->filter("MyStudentID", $this->ID);
}
}

View File

@ -10,7 +10,7 @@ class GroupedList extends SS_ListDecorator {
/**
* @param string $index
* @return ArrayList
* @return array
*/
public function groupBy($index) {
$result = array();
@ -29,8 +29,11 @@ class GroupedList extends SS_ListDecorator {
}
/**
* Similar to {@link groupBy()}, but returns
* the data in a format which is suitable for usage in templates.
*
* @param string $index
* @param string $children
* @param string $children Name of the control under which children can be iterated on
* @return ArrayList
*/
public function GroupedBy($index, $children = 'Children') {