Moin,
danke für's Feedback - das geht ja eindeutig Richtung ObjectStorage-Methode.
Am besten mache ich es etwas konkreter, wie die Struktur ist:
Es gibt ein DomainModel Category mit der Relation zum DomainModel Entry. Allgemein darf jeder FrontendUser die Entry im Category sehen. Ausgewählte FrontendUser - nennen wir sie Member der Category - dürfen aber mehr: Entry der Category hinzufügen.
Dadurch, dass ich noch mehr über den aktuellen FrontendUser wissen muss - z.B. Zugriffsrechte für andere Objekte setzen und Benutzername ausgeben, erstelle ich in der initializeAction() des Controllers mit Hilfe einer Service-Klasse ein $GLOBALS-Object des aktuellen FrontendUser, um diesen überall zur Verfügung zu haben. Category wäre im obigen Beispiel der Parent und FrontendUser der Child.
Da der FrontendUser global ist, könnte ich in diesem Fall auf den Parameter im Getter verzichten - da ist schonmal etwas gewonnen:
public function isMember() {
if (!$GLOBALS['theCurrentFrontendUser']) {
return false;
}
return $this->getMember()->offsetExists($GLOBALS['theCurrentFrontendUser']);
}
Nun noch konkreter:
30 auszugebende Category im View sind denkbar. Mal angenommen, es gibt ca. 200 FrontendUser, von denen 50 zum Kern gehören und Member der Category sind.
- Bei der foreach-Schleife wären das im Grenzfall 30x50 = 1500 Iterationen über Domain-Objekte im ObjectStorage nur bei der Ausgabe der Category. Alle Member-Objekte müssen in der Persistence-Schicht existieren.
- Bei der Befrage-die-Datenbank-Methode wären es 30 zusätzliche Zugriffe auf die Datenbank.
- Mit der bevorzugten offsetExists()- oder contains()-Methode müssen auch alle Member-Objekte aus der Datenbank geholt werden. Der wesentliche Vorteil ist hier, dass nur einmal über alle Member-Objekte iteriert wird, um die Domain-Objekte zu erstellen (afaik).
Da kommt mir gerade eine Idee:
Da Category und Member eine mm-Relation darstellt, kann ich sie auch bidirektional anlegen und von Seitens des Member aus abfragen. Das dürfte die Menge der Domain-Objekte deutlich verringern, da eh alle Category ausgegeben werden und der Member nur in einigen von denen vertreten ist. Es muss nur der aktuelle FrontendUser vorhanden sein und nicht alle FrontendUser, die in einer der Category Member sind.
Hier die Implementierung der bidirektionalen mm-Relation, da diese nicht so bekannt sein dürfte:
#
# Table structure for table 'tx_exttitle_category_frontenduser_mm'
#
CREATE TABLE tx_exttitle_category_frontenduser_mm (
uid_local int(11) unsigned DEFAULT '0' NOT NULL,
uid_foreign int(11) unsigned DEFAULT '0' NOT NULL,
sorting int(11) unsigned DEFAULT '0' NOT NULL,
sorting_foreign int(11) unsigned DEFAULT '0' NOT NULL,
category int(11) unsigned DEFAULT '0' NOT NULL,
KEY uid_local (uid_local),
KEY uid_foreign (uid_foreign)
);
TCA Category:
'member' => array(
'exclude' => 0,
'label' => 'Member',
'config' => array(
'type' => 'group',
'internal_type' => 'db',
'foreign_table' => 'fe_users',
'allowed' => 'fe_users',
'MM' => 'tx_exttitle_category_frontenduser_mm',
'MM_opposite_field' => 'category',
'maxitems' => 99999,
'show_thumbs' => 1,
'size' => 10,
),
),
TCA Member bzw. FrontendUser
'category' => array(
'exclude' => 0,
'label' => 'Category',
'config' => array(
'type' => 'group',
'internal_type' => 'db',
'foreign_table' => 'tx_exttitle_domain_model_category',
'allowed' => 'tx_exttitle_domain_model_category',
'MM' => 'tx_exttitle_category_frontenduser_mm',
'size' => 10,
'maxitems' => 99999,
),
),
Die Deklaration des ObjectStorage inkl. Getter und Setter müssen dann ganz normal in beiden DomainModels vorhanden sein (im CategoryModel $member und im FrontendUserModel $category).
Die isMember()-Methode verschiebt sich jetzt in das FrontendUser-Model (wobei ich hier nicht mehr mit global arbeiten kann und dem Getter einen Parameter mitgeben müsste. Deswegen kann ich diesen Getter auch gleich weglassen und in einen ViewHelper verschieben):
public function isMemberOfCategory($categoryToDetect) {
if (!$categoryToDetect) {
return false;
}
return $this->getCategory()->offsetExists($categoryToDetect);
}
Eine Abfrage im View müsste durch einen ViewHelper erledigt werden:
<f:if condition="{tx:categoryHasMember(category:categoryInForLoop, member:currentFrontendUser)}"></f:if>
CategoryHasMemberViewHelper:
public function render($category, $member) {
if (!$member) {
return false;
}
return $member->getCategory()->getCategory()->offsetExists($category);
}
Falls ich mal irgendwann konkreteres weiß bzgl. Performance und Speicherbedarf, geb' ich bescheid.
Vielen Dank für euer Gehör und sonnige Grüße
sun