Domain Model und sorting

  • sunixzs sunixzs
    R2-D2
    0 x
    123 Beiträge
    2 Hilfreiche Beiträge
    28. 02. 2011, 14:38

    Hallo Forum,

    für eine Extension habe ich zwei Domain-Model:
    - Entry
    - Category

    Ein Entry kann mehrere Category-Verknüpfungen haben, die als MM-Relation mit einer MM-Tabelle realisiert sind.

    Für einen View benötige ich nun alle Entry aus einer bestimmten Kategorie. Um das zu realisieren habe ich im Repository ein SQL-Statement mit zwei JOINS:

    1. /**
    2. SQL-Statement
    3. */
    4. $sql = "
    5. SELECT " . $this->tableEntry . ".* FROM " . $this->tableEntry . "
    6. JOIN " . $this->tableMM . " ON " . $this->tableEntry . ".uid = " . $this->tableMM . ".uid_local
    7. JOIN " . $this->tableCategory . " ON " . $this->tableCategory . ".uid = " . $this->tableMM . ".uid_foreign
    8. WHERE " . $where . "
    9. GROUP BY " . $this->tableEntry . ".uid
    10. ORDER BY " . $order . " " . $direction . "
    11. LIMIT " . $limit . "
    12. ";
    13. // Anm.: in $where stehen dann z. B. $cObj->enableFields( "table" ) und die Einschränkung auf die Kategorien
    14.  
    15. /**
    16. Query
    17. */
    18. $query = $this->createQuery();
    19. $query->statement($sql);
    20. Return $query->execute();

    Das funktioniert auch soweit.

    Beim Anzeigen der Einträge will ich auch die Kategorien mit ausgeben - die sollen sortiert sein. Da ich kein SQL-Statement kenne, wo man die Relation aus dem JOIN sortieren kann, mache ich das per PHP anschließend im Controller (Vllt. weiß wer, wie man das einfacher machen kann mit weniger Aufwand?):

    1. // Entry-Controller-Action (gekürzt zum Erklären)
    2. $entries = $this->entryRepository->findByCategory($category);
    3. $entries->toArray();
    4. foreach ($entries as $entry){
    5. $entry->orderCategory();
    6. }
    7. $this->view->assign('entries', $entries);

    Methode orderCategory() im Entry-Model:

    1. public function orderCategory() {
    2. // write Categroy-Objects to array
    3. $tmpArr = Array();
    4. foreach ($this->category as $cat) {
    5. $tmpArr[] = $cat;
    6. }
    7.  
    8. // Sort Objects in Array
    9. usort($tmpArr, Array("Tx_LbrDate_Domain_Model_Entry", "sortBySortingAsc" ));
    10.  
    11. // create new Data-Object and add Category-Objects
    12. $this->category = new Tx_Extbase_Persistence_ObjectStorage;
    13. foreach ($tmpArr as $cat) {
    14. self::addCategory($cat);
    15. }
    16.  
    17. public static function sortBySortingAsc($a, $b) {
    18. if ($a->getSorting() < $b->getSorting()) $retVal = -1;
    19. else if($a->getSorting() == $b->getSorting()) $retVal = 0;
    20. else $retVal = 1;
    21. #echo $retVal;
    22. return $retVal;
    23. }

    Damit "sorting" überhaupt vorhanden ist machte ich folgendes:

    - Feld sorting in der Datenbank erstellen (Datei ext_tables.sql):

    1. CREATE TABLE tx_myextension_domain_model_category (
    2. // [...]
    3. sorting INT(11) DEFAULT '0' NOT NULL,
    4. // [...]
    5. )

    - Sorting im TCA deklarieren, damit die Kategorien überhaupt sortierbar sind im Backend (Datei ext_tables.php):

    1. $TCA['tx_myextension_domain_model_category'] = array (
    2. // [...]
    3. [ctrl] = array(
    4. // [...]
    5. 'sortby' => 'sorting',
    6. // [...]
    7. )
    8. // [...]
    9. );

    - Dem Model "sorting" beibringen (Classes/Domain/Model/Category.php):

    1. /**
    2.  * sorting
    3.  *
    4.  * @var string $sorting
    5.  */
    6. Protected $sorting;
    7.  
    8. /**
    9.  * Setter for sorting
    10.  *
    11.  * @param string $sorting
    12.  * @return void
    13.  */
    14. public function setSorting($sorting) {
    15. $this->sorting = $sorting;
    16. }
    17.  
    18. /**
    19.  * Getter for sorting
    20.  *
    21.  * @return string sorting
    22.  */
    23. public function getSorting() {
    24. return $this->sorting;
    25. }

    (müsste eigtl. vom Typ int sein, brachte aber keinen Unterschied)

    Nun das Problem:
    Nach diesen Schritten dachte ich, dass das Model "sorting" kennt und man loslegen kann mit der Sortierung. Die Sortier-Methoden brachten auch keine Fehler - also der Zugriff auf "Tx_MyExtension_Domain_Model_Category->getSorting()" funktionierte. Das Problem dabei war aber, dass in der Datenbank Werte für "sorting" vorhanden waren, die Methode getSorting() aber keine Werte zurücklieferte.

    Dann ging ich her und erweiterte die TCA-Konfiguration für die Tabelle um das Feld "sorting", um mir die Werte mal im Backend anzuschauen (Datei: Classes/Configuration/TCA/Category.php):

    1. $TCA['tx_myextension_domain_model_category'] = array(
    2. [...] 'showRecordFieldList' => '[...] sorting [...]'
    3. [...] 'interface' => '[...] sorting [...]'
    4. 'columnes' => [...]
    5. 'sorting' => array(
    6. 'exclude' => 1,
    7. 'label' => 'sorting',
    8. 'config' => array(
    9. 'type' => 'input',
    10. 'size' => 6,
    11. 'eval' => '',
    12. 'readOnly' => 1
    13. ),
    14. ),
    15. [...]
    16. );

    Von nun an liefert das Model den korrekten Werte für "sorting". Hässlich ist nur, dass ich im Backend ein TCA-Feld für "sorting" benötige. Das habe ich jetzt als readonly markiert (hidden gibt es nicht, oder?).

    Was ich nun nicht verstehe:
    (1) Wenn ich die Kategorien ausgebe und gleich im Category-Repository nach "sorting" sortiere, funktioniert das korrekt, auch wenn das Model keine Variable $sorting kennt, ebenso keine Getter/Setter vorhanden sind (Datei: Classes/Domain/Model/Category.php) und "sorting" nicht im TCA definiert ist (Datei: Classes/Configuration/TCA/Category.php). Eigtl. müsste das Repository doch hergehen und Alarm geben, dass "sorting" unbekannt ist?

    (2) Wenn das Model "sorting" kennt, warum liefert getSorting() erst den korrekten Wert, wenn es zusätzlich zu ext_tables.php in Classes/Configuration/TCA/Category.php definiert ist? In den Parent-Classes habe ich diesbezüglich leider nichts finden können (dort wird z. B. uid und pid definiert - zu sorting fand ich nichts).

    Das ganze habe ich mal etwas ausführlicher beschrieben, da ich denke, dass MM-Relationen und Sortierungen häufig in Extensions anzutreffen sind und ich, vllt. auch andere, darüber bisher nicht schlauer wurde.

    Ich erhoffe mir, dass
    - wir die beste Methode finden JOINS im Repository zu realisieren (nur SQL grenzt halt ein und entspricht nicht dem MVC-Gedanken)

    - wir die einfachste Methodik finden die Relationen zu sortieren.

    - Klarheit entsteht, wie das Model zu seinen Daten findet. (Warum erhält das Model nicht die Daten, die im Model beschrieben sind. Warum sind die Daten erst vorhanden, wenn es auch im TCA definiert ist?).
    Eine Idee, die ich noch verfolge, sind die @-Kommentare bei der Variablen-Definition im Model - vllt. lässt sich dort ja definieren, dass die Daten doch entsprechend aus dem Repository geholt werden sollen, auch wenn darüber im TCA nichts steht.

    Vielen Dank für euer Gehör und danke für etwaige Lösungen bei meinen Problemchen.

    LG sun

    Edith sagt; Smilies aus den Quelltexten entfernt


  • 1
  • sunixzs sunixzs
    R2-D2
    0 x
    123 Beiträge
    2 Hilfreiche Beiträge
    28. 02. 2011, 15:05

    Beim weiteren verfolgen von "wie bekommt das Model die Daten" fand ich in der Doku, dass die Daten mit Hilfe vom TCA ge-mapped werden.

    Dazu fand ich auch in der Klasse Tx_Extbase_Persistence_Mapper_DataMapper die Methode thawProperties(). Dort wird u. a. uid und pid in das MOdel-Object geladen.

    Anscheinend wäre dort auch der Ansatzpunkt für das Feld "sorting"?

  • Proximo Proximo
    Jedi-Ratsmitglied
    0 x
    563 Beiträge
    0 Hilfreiche Beiträge
    01. 03. 2011, 10:27

    Danke für deine Anleitung, ich hab mit ihr Sorting in meine neue Extension für Extbase einbauen können. Ich selbst habe dabei "sorting" übrigens nicht auf "readonly" gesetzt sondern schlichtweg bei 'types' => '1' => 'showitems' => ... weglassen.

    MFG Proximo

  • kimpixel kimpixel
    TYPO3-Anwärter
    0 x
    6 Beiträge
    0 Hilfreiche Beiträge
    24. 09. 2012, 16:05

    Wenn man Eigenschaften aus der DB im Model haben möchte, diese aber nicht im TCA definieren will, kann man diese in der setup.txt eintragen.

    1. persistence {
    2. classes {
    3. Tx_MyExt_Domain_Model_Name {
    4. mapping {
    5. tableName = tx_myext_domain_model_name
    6. columns {
    7. sorting.mapOnProperty = sorting
    8. }
    9. }
    10. }
    11. }
    12. }

  • DavidBruchmann DavidBruc...
    Typ im Roten Hemd
    0 x
    2 Beiträge
    0 Hilfreiche Beiträge
    22. 04. 2014, 03:50

    Ist zwar schon alt aber vielleicht interessierts Jemanden:

    Beim Anzeigen der Einträge will ich auch die Kategorien mit ausgeben - die sollen sortiert sein. Da ich kein SQL-Statement kenne, wo man die Relation aus dem JOIN sortieren kann, mache ich das per PHP anschließend im Controller (Vllt. weiß wer, wie man das einfacher machen kann mit weniger Aufwand?):

    so etwa klappt es bei mir problemlos (code ist wegen Lesbarkeit reduziert und funktioniert so nicht):

    1. SELECT $this->tableEntry.* FROM $this->tableEntry
    2. FROM $this->tableEntry, $this->tableMM, $this->tableCategory
    3. WHERE $this->tableEntry.uid = $this->tableMM.uid_local
    4. AND $this->tableCategory.uid = $this->tableMM.uid_foreign
    5. AND $where
    6. (GROUP BY $this->tableEntry.uid)
    7. ORDER BY $this->tableCategory.title
    8. LIMIT $limit

    Übrigens lese ich nur die uids aus und rufe die entsprechenden Datensätze hinterher einzeln auf, dadurch habe ich Objekte und keine Arrays in Extbase und muss im Fluid-Template nicht lange ändern.

  • 1