mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
Merge pull request #465 from halkyon/aggregate_fixes
Deprecated aggregates fix
This commit is contained in:
commit
c4a1523fac
@ -193,6 +193,17 @@ 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()`).
|
||||||
|
|
||||||
|
### Aggregate changes for partial caching in templates ###
|
||||||
|
|
||||||
|
`DataObject::Aggregate()` and `DataObject::RelationshipAggregate()` are now deprecated. To replace your deprecated aggregate calls
|
||||||
|
in PHP code, you should query with something like `Member::get()->max('LastEdited')`, that is, calling the aggregate on the `DataList` directly.
|
||||||
|
The same concept applies for replacing `RelationshipAggregate()`, just call the aggregate method on the relationship instead,
|
||||||
|
so something like `Member::get()->Groups()->max('LastEdited')`.
|
||||||
|
|
||||||
|
For partial caching in templates, the syntax `<% cached Aggregate(Page).Max(LastEdited) %>` has been deprecated. The new syntax is similar,
|
||||||
|
except you use `List()` instead of `Aggregate()`, and the aggregate call `Max()` is now lowercase, as in `max()`.
|
||||||
|
An example of the new syntax is `<% cached List(Page).max(LastEdited) %>`. Check `DataList` class for more aggregate methods to use.
|
||||||
|
|
||||||
### `SQLQuery` changes ###
|
### `SQLQuery` changes ###
|
||||||
|
|
||||||
`SQLQuery` has been changed so direct access to internal properties `$from`, `$select`, `$orderby` is
|
`SQLQuery` has been changed so direct access to internal properties `$from`, `$select`, `$orderby` is
|
||||||
|
@ -61,21 +61,21 @@ For example, if we have a menu, we want that menu to update whenever _any_ page
|
|||||||
otherwise. By using aggregates, that's easy
|
otherwise. By using aggregates, that's easy
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<% cached 'navigation', Aggregate(Page).Max(LastEdited) %>
|
<% cached 'navigation', List(Page).max(LastEdited) %>
|
||||||
|
|
||||||
|
|
||||||
If we have a block that shows a list of categories, we can make sure the cache updates every time a category is added or
|
If we have a block that shows a list of categories, we can make sure the cache updates every time a category is added or
|
||||||
edited
|
edited
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<% cached 'categorylist', Aggregate(Category).Max(LastEdited) %>
|
<% cached 'categorylist', List(Category).max(LastEdited) %>
|
||||||
|
|
||||||
|
|
||||||
We can also calculate aggregates on relationships. A block that shows the current member's favourites needs to update
|
We can also calculate aggregates on relationships. A block that shows the current member's favourites needs to update
|
||||||
whenever the relationship Member::$has_many = array('Favourites' => Favourite') changes.
|
whenever the relationship Member::$has_many = array('Favourites' => Favourite') changes.
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<% cached 'favourites', CurrentMember.ID, CurrentMember.RelationshipAggregate(Favourites).Max(LastEdited) %>
|
<% cached 'favourites', CurrentMember.ID, CurrentMember.Favourites.max(LastEdited) %>
|
||||||
|
|
||||||
|
|
||||||
## Cache key calculated in controller
|
## Cache key calculated in controller
|
||||||
@ -89,7 +89,7 @@ logic into the controller
|
|||||||
return implode('_', array(
|
return implode('_', array(
|
||||||
'favourites',
|
'favourites',
|
||||||
$member->ID,
|
$member->ID,
|
||||||
$member->RelationshipAggregate('Favourites')->Max('LastEdited')
|
$member->Favourites()->max('LastEdited')
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ Can be re-written as:
|
|||||||
:::ss
|
:::ss
|
||||||
<% cached LastEdited %>
|
<% cached LastEdited %>
|
||||||
|
|
||||||
<% cached RelationshipAggregate(Children).Max(LastEdited) %>
|
<% cached Children.max(LastEdited) %>
|
||||||
<% control Children %>
|
<% control Children %>
|
||||||
$Name
|
$Name
|
||||||
<% end_control %>
|
<% end_control %>
|
||||||
|
@ -2659,7 +2659,9 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
* @deprecated 3.0 Use DataList::create and DataList to do your querying
|
* @deprecated 3.0 Use DataList::create and DataList to do your querying
|
||||||
*/
|
*/
|
||||||
public function Aggregate($class = null) {
|
public function Aggregate($class = null) {
|
||||||
Deprecation::notice('3.0', 'Use DataList::create and DataList to do your querying instead.');
|
Deprecation::notice('3.0', 'Call aggregate methods on a DataList directly instead. In templates ' .
|
||||||
|
'an example of the new syntax is <% cached List(Member).max(LastEdited) %> instead (check partial-caching.md documentation ' .
|
||||||
|
'for more details.)');
|
||||||
|
|
||||||
if($class) {
|
if($class) {
|
||||||
$list = new DataList($class);
|
$list = new DataList($class);
|
||||||
@ -2676,7 +2678,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
* @deprecated 3.0 Use DataList::create and DataList to do your querying
|
* @deprecated 3.0 Use DataList::create and DataList to do your querying
|
||||||
*/
|
*/
|
||||||
public function RelationshipAggregate($relationship) {
|
public function RelationshipAggregate($relationship) {
|
||||||
Deprecation::notice('3.0', 'Use DataList::create and DataList to do your querying instead.');
|
Deprecation::notice('3.0', 'Call aggregate methods on a relationship directly instead.');
|
||||||
|
|
||||||
return $this->$relationship();
|
return $this->$relationship();
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,7 @@ class DataQuery {
|
|||||||
*
|
*
|
||||||
* @param String $field Unquoted database column name (will be escaped automatically)
|
* @param String $field Unquoted database column name (will be escaped automatically)
|
||||||
*/
|
*/
|
||||||
function Max($field) {
|
function max($field) {
|
||||||
return $this->getFinalisedQuery()->aggregate(sprintf('MAX("%s")', Convert::raw2sql($field)))->execute()->value();
|
return $this->getFinalisedQuery()->aggregate(sprintf('MAX("%s")', Convert::raw2sql($field)))->execute()->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +333,7 @@ class DataQuery {
|
|||||||
*
|
*
|
||||||
* @param String $field Unquoted database column name (will be escaped automatically)
|
* @param String $field Unquoted database column name (will be escaped automatically)
|
||||||
*/
|
*/
|
||||||
function Min($field) {
|
function min($field) {
|
||||||
return $this->getFinalisedQuery()->aggregate(sprintf('MIN("%s")', Convert::raw2sql($field)))->execute()->value();
|
return $this->getFinalisedQuery()->aggregate(sprintf('MIN("%s")', Convert::raw2sql($field)))->execute()->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +342,7 @@ class DataQuery {
|
|||||||
*
|
*
|
||||||
* @param String $field Unquoted database column name (will be escaped automatically)
|
* @param String $field Unquoted database column name (will be escaped automatically)
|
||||||
*/
|
*/
|
||||||
function Avg($field) {
|
function avg($field) {
|
||||||
return $this->getFinalisedQuery()->aggregate(sprintf('AVG("%s")', Convert::raw2sql($field)))->execute()->value();
|
return $this->getFinalisedQuery()->aggregate(sprintf('AVG("%s")', Convert::raw2sql($field)))->execute()->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +351,7 @@ class DataQuery {
|
|||||||
*
|
*
|
||||||
* @param String $field Unquoted database column name (will be escaped automatically)
|
* @param String $field Unquoted database column name (will be escaped automatically)
|
||||||
*/
|
*/
|
||||||
function Sum($field) {
|
function sum($field) {
|
||||||
return $this->getFinalisedQuery()->aggregate(sprintf('SUM("%s")', Convert::raw2sql($field)))->execute()->value();
|
return $this->getFinalisedQuery()->aggregate(sprintf('SUM("%s")', Convert::raw2sql($field)))->execute()->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A hierarchy of data types, to
|
* A hierarchy of data types, to...
|
||||||
|
*
|
||||||
|
* @deprecated. This is testing`
|
||||||
|
* {@link DataObject::Aggregate()} and {@link DataObject::RelationshipAggregate()}
|
||||||
|
* which are deprecated. Aggregates are handled directly by DataList instead.
|
||||||
|
* This test should be removed or merged into DataListTest once those functions are
|
||||||
|
* removed from DataObject.
|
||||||
*/
|
*/
|
||||||
class AggregateTest_Foo extends DataObject implements TestOnly {
|
class AggregateTest_Foo extends DataObject implements TestOnly {
|
||||||
static $db = array(
|
static $db = array(
|
||||||
|
@ -3,7 +3,8 @@ class GenericTemplateGlobalProvider implements TemplateGlobalProvider {
|
|||||||
|
|
||||||
public static function get_template_global_variables() {
|
public static function get_template_global_variables() {
|
||||||
return array(
|
return array(
|
||||||
'ModulePath'
|
'ModulePath',
|
||||||
|
'List' => 'getDataList'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,5 +31,24 @@ class GenericTemplateGlobalProvider implements TemplateGlobalProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This allows templates to create a new `DataList` from a known
|
||||||
|
* DataObject class name, and call methods such as aggregates.
|
||||||
|
*
|
||||||
|
* The common use case is for partial caching:
|
||||||
|
* <code>
|
||||||
|
* <% cached List(Member).max(LastEdited) %>
|
||||||
|
* loop members here
|
||||||
|
* <% end_cached %>
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @return DataList
|
||||||
|
*/
|
||||||
|
public static function getDataList($className) {
|
||||||
|
$list = new DataList($className);
|
||||||
|
$list->setDataModel(DataModel::inst());
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ class SSViewer_Scope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function obj($name, $arguments = null, $forceReturnedObject = true, $cache = false, $cacheName = null) {
|
function obj($name, $arguments = null, $forceReturnedObject = true, $cache = false, $cacheName = null) {
|
||||||
|
|
||||||
switch ($name) {
|
switch ($name) {
|
||||||
case 'Up':
|
case 'Up':
|
||||||
if ($this->upIndex === null) user_error('Up called when we\'re already at the top of the scope', E_USER_ERROR);
|
if ($this->upIndex === null) user_error('Up called when we\'re already at the top of the scope', E_USER_ERROR);
|
||||||
@ -72,7 +71,6 @@ class SSViewer_Scope {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
$this->item = $this->getObj($name, $arguments, $forceReturnedObject, $cache, $cacheName);
|
$this->item = $this->getObj($name, $arguments, $forceReturnedObject, $cache, $cacheName);
|
||||||
|
|
||||||
$this->itemIterator = null;
|
$this->itemIterator = null;
|
||||||
$this->upIndex = $this->currentIndex ? $this->currentIndex : count($this->itemStack)-1;
|
$this->upIndex = $this->currentIndex ? $this->currentIndex : count($this->itemStack)-1;
|
||||||
$this->currentIndex = count($this->itemStack);
|
$this->currentIndex = count($this->itemStack);
|
||||||
@ -380,7 +378,6 @@ class SSViewer_DataPresenter extends SSViewer_Scope {
|
|||||||
// Then for iterator-specific overrides
|
// Then for iterator-specific overrides
|
||||||
else if (array_key_exists($property, self::$iteratorProperties)) {
|
else if (array_key_exists($property, self::$iteratorProperties)) {
|
||||||
$source = self::$iteratorProperties[$property];
|
$source = self::$iteratorProperties[$property];
|
||||||
|
|
||||||
if ($this->itemIterator) {
|
if ($this->itemIterator) {
|
||||||
// Set the current iterator position and total (the object instance is the first item in the callable array)
|
// Set the current iterator position and total (the object instance is the first item in the callable array)
|
||||||
$source['implementer']->iteratorProperties($this->itemIterator->key(), $this->itemIteratorTotal);
|
$source['implementer']->iteratorProperties($this->itemIterator->key(), $this->itemIteratorTotal);
|
||||||
@ -423,6 +420,7 @@ class SSViewer_DataPresenter extends SSViewer_Scope {
|
|||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getObj($name, $arguments = null, $forceReturnedObject = true, $cache = false, $cacheName = null) {
|
function getObj($name, $arguments = null, $forceReturnedObject = true, $cache = false, $cacheName = null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user