Hallo Harald,
vielen Dank für deine ausführliche Antwort.
Erstmal zu deiner ersten Nachfrage:
Bei der 1:n-Beziehung ist es so, wie du sagstest: die Mitarbeiter wurden auf deleted=1 gesetzt und die Anzahl der Mitarbeiter in dem Datensatz der gelöschten Firma bleibt gleich.
Bei der n:m-Beziehung wird zumindest der eine Datensatz richtig aus der Zuordnungstabelle gelöscht (also entfernt) - der Datensatz in der Mitarbeiter-Tabelle bleibt bestehen (was ja auch korrekt ist). Hier stimmt die Anzahl der Mitarbeiter in der Firma nach dem Löschen mit denen in der Zuordnungstabelle überein (wird also um 1 weniger, da eine Zuordnung aus der Datenbank gelöscht wurde).
Zu attach/detach:
Du hast Recht, wenn ich einen einzelnen Mitarbeiter via detach bei der n:m-Beziehung aus der Firma entferne, wird sowohl der Datensatz in der Zuordnungstabelle korrekt gelöscht, als auch die Anzahl der Mitarbeiter im Firmendatensatz runter gezählt. Wenn ich die Mitarbeiter aber in einer Schleife mit detach entferne, tritt bei mir das selbe Phänomen auf, wie bei dir: es wird nur jeder zweite Datensatz aus der Zuordnungstabelle gelöscht.
Da dies also offensichtlich ein Bug ist, habe ich mich auf die Suche nach bestehenden Bug-Reports gemacht und siehe da - hier ist die Lösung zu dem Problem:
http://forge.typo3.org/issues/51859
Der Code zum Löschen der Mitarbeiter in einer n:m-Beziehung in dem Firmen-Controller muss also wie folgt aussehen:
$company = $this->companyRepository->findByUid(5);
$members = $company->getMembers();
$memberClone = clone $members;
$members->removeAll($memberClone);
$this->companyRepository->update($company);
$this->companyRepository->remove($company);
Zu n:m-Beziehung aus zwei Seiten betrachten:
n:m-Beziehungen lassen sich leider nicht immer vermeiden und sind ja eigentlich auch eine völlig normale Sache bei der Datenbankmodellierung, wenn es korrekt über eine Zuordnungstabelle gelöst ist. Das kann Typo3 mit extbase ja auch sehr schön - aber eben nur von einer Seite aus...
D.h. nach deinem Vorschlag dürfte ich die Zuordnungstabellen nicht automatisch aus einer n:m-Beziehung über Typo3 bzw. den Extension-Builder erstellen lassen, sondern ich müsste die Zuordnungstabelle als eigenes Objekt anlegen (z.B. Contract) und dann die Firma und die Mitarbeiter per 1:n-Beziehung zu "Cotract" verweisen lassen? Hm... das hört sich für mich nach ziemlich viel Aufwand und vor allem nach ziemlich viel zusätzlichen Objekten an, wenn man viele Zuordnungstabellen benötigt... Da mus sich noch mal drüber schlafen :-)
Ich habe nochmal versucht die andere Betrachtungsweise (Firmen, die einem Mitarbeiter zugeordnet sind) zusätzlich selbst einzubauen. Dabei habe ich den Code, den der Extension-Builder im Company-Model angelegt hat um die members (Mitarbeiter) zu verwalten, in mein Member-Model übernommen und entsprechend angepasst. Gleiches gilt auch für das TCA der Members (hier habe ich die Eigenschaft "companies" ergänzt mit den entsprechenden Änderungen). Auf den ersten Blick funktioniert es auch, dass ich im BE beim Bearbeiten der Mitarbeiter eine Firmenauswahl erhalte und die Zuordnung in der Zuordnungstabelle gespeichert wird. Der Haken: die Zuordnungstabelle heißt tx_test_company_member_mm - entsprechend muss in die Spalte uid_local die uid der Firma und in uid_foreign die uid des Mitarbeiters. Wenn ich eine Firma bearbeite und einen Mitarbeiter hinzufüge, funktioniert das auch. Wenn ich aber einen Mitarbeiter bearbeite und eine Firma hinzufüge, speichert Typo3 in uid_local die uid des Mitarbeiters, was natürlich genau falsch herum ist. Wenn ich dieses Problem beheben kann, kann ich theoretisch die Betrachtung aus zwei Seiten für n:m-Beziehungen realisieren ohne die Zuordnungstabelle als eigenes Objekt anlegen zu müssen. Ich vermute mal, dass man in der Configuration/TCA/Member.php irgendwo in der Definition der Eigenschaft "companies" angeben kann, dass die uid des Mitarbeiters in der Spalte "uid_foreign" gespeichert werden soll. Hast du hier vielleicht eine Idee, wie ich das hinbekomme? Meine Definition für "companies" im TCA der Member sieht aktuell wie folgt aus:
'companies' => array(
'exclude' => 0,
'label' => 'LLL:EXT:test/Resources/Private/Language/locallang_db.xlf:tx_test_domain_model_member.companies',
'config' => array(
'type' => 'select',
'foreign_table' => 'tx_test_domain_model_company',
'MM' => 'tx_test_company_member_mm',
'size' => 10,
'autoSizeMax' => 30,
'maxitems' => 9999,
'multiple' => 0,
'wizards' => array(
'_PADDING' => 1,
'_VERTICAL' => 1,
'edit' => array(
'type' => 'popup',
'title' => 'Edit',
'script' => 'wizard_edit.php',
'icon' => 'edit2.gif',
'popup_onlyOpenIfSelected' => 1,
'JSopenParams' => 'height=350,width=580,status=0,menubar=0,scrollbars=1',
),
'add' => Array(
'type' => 'script',
'title' => 'Create new',
'icon' => 'add.gif',
'params' => array(
'table' => 'tx_test_domain_model_company',
'pid' => '###CURRENT_PID###',
'setValue' => 'prepend'
),
'script' => 'wizard_add.php',
),
),
),
),
Wäre super, wenn man das so lösen könnte!