mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Fixed usage of DataList etc in docs (fixes #7518)
This commit is contained in:
parent
cb145a0094
commit
868d3697fd
@ -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.
|
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()`).
|
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 ###
|
### Aggregate changes for partial caching in templates ###
|
||||||
|
|
||||||
`DataObject::Aggregate()` and `DataObject::RelationshipAggregate()` are now deprecated. To replace your deprecated aggregate calls
|
`DataObject::Aggregate()` and `DataObject::RelationshipAggregate()` are now deprecated. To replace your deprecated aggregate calls
|
||||||
|
@ -184,9 +184,7 @@ Sample implementation of a custom loader. Assumes a CSV-file in a certain format
|
|||||||
$obj->LastName = $parts[1];
|
$obj->LastName = $parts[1];
|
||||||
}
|
}
|
||||||
public static function getTeamByTitle(&$obj, $val, $record) {
|
public static function getTeamByTitle(&$obj, $val, $record) {
|
||||||
$SQL_val = Convert::raw2sql($val);
|
return FootballTeam::get()->filter('Title', $val)->First();
|
||||||
return DataObject::get_one(
|
|
||||||
'FootballTeam', "Title = '{$SQL_val}'"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ Add the following code to a new file `zzz_admin/code/BookmarkedLeftAndMainExtens
|
|||||||
<?php
|
<?php
|
||||||
class BookmarkedPagesLeftAndMainExtension extends LeftAndMainExtension {
|
class BookmarkedPagesLeftAndMainExtension extends LeftAndMainExtension {
|
||||||
public function BookmarkedPages() {
|
public function BookmarkedPages() {
|
||||||
return DataList::create('Page')->where('"IsBookmarked" = 1');
|
return Page::get()->filter("IsBookmarked", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
The [api:SS_List] class is designed to return a flat list of records.
|
||||||
can be used to break up long lists of data into more manageable sub-sections.
|
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
|
In this howto, we present an alternative to pagination:
|
||||||
of arrays, where each array contains only objects with the same value of that field. The [api:DataObjectSet->GroupedBy()]
|
Grouping a list by various criteria, through the `[api:GroupedList]` class.
|
||||||
method builds on this and returns the same data in a template-friendly format.
|
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
|
## 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
|
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:
|
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
|
* 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.
|
will be used both for grouping and for the title in the template.
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
class Module extends DataObject {
|
class Module extends DataObject {
|
||||||
|
|
||||||
public static $db = array(
|
public static $db = array(
|
||||||
'Title' => 'Varchar(255)'
|
'Title' => 'Text'
|
||||||
);
|
);
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the first letter of the module title, used for grouping.
|
* Returns the first letter of the module title, used for grouping.
|
||||||
*
|
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getTitleFirstLetter() {
|
public function getTitleFirstLetter() {
|
||||||
return $this->Title[0];
|
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
|
The next step is to create a method or variable that will contain/return all the objects,
|
||||||
this example this will be a method on the Page class.
|
sorted by title. For this example this will be a method on the `Page` class.
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
class Page extends SiteTree {
|
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.
|
* Returns all modules, sorted by their title.
|
||||||
*
|
* @return GroupedList
|
||||||
* @return DataObjectSet
|
|
||||||
*/
|
*/
|
||||||
public function getModules() {
|
public function getGroupedModules() {
|
||||||
return DataObject::get('Module', null, '"Title"');
|
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
|
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
|
a number of sets, grouped by the field that is passed as the parameter.
|
||||||
defined earlier is used to break them up.
|
In this case, the `getTitleFirstLetter()` method defined earlier is used to break them up.
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
// Modules list grouped by TitleFirstLetter
|
<%-- Modules list grouped by TitleFirstLetter --%>
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<% control Modules.GroupedBy(TitleFirstLetter) %>
|
<% control GroupedModules.GroupedBy(TitleFirstLetter) %>
|
||||||
<h3>$TitleFirstLetter</h3>
|
<h3>$TitleFirstLetter</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<% control Children %>
|
<% control Children %>
|
||||||
@ -83,61 +85,63 @@ defined earlier is used to break them up.
|
|||||||
|
|
||||||
## Grouping Sets By Month
|
## 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
|
Grouping a set by month is a very similar process.
|
||||||
then create a method on the DataObject that returns the month name, and pass that to the [api:DataObjectSet->GroupedBy()]
|
The only difference would be to sort the records by month name, and
|
||||||
call.
|
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,
|
We're reusing our example `Module` object,
|
||||||
a [api:DataObject] called NewsItem will be used. This will have a method which returns the month it was posted in:
|
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
|
:::php
|
||||||
class NewsItem extends DataObject {
|
class Module extends DataObject {
|
||||||
|
|
||||||
public static $db = array(
|
|
||||||
'Title' => 'Varchar(255)',
|
|
||||||
'Date' => 'Date'
|
|
||||||
);
|
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the month name this news item was posted in.
|
* Returns the month name this news item was posted in.
|
||||||
*
|
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getMonthPosted() {
|
public function getMonthCreated() {
|
||||||
return date('F', strtotime($this->Date));
|
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
|
The next step is to create a method that will return all records that exist,
|
||||||
January to December. This can be accomplshed by sorting by the Date field:
|
sorted by month name from January to December. This can be accomplshed by sorting by the `Created` field:
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
class Page extends SiteTree {
|
class Page extends SiteTree {
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all news items, sorted by the month they were posted
|
* Returns all news items, sorted by the month they were posted
|
||||||
*
|
* @return GroupedList
|
||||||
* @return DataObjectSet
|
|
||||||
*/
|
*/
|
||||||
public function getNewsItems() {
|
public function getGroupedModulesByDate() {
|
||||||
return DataObject::get('NewsItem', null, '"Date"');
|
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
|
:::ss
|
||||||
// Modules list grouped by the Month Posted
|
// Modules list grouped by the Month Posted
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<% control NewsItems.GroupedBy(MonthPosted) %>
|
<% control GroupedModulesByDate.GroupedBy(MonthCreated) %>
|
||||||
<h3>$MonthPosted</h3>
|
<h3>$MonthCreated</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<% control Children %>
|
<% control Children %>
|
||||||
<li>$Title ($Date.Nice)</li>
|
<li>$Title ($Created.Nice)</li>
|
||||||
<% end_control %>
|
<% end_control %>
|
||||||
</ul>
|
</ul>
|
||||||
<% end_control %>
|
<% end_control %>
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
* [Howto: "Pagination"](/howto/pagination)
|
@ -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
|
* [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.
|
* [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
|
* [PHPUnit Configuration](phpunit-configuration). How to setup your testing environment with PHPUnit
|
||||||
* [Extend the CMS Interface](extend-cms-interface).
|
* [Extend the CMS Interface](extend-cms-interface).
|
||||||
* [How to customize CMS Tree](customize-cms-tree).
|
* [How to customize CMS Tree](customize-cms-tree).
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# Paginating A List
|
# 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
|
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.
|
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
|
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
|
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
|
HTTP request object so it can read the current page information from the
|
||||||
"?start=" GET var.
|
"?start=" GET var.
|
||||||
@ -18,8 +18,7 @@ information.
|
|||||||
* Returns a paginated list of all pages in the site.
|
* Returns a paginated list of all pages in the site.
|
||||||
*/
|
*/
|
||||||
public function PaginatedPages() {
|
public function PaginatedPages() {
|
||||||
$pages = DataList::create('Page');
|
return new PaginatedList(Page::get(), $this->request);
|
||||||
return new PaginatedList($pages, $this->request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
## Setting Up The Template
|
## 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]`
|
page. In this situation the automatic limiting done by `[api:PaginatedList]`
|
||||||
will break the pagination. You can disable automatic limiting using the
|
will break the pagination. You can disable automatic limiting using the
|
||||||
`[api:PaginatedList->setLimitItems()]` method when using custom lists.
|
`[api:PaginatedList->setLimitItems()]` method when using custom lists.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
* [Howto: "Grouping Lists"](/howto/grouping-dataobjectsets)
|
@ -403,7 +403,7 @@ Example:
|
|||||||
* This method returns something cool. {@link MyParentMethod} has other cool stuff in it.
|
* This method returns something cool. {@link MyParentMethod} has other cool stuff in it.
|
||||||
*
|
*
|
||||||
* @param string $colour The colour of cool things that you want
|
* @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) {}
|
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.
|
with the column or table name escaped with double quotes and values with single quotes.
|
||||||
|
|
||||||
:::php
|
:::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.
|
Use [ANSI SQL](http://en.wikipedia.org/wiki/SQL#Standardization) format where possible.
|
||||||
|
|
||||||
|
@ -2,53 +2,67 @@
|
|||||||
|
|
||||||
## Introduction
|
## 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
|
Properties defined through `DataObject::$db` map to table columns,
|
||||||
* [data-types](/topics/data-types): Casting and special property-parsing
|
and can be declared as different [data-types](/topics/data-types).
|
||||||
* `[api:DataObject]`: A "container" for DataObjects
|
|
||||||
|
|
||||||
## Basics
|
## Loading and Saving Records
|
||||||
|
|
||||||
The call to `DataObject->getCMSFields()` is the centerpiece of every data administration interface in SilverStripe,
|
The basic principles around data persistence and querying for objects
|
||||||
which returns a `[api:FieldList]`''.
|
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
|
:::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() {
|
public function getCMSFields() {
|
||||||
$fields = parent::getCMSFields();
|
$fields = parent::getCMSFields();
|
||||||
$fields->addFieldToTab('Root.Content',new CheckboxField('CustomProperty'));
|
$fields->fieldByName('IsActive')->setTitle('Is active?');
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
The `[ModelAdmin](/reference/modeladmin)` class uses this approach to provide
|
||||||
|
data management interfaces with very little custom coding.
|
||||||
|
|
||||||
## Scaffolding Formfields
|
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()]`.
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
### Searchable Fields
|
### Searchable Fields
|
||||||
|
|
||||||
|
@ -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]`
|
|
@ -48,17 +48,14 @@ mod_rewrite works.
|
|||||||
|
|
||||||
## main.php
|
## 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
|
## Director and URL patterns
|
||||||
|
|
||||||
main.php relies on `[api:Director]` to work out which controller should handle this request. `[api:Director]` will instantiate that
|
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()]`.
|
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.
|
This will add an object with ID 12 to the cart.
|
||||||
|
|
||||||
When you create a function, you can access the ID like this:
|
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) {
|
public function addToCart ($request) {
|
||||||
$param = $r->allParams();
|
$param = $r->allParams();
|
||||||
echo "my ID = ".$param["ID"];
|
echo "my ID = ".$param["ID"];
|
||||||
$obj = DataObject::get("myProduct", $param["ID"]);
|
$obj = MyProduct::get()->byID($param["ID"]);
|
||||||
$obj->addNow();
|
$obj->addNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
* [Database Structure](database-structure): Conventions and best practices for database tables and fields
|
||||||
* [DataObject](dataobject): Base class for database records
|
* [DataObject](dataobject): Base class for database records
|
||||||
* [DataExtension](dataextension): A "mixin" system allowing to extend core classes
|
* [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
|
* [Director](director): Routes URLs and handles HTTP requests
|
||||||
* [Execution Pipeline](execution-pipeline): Detailed look on the way an HTTP request takes through the system
|
* [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
|
* [Form Field Types](form-field-types): Highlevel overview of field classes
|
||||||
@ -33,7 +32,3 @@ Reference articles complement our auto-generated [API docs](http://api.silverstr
|
|||||||
* [Typography](typography): CSS file to enable WYSIWYG previews in the CMS
|
* [Typography](typography): CSS file to enable WYSIWYG previews in the CMS
|
||||||
* [urlvariabletools](urlvariabletools): Debug and maintenance switches
|
* [urlvariabletools](urlvariabletools): Debug and maintenance switches
|
||||||
* [Versioned](versioned): Extension for SiteTree and other classes to store old versions and provide "staging"
|
* [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)
|
|
@ -57,7 +57,7 @@ something like this:
|
|||||||
|
|
||||||
public function LatestUpdates() {
|
public function LatestUpdates() {
|
||||||
// 10 is the number of pages
|
// 10 is the number of pages
|
||||||
return DataObject::get("Page", "", "LastEdited DESC", "", 10);
|
return Page::get()->sort("LastEdited", "DESC")->limit(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ CustomSideReport.php
|
|||||||
|
|
||||||
public function records() {
|
public function records() {
|
||||||
// the data the report returns all the dataobjects of type Page and sorted by title. See datamodel for more info
|
// 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() {
|
public function fieldsToShow() {
|
||||||
|
@ -23,7 +23,7 @@ might consist of more than one *URLSegment*).
|
|||||||
|
|
||||||
:::php
|
:::php
|
||||||
// wrong
|
// wrong
|
||||||
$mypage = DataObject::get_one('SiteTree', '"URLSegment" = \'<mylink>\'');
|
$mypage = SiteTree::get()->filter("URLSegment", '<mylink>')->First();
|
||||||
// right
|
// right
|
||||||
$mypage = SiteTree::get_by_link('<mylink>');
|
$mypage = SiteTree::get_by_link('<mylink>');
|
||||||
|
|
||||||
@ -114,7 +114,8 @@ it is a good starting point, for choosing your customisation.
|
|||||||
|
|
||||||
public function canCreate() {
|
public function canCreate() {
|
||||||
//here is a trick to only allow one (e.g. holder) of a page
|
//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() {
|
public function canDelete() {
|
||||||
|
@ -32,7 +32,7 @@ publisher to generate folders and HTML-files.
|
|||||||
$urls = array();
|
$urls = array();
|
||||||
|
|
||||||
// memory intensive depending on number of pages
|
// memory intensive depending on number of pages
|
||||||
$pages = DataObject::get("SiteTree");
|
$pages = SiteTree::get();
|
||||||
|
|
||||||
foreach($pages as $page) {
|
foreach($pages as $page) {
|
||||||
$urls = array_merge($urls, (array)$page->subPagesToCache());
|
$urls = array_merge($urls, (array)$page->subPagesToCache());
|
||||||
@ -78,7 +78,7 @@ you can also add an exclusion
|
|||||||
:::php
|
:::php
|
||||||
public function allPagesToCache() {
|
public function allPagesToCache() {
|
||||||
$urls = array();
|
$urls = array();
|
||||||
$pages = DataObject::get("SiteTree");
|
$pages = SiteTree::get();
|
||||||
|
|
||||||
// ignored page types
|
// ignored page types
|
||||||
$ignored = array('UserDefinedForm');
|
$ignored = array('UserDefinedForm');
|
||||||
@ -93,12 +93,12 @@ you can also add an exclusion
|
|||||||
return $urls;
|
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
|
:::php
|
||||||
public function allPagesToCache() {
|
public function allPagesToCache() {
|
||||||
$urls = array();
|
$urls = array();
|
||||||
$pages = DataObject::get("SiteTree", "ClassName != 'UserDefinedForm'");
|
$pages = SiteTree::get()->where("ClassName != 'UserDefinedForm'");
|
||||||
...
|
...
|
||||||
|
|
||||||
## Single server Caching
|
## Single server Caching
|
||||||
|
@ -82,7 +82,7 @@ For more information on each of the features used in the example, you can read b
|
|||||||
);
|
);
|
||||||
|
|
||||||
// custom DataObjectSet
|
// custom DataObjectSet
|
||||||
$myProducts = DataObject::get('Product','Code = "MyCode"');
|
$myProducts = Product::get()->filter('Code', "MyCode");
|
||||||
$myTableListField->setCustomSourceItems($myProducts);
|
$myTableListField->setCustomSourceItems($myProducts);
|
||||||
|
|
||||||
// custom SQL
|
// custom SQL
|
||||||
|
@ -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::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::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 |
|
| 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 |
|
| SSViewer::set_theme(string $themename) | | Choose the default theme for your site |
|
||||||
|
|
||||||
## Constants
|
## Constants
|
||||||
|
@ -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]`
|
Properties on any SilverStripe object can be type casted automatically,
|
||||||
for introducing their usage.
|
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.
|
||||||
|
|
||||||
|
## Available Types
|
||||||
|
|
||||||
## 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: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: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: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: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: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
|
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
|
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
|
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.
|
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)
|
@ -3,21 +3,20 @@
|
|||||||
SilverStripe uses an [object-relational model](http://en.wikipedia.org/wiki/Object-relational_model) that assumes the
|
SilverStripe uses an [object-relational model](http://en.wikipedia.org/wiki/Object-relational_model) that assumes the
|
||||||
following connections:
|
following connections:
|
||||||
|
|
||||||
* Each database-table maps to a php-class
|
* Each database-table maps to a PHP class
|
||||||
* Each database-row maps to a php-object
|
* Each database-row maps to a PHP object
|
||||||
* Each database-column maps to a property on 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
|
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
|
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.
|
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
|
Most of the ORM customizations are possible through [PHP5 Object
|
||||||
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.
|
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.
|
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.
|
The SilverStripe database-schema is generated automatically by visiting the URL.
|
||||||
`http://<mysite>/dev/build`
|
`http://<mysite>/dev/build`
|
||||||
@ -28,14 +27,13 @@ Note: You need to be logged in as an administrator to perform this command.
|
|||||||
|
|
||||||
## Querying Data
|
## Querying Data
|
||||||
|
|
||||||
Every query to data starts with a `DataList::create($class)` or `$class::get()` call. For example, this query would return
|
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:
|
||||||
all of the Member objects:
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
$members = Member::get();
|
$members = Member::get();
|
||||||
|
|
||||||
The ORM uses a "fluent" syntax, where you specify a query by chaining together different methods. Two common methods
|
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
|
:::php
|
||||||
$members = Member::get()->filter(array('FirstName' => 'Sam'))->sort('Surname');
|
$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.
|
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
|
:::php
|
||||||
$member = Member::get()->sort('FirstName');
|
|
||||||
// Or the more expressive way
|
|
||||||
$member = Member::get()->sort('FirstName', 'ASC');
|
$member = Member::get()->sort('FirstName', 'ASC');
|
||||||
|
$member = Member::get()->sort('FirstName'); // Ascending is implied
|
||||||
|
|
||||||
To reverse the sort
|
To reverse the sort
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
$member = Member::get()->sort('FirstName', 'DESC');
|
$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
|
:::php
|
||||||
$member = Member::get()->sort(array(
|
$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.
|
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").
|
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.
|
but using the *obj()*-method or accessing through a template will cast the value according to the $casting-definition.
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
@ -594,6 +591,9 @@ This functionality is provided by the `SS_Map` class, which can be used to build
|
|||||||
$members = Member::get();
|
$members = Member::get();
|
||||||
$map = new SS_Map($members, 'ID', 'FirstName');
|
$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
|
## Data Handling
|
||||||
|
|
||||||
When saving data through the object model, you don't have to manually escape strings to create SQL-safe commands.
|
When saving data through the object model, you don't have to manually escape strings to create SQL-safe commands.
|
||||||
|
@ -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.
|
Selecting from the results will add the object to the relation.
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
$group = DataObject::get_one('Group');
|
$group = Group::get()->First();
|
||||||
$config = GridFieldConfig::create()->addComponent(new GridFieldAddExistingAutocompleter(array('FirstName', 'Surname', 'Email'));
|
$config = GridFieldConfig::create()->addComponent(new GridFieldAddExistingAutocompleter(array('FirstName', 'Surname', 'Email'));
|
||||||
$gridField = new GridField('Members', 'Members', $group->Members(), $config);
|
$gridField = new GridField('Members', 'Members', $group->Members(), $config);
|
||||||
|
|
||||||
|
@ -386,8 +386,7 @@ PHP:
|
|||||||
:::php
|
:::php
|
||||||
class MyController {
|
class MyController {
|
||||||
function autocomplete($request) {
|
function autocomplete($request) {
|
||||||
$SQL_title = Convert::raw2sql($request->getVar('title'));
|
$results = Page::get()->filter("Title", $request->getVar('title'));
|
||||||
$results = DataObject::get("Page", "Title = '$SQL_title'");
|
|
||||||
if(!$results) return new HTTPResponse("Not found", 404);
|
if(!$results) return new HTTPResponse("Not found", 404);
|
||||||
|
|
||||||
// Use HTTPResponse to pass custom status messages
|
// Use HTTPResponse to pass custom status messages
|
||||||
|
@ -150,7 +150,7 @@ and [tutorial:3-forms](/tutorials/3-forms).
|
|||||||
## Updating a page:
|
## Updating a page:
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
$page = DataObject::get_one("Page", "ParentID = 18");
|
$page = Page::get()->filter("ParentID", 18)->First();
|
||||||
$page->Title = "More Serious";
|
$page->Title = "More Serious";
|
||||||
$page->writeToStage('Stage');
|
$page->writeToStage('Stage');
|
||||||
$page->Publish('Stage', 'Live');
|
$page->Publish('Stage', 'Live');
|
||||||
|
@ -24,6 +24,7 @@ For `[api:MySQLDatabase]`, this will be `[mysql_real_escape_string()](http://de3
|
|||||||
* DataObject::castedUpdate()
|
* DataObject::castedUpdate()
|
||||||
* DataObject->Property = 'val', DataObject->setField('Property','val')
|
* DataObject->Property = 'val', DataObject->setField('Property','val')
|
||||||
* DataObject::write()
|
* DataObject::write()
|
||||||
|
* DataList->byID()
|
||||||
* Form->saveInto()
|
* Form->saveInto()
|
||||||
* FormField->saveInto()
|
* FormField->saveInto()
|
||||||
* DBField->saveInto()
|
* DBField->saveInto()
|
||||||
@ -65,7 +66,7 @@ Example:
|
|||||||
class MyForm extends Form {
|
class MyForm extends Form {
|
||||||
public function save($RAW_data, $form) {
|
public function save($RAW_data, $form) {
|
||||||
$SQL_data = Convert::raw2sql($RAW_data); // works recursively on an array
|
$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 {
|
class MyController extends Controller {
|
||||||
public function myurlaction($RAW_urlParams) {
|
public function myurlaction($RAW_urlParams) {
|
||||||
$SQL_urlParams = Convert::raw2sql($RAW_urlParams); // works recursively on an array
|
$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
|
// cast the 'category' GET variable as an integer
|
||||||
$categoryID = (int)$_GET['category'];
|
$categoryID = (int)$_GET['category'];
|
||||||
|
|
||||||
// perform a get_by_id, ensure the ID is an integer before querying
|
// perform a byID(), which ensures the ID is an integer before querying
|
||||||
return DataObject::get_by_id('CaseStudy', $categoryID);
|
return CaseStudy::get()->byID($categoryID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ but rather just the returned collection,
|
|||||||
:::php
|
:::php
|
||||||
$myPage = $this->objFromFixture('Page', 'mypage');
|
$myPage = $this->objFromFixture('Page', 'mypage');
|
||||||
$myOtherPage = $this->objFromFixture('Page', 'myotherpage');
|
$myOtherPage = $this->objFromFixture('Page', 'myotherpage');
|
||||||
$pages = DataObject::get('Page');
|
$pages = Page::get();
|
||||||
// Bad: Assumptions about IDs and their order
|
// Bad: Assumptions about IDs and their order
|
||||||
$this->assertEquals(array(1,2), $pages->column('ID'));
|
$this->assertEquals(array(1,2), $pages->column('ID'));
|
||||||
// Good: Uses actually created IDs, independent of their order
|
// Good: Uses actually created IDs, independent of their order
|
||||||
|
@ -406,8 +406,8 @@ control. We can get the data for the news articles by implementing our own funct
|
|||||||
:::php
|
:::php
|
||||||
...
|
...
|
||||||
public function LatestNews($num=5) {
|
public function LatestNews($num=5) {
|
||||||
$holder = DataObject::get_one("ArticleHolder");
|
$holder = ArticleHolder::get()->First();
|
||||||
return ($holder) ? DataList::create('ArticlePage')->where('"ParentID" = '.$holder->ID)->sort('Date DESC')->limit($num) : false;
|
return ($holder) ? ArticlePage::get()->filter('ParentID', $holder->ID)->sort('Date DESC')->limit($num) : false;
|
||||||
}
|
}
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ then create our graph using a page control in the template. Create the function
|
|||||||
|
|
||||||
:::php
|
:::php
|
||||||
public function BrowserPollResults() {
|
public function BrowserPollResults() {
|
||||||
$submissions = DataObject::get('BrowserPollSubmission');
|
$submissions = BrowserPollSubmission::get();
|
||||||
$total = $submissions->Count();
|
$total = $submissions->Count();
|
||||||
|
|
||||||
$doSet = new DataObjectSet();
|
$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.
|
This introduces a few new concepts, so let's step through it.
|
||||||
|
|
||||||
:::php
|
:::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
|
First we get all of the *BrowserPollSubmission*s from the database. This returns the submissions as a
|
||||||
|
@ -703,7 +703,7 @@ it *MyProject* for instance.
|
|||||||
...
|
...
|
||||||
|
|
||||||
public function MyProject() {
|
public function MyProject() {
|
||||||
return DataObject::get( 'Project', "`MyStudentID` = '{$this->ID}'" );
|
return Project::get()->filter("MyStudentID", $this->ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ class GroupedList extends SS_ListDecorator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $index
|
* @param string $index
|
||||||
* @return ArrayList
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function groupBy($index) {
|
public function groupBy($index) {
|
||||||
$result = array();
|
$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 $index
|
||||||
* @param string $children
|
* @param string $children Name of the control under which children can be iterated on
|
||||||
* @return ArrayList
|
* @return ArrayList
|
||||||
*/
|
*/
|
||||||
public function GroupedBy($index, $children = 'Children') {
|
public function GroupedBy($index, $children = 'Children') {
|
||||||
|
Loading…
Reference in New Issue
Block a user