Version 2.4.3
Mit Hilfe des DataObjectSet kann man die Blätterfunktion von Objekten erstellen. Der Aufruf von Children oder AllChildren liefert ein solches Objekt zurück.
Dieses kann man mit setPageLength, getRange, setPageLimits wie folgt die gewünschten Objekte anzeigen:
| Controller | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$allChild = $this->AllChildren(); if(!$allChild) return null; # einträge pro seite $limit = $this->PageLength; if(empty($limit)) $limit = 5; $allChild->setPageLength($limit); $allChild->sort('PublicationDate','DESC'); # start ist der default wert. # kann mit setPaginationGetVar geändert werden. $start = 0; if(isset($_GET['start']) && !empty($_GET['start'])) { $start = $_GET['start']; } $ret = $allChild->getRange($start,$limit); $ret->setPageLimits($start,$limit,$allChild->count()); |
Dazu das Template:
| Template | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<% if getNews %> <% control getNews %> <h2>$MenuTitle.XML</h2> $MetaDescription <p>$PublicationDate.Nice</p> <% end_control %> <% end_if %> <% if getNews.MoreThanOnePage %> <% if getNews.NotFirstPage %> <a class="prev" href="$getNews.PrevLink">Zurück</a> <% end_if %> <% control getNews.PaginationSummary %> <% if CurrentBool %> $PageNum <% else %> <% if Link %> <a href="$Link">$PageNum</a> <% else %> ... <% end_if %> <% end_if %> <% end_control %> <% if getNews.NotLastPage %> <a class="next" href="$getNews.NextLink">Weiter</a> <% end_if %> <% end_if %> |
Dies funktioniert wunderbar, wenn man die den bestehenden Features arbeitet. Man kann sogar nach den zusätzlichen Felder (PublicationDate) sortieren. So weit so gut.
Was aber nun wenn man die Kindern anhand andere Kriterien filtern möchte, dabei aber die normalen Zugriffsregeln nicht aus acht lassen ?
Denn wenn man seine eigenen Abfragen mit DataObjet::get macht, umgeht man die Zugriffsregeln wie canView, canEdit etc. Ist natürlich keine so tolle Sache.... Ich habe leider bisher keine Möglichkeit gefunden zusätzliche Kriterien den Standart-funktionen mitzugeben.
Ein bestehendes Problem ist leider, dass die Limitierung nur für die Anzeige gilt, nicht aber für die Abfrage. Es werden bei Children() und AllChildren() immer alle Einträge ausgelesen und diese dann im DataObjectSet limitiert. Performant ist das nicht.
Sicherlich kann man das auch mit eigenen SQL Abfragen hinbekommen, aber wenn man schon ein Framework einsetzt dann sollte man sich an die Möglichkeiten die dieses System bietet auch halten.
Also musste ich etwas anderes finden, was aber mit dem System kompatibel ist und ich nicht das Basissystem ändern muss. Nach langem hin und her bin ich aber dann doch auf eine simple Methode gestossen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public function getNews() { $allChild = new DataObjectSet(); $run1 = DataObject::get( $callerClass = "NewsPage", $filter = "`ParentID` = '".$this->ID."'" ); if(!empty($run1)) { foreach($run1 as $entry) { if($entry->canView()) { $allChild->push($entry); } } } # einträge pro seite $limit = $this->PageLength; if(empty($limit)) $limit = 5; $allChild->setPageLength($limit); // sort the DataObjectSet // see http://doc.silverstripe.com/doku.php?id=dataobjectset#sorting $allChild->sort('PublicationDate','DESC'); # start ist der default wert. # kann mit setPaginationGetVar geändert werden. $start = 0; if(isset($_GET['start']) && !empty($_GET['start']) && filter_var($_GET['start'],FILTER_VALIDATE_INT)) { $start = $_GET['start']; } $ret = $allChild->getRange($start,$limit); $ret->setPageLimits($start,$limit,$allChild->count()); return $ret; } |
Somit lässt sich die Auflistung von Unterseiten unkompliziert auf den Klassennamen einschränken und man hat doch die volle Kontrolle über die Rechte.
Performant ist die Lösung nicht. Aber wenn es um Performance geht, stelle ich SilverStripe eher hinten an.
Man hätte auch im Template selber via control "KlassenName" die Unterseiten bekommen können, aber damit hat man nicht wirklich die Kontrolle über das Ergebnis.
