Skip to content

Commit

Permalink
Fixed usage of DataList etc in docs (fixes #7518)
Browse files Browse the repository at this point in the history
  • Loading branch information
chillu committed Jun 27, 2012
1 parent cb145a0 commit 868d369
Show file tree
Hide file tree
Showing 28 changed files with 246 additions and 259 deletions.
9 changes: 9 additions & 0 deletions docs/en/changelogs/3.0.0.md
Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions docs/en/howto/csv-import.md
Expand Up @@ -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();
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion docs/en/howto/extend-cms-interface.md
Expand Up @@ -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);
}
}

Expand Down
106 changes: 55 additions & 51 deletions docs/en/howto/grouping-dataobjectsets.md
@@ -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:
Expand All @@ -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 {
Expand All @@ -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 %>
Expand All @@ -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)
2 changes: 1 addition & 1 deletion docs/en/howto/index.md
Expand Up @@ -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).
Expand Down
11 changes: 7 additions & 4 deletions docs/en/howto/pagination.md
@@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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)
4 changes: 2 additions & 2 deletions docs/en/misc/coding-conventions.md
Expand Up @@ -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) {}
Expand All @@ -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.

Expand Down
76 changes: 45 additions & 31 deletions docs/en/reference/dataobject.md
Expand Up @@ -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).

:::php
class MyPage extends Page {
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Content',new CheckboxField('CustomProperty'));
return $fields;
}
}


## Scaffolding Formfields
## Defining Form Fields

These calls retrieve a `[api:FieldList]` for the area where you intend to work with the scaffolded form.
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.

### For the CMS
Example getCMSFields implementation

:::php
$fields = singleton('MyDataObject')->getCMSFields();
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.

### For the Frontend
## Scaffolding Form Fields

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()`.
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
$fields = singleton('MyDataObject')->getFrontEndFields();


## Customizing Scaffolded Fields
class MyDataObject extends DataObject {
// ...
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->fieldByName('IsActive')->setTitle('Is active?');
return $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.
The `[ModelAdmin](/reference/modeladmin)` class uses this approach to provide
data management interfaces with very little custom coding.

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

Expand Down

0 comments on commit 868d369

Please sign in to comment.