Bidirektionale MM-Relation in Typo3 (ab Version 6.2). Feld wird nicht gespeichert, Feld bleibt leer. uid_local und uid_foreign vertauscht.

Problem: Man hat eine MM-Tabelle in Typo3 angelegt, z.B. um eine Verbindung zwischen den Tabellen „Firma“ und „Mitarbeiter“ zu schaffen. Beim Bearbeiten eines Datensatzes „Firma“ möchte man Mitarbeiter auswählen können. Anders herum (bidirektional) soll man beim Öffnen eines Datensatzes „Mitarbeiter“ sehen können, welchen Firmen er zugeordnet wurde und auch von dieser Seite aus die MM-Relation bearbeiten können. Man kann die MM-Relation also von beiden Seiten aus (bidirectional) bearbeiten.

Vorab: Ich habe sie alle probiert. Alle Tutorials die bei Google auftauchen, z.B.
http://de.kimpixel.wikia.com/wiki/TCA_Beispiele
http://blog.undkonsorten.com/datenbankrelationen-typo3-irre-extension
http://www.andreas-buergel.com/kb/typo3/typo3-mm-relation-beidseitig-in-extension.html
http://www.typo3tiger.de/blog/post/typo3-bidirektionale-mm-relation-tca-extbase.html
… und sie haben alle nicht funktioniert. Am Ende scheiterte es immer daran, dass beim Einfügen folgender Zeile ins TCA

'MM_opposite_field' => 'xxx'

keine Relationen mehr im dem bidirektionalen Datensatz gespeichert wurden. Das Feld blieb einfach leer. Wenn ich dagegen die Zeile auskommentiert hatte, wurden die uid_foreign und uid_local in der MM-Tabelle vertauscht.

Für Suchmaschinen: Typo3 bidirectional m:m relationship not working. Problem birdirektionale mm-Relation extbase. Bidrektionale MM-Relation Problem Feld wird nicht gespeichert. uid_local uid_foreign vertauscht. MM_opposite_field funktioniert nicht. MM-Datensätze beidseitig bearbeiten. uk Datenbank Tutorial Fehler. t3uk_db_tutorial für Typo3 6.2.

Lösung (Kurzversion)

:
1. Im TCA muss (neben dem Feld MM_opposite_field) zwingend die Einstellung ‚multiple‘ => ‚1‘ gesetzt werden

'multiple' => 1

2. In der MM-Tabelle muss es ein Feld für sorting_foreign geben:

sorting_foreign int(11) DEFAULT '0' NOT NULL

Lösung (Langversion und Beispiel)

Die entscheidenden Felder in der Tabelle ext_tables.sql:

#
# Die MM-Tabelle 'tx_beispiel_mitarbeiter_firma_mm'
#
CREATE TABLE tx_beispiel_mitarbeiter_firma_mm (
  uid_local int(11) DEFAULT '0' NOT NULL,
  uid_foreign int(11) DEFAULT '0' NOT NULL,
  tablenames varchar(30) DEFAULT '' NOT NULL,
  sorting int(11) DEFAULT '0' NOT NULL,
  sorting_foreign int(11) DEFAULT '0' NOT NULL,
  KEY uid_local (uid_local),
  KEY uid_foreign (uid_foreign)
);

#
# Die Tabelle für die Firmen
#
CREATE TABLE tx_beispiel_firma (
   ...
   mitarbeiter tinyint(1) DEFAULT '1' NOT NULL,
   ...
);

#
# Die Tabelle für die Mitarbeiter
#
CREATE TABLE tx_beispiel_mitarbeiter (
   ...
   firmen tinyint(1) DEFAULT '1' NOT NULL,
   ...
);

Die Feld-Definitionen im TCA für die Tabelle der Firma (tx_beispiel_firma). Hier ist entscheidend, dass ‚multiple‘ => 1 gesetzt ist:

'mitarbeiter' => array(
   'label'   => 'Mitarbeiter',
   'config' => array(
      'type' => 'select',            
      'size' => 10,
      'maxitems' => 9999,
      'autoSizeMax' => 10,
      'foreign_table' => 'fe_users',
      'multiple' => 1,
      'MM' => 'tx_beispiel_mitarbeiter_firma_mm',
   )
),

Die Feld-Definitionen im TCA für die Tabelle der Mitarbeiter (tx_beispiel_mitarbeiter). Hier ist entscheidend, dass ‚multiple‘ => 1 und ‚MM_opposite_field‘ => ‚mitarbeiter‘ gesetzt ist. ‚mitarbeiter‘ ist dabei der „gegenüberliegende“ Feld-Name in der Tabelle tx_beispiel_firma.

'firmen' => Array (
   'label' => 'Firmen',
   'config' => array(
      'type' => 'select',
      'size' => 10,
      'maxitems' => 9999,
      'multiple' => 1,
      'foreign_table' => 'tx_beispiel_firma',
      'MM' => 'tx_beispiel_mitarbeiter_firma_mm',
      'MM_opposite_field' => 'mitarbeiter',
   )
),