Moin.
Ich bin mit meinem "Extbase"-Latein am Ende... Ich habe zwei Objekte, die sich bis auf einige Unterschiede recht ähnlich sind und die ich deshalb von einer gemeinsamen Basisklasse ableite.
Dies möchte ich in Extbase / der Datenbank mittels "Single Table Inheritance (STI)" abbilden. Über das Listenmodul im Backend funktioniert das Anlegen der Objekte einwandfrei und ich kann in der entsprechenden Tabelle in der DB auch wunderbar sehen, dass die Daten dort korrekt ankommen und unter dem richtigen "record_type" gespeichert werden.
Im Frontend funktioniert das leider nicht. Ich habe mittels XDebug ziemlich "tief" in den Extbase-Code hineingeschaut und konnte dabei sehen, dass - auch wenn ich die Details wahrscheinlich nicht ganz verstanden habe - das jeweilige Objektaggregat korrekt aus dem Formular zusammengebaut und an so auch an die Kaskaden von "Persistenzfunktionen" im Extbase weitergereicht wird.
Nur leider steht am Ende des Vorgangs nichts in der Datenbank. Eine Fehlermeldung oder Exception gibt's aber leider auch nirgends.
Ich bin für jeden Hinweis dankbar. Was habe ich übersehen? Was falsch konfiguriert? Wo ist mein evtl. Denkfehler? Ich seh's einfach nicht...
Beste Grüße aus Kiel,
der Hauke
Anbei der Code von dem ich denke, dass er relevant ist...
Das ist die Basisklasse meiner "Firmen-" und "Filial-" Klassen:
class Tx_Gpqg_Domain_Model_BaseFirma extends Tx_Gpqg_Domain_Model_BaseModel
{
/**
* @var string
* @validate StringLength(minimum=3, maximum=200)
*/
protected $name;
/**
* @var Tx_Gpqg_Domain_Model_Adresse
* @validate GenericObject
*/
protected $adresse;
/**
* @var string
* @validate StringLength(minimum=3, maximum=20)
*/
protected $telefon;
/**
* @var string
* @validate StringLength(maximum=20)
*/
protected $fax;
/**
* @var string
* @validate EmailAddress()
*/
protected $email;
/**
* @var string
*/
protected $www;
/**
* @var Tx_Gpqg_Domain_Model_Person
*/
protected $fachlicheLeitung;
/**
* @var string
*/
protected $ikNummern;
/**
* Setzt den Firmennamen
*
* @param string $name Firmenname
* @return void
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Holt den Firmennamen
*
* @return string Name der Firma
*/
public function getName()
{
return $this->name;
}
/**
* Setzt die Adresse
*
* @param Tx_Gpqg_Domain_Model_Adresse $adresse Adresse der Firma
* @return void
*/
public function setAdresse(Tx_Gpqg_Domain_Model_Adresse $adresse)
{
$this->adresse = $adresse;
}
/**
* Holt die Adresse
*
* @return Tx_Gpqg_Domain_Model_Adresse Adresse der Firma
*/
public function getAdresse()
{
return $this->adresse;
}
/**
* Setzt die Telefonnummer
*
* @param string $telefon Telefonnummer
* @return void
*/
public function setTelefon($telefon)
{
$this->telefon = $telefon;
}
/**
* Holt die Telefonnummer
*
* @return string Telefonnummer
*/
public function getTelefon()
{
return $this->telefon;
}
/**
* Setzt die Faxnummer
*
* @param string $fax Faxnummer
* @return void
*/
public function setFax($fax)
{
$this->fax = $fax;
}
/**
* Holt die Faxnummer
*
* @return void
*/
public function getFax()
{
return $this->fax;
}
/**
* Setzt die Emailadresse
*
* @param string $email Emailadresse
* @return void
*/
public function setEmail($email)
{
$this->email = $email;
}
/**
* Holt die Emailadresse
*
* @return string Emailadresse
*/
public function getEmail() {
return $this->email;
}
/**
* Setzt die Internetadresse
*
* @param string $www Internetadresse
* @return void
*/
public function setWww($www)
{
$this->www = $www;
}
/**
* Holt die Internetadresse
*
* @return string Internetadresse
*/
public function getWww()
{
return $this->www;
}
/**
* Setzt die fachliche Leitung
*
* @param Tx_Gpqg_Domain_Model_Person $fachlicheLeitung Fachliche Leitung der Firma
* @return void
*/
public function setFachlicheLeitung(Tx_Gpqg_Domain_Model_Person $fachlicheLeitung)
{
$this->fachlicheLeitung = $fachlicheLeitung;
}
/**
* Holt die fachliche Leitung
*
* @return Tx_Gpqg_Domain_Model_Person Fachliche Leitung der Firma
*/
public function getFachlicheLeitung()
{
return $this->fachlicheLeitung;
}
/**
* Setze IK-Nummern
*
* @param string $ikNummern IK Nummern
* @return void
*/
public function setIkNummern($ikNummern)
{
$this->ikNummern = $ikNummern;
}
/**
* Holt die IK Nummern
*
* @return string IK Nummern
*/
public function getIkNummern()
{
return $this->ikNummern;
}
/**
* @return string Name der Firma
*/
public function __toString()
{
return $this->name;
}
}
Die beiden abgeleiteten Klassen sind folgendermaßen aufgebaut:
class Tx_Gpqg_Domain_Model_Firma extends Tx_Gpqg_Domain_Model_BaseFirma
{
/**
* @var Tx_Gpqg_Domain_Model_Person
*/
protected $geschaeftsfuehrer;
/**
* Setzt den Geschäftsführer
*
* @param Tx_Gpqg_Domain_Model_Person $geschaeftsfuehrer Geschäftsführer der Firma
* @return void
*/
public function setGeschaeftsfuehrer(Tx_Gpqg_Domain_Model_Person $geschaeftsfuehrer)
{
$this->geschaeftsfuehrer = $geschaeftsfuehrer;
}
/**
* Holt den Geschaeftsfuehrer
*
* @return Tx_Gpqg_Domain_Model_Person Geschäftsführer der Firma
*/
public function getGeschaeftsfuehrer()
{
return $this->geschaeftsfuehrer;
}
}
class Tx_Gpqg_Domain_Model_Filiale extends Tx_Gpqg_Domain_Model_BaseFirma
{
/**
* @var Tx_Gpqg_Domain_Model_Firma
*/
protected $firma;
/**
* Setzt die Hauptstelle einer Niederlassung
*
* @param Tx_Gpqg_Domain_Model_Firma $firma
* @return void
*/
public function setFirma(Tx_Gpqg_Domain_Model_Firma $firma)
{
$this->firma = $firma;
}
/**
* Holt die Hauptstelle einer Niederlassung
*
* @return Tx_Gpqg_Domain_Model_Firma
*/
public function getFirma()
{
return $this->firma;
}
}
Die Konfiguration der Tabellen / des TCA sieht so aus:
ext_tables.php
$TCA['tx_gpqg_domain_model_basefirma'] = array(
'ctrl' => array(
'title' => 'Firma / Filiale',
'label' => 'name',
'type' => 'record_type',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'dynamicConfigFile' => $ePath . '/Configuration/TCA/BaseFirma.php',
)
);
Die TCA Konfiguration
$TCA['tx_gpqg_domain_model_basefirma'] = array(
'ctrl' => $TCA['tx_gpqg_domain_model_basefirma']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'name, adresse, telefon, fax, email,
www, ik_nummern, firma',
),
'types' => array(
'Tx_Gpqg_Domain_Model_Firma' => array('showitem' => 'record_type, name, adresse;;1;;, telefon, fax, email,
geschaeftsfuehrer, fachliche_leitung, ik_nummern'),
'Tx_Gpqg_Domain_Model_Filiale' => array('showitem' => 'record_type, firma, name, adresse;;1;;, telefon, fax, email,
fachliche_leitung, ik_nummern'),
),
'columns' => array(
'name' => array(
'label' => 'Firmenname',
'config' => array(
'type' => 'input',
'size' => 50,
'max' => 200,
'eval' => 'trim,required',
),
),
'adresse' => array(
'label' => 'Adresse',
'config' => array(
'type' => 'select',
'foreign_table' => 'tx_gpqg_domain_model_adresse',
'foreign_table_where' => 'AND `tx_gpqg_domain_model_adresse`.`firma` = ###THIS_UID###',
),
),
'telefon' => array(
'label' => 'Telefon',
'config' => array(
'type' => 'input',
'size' => 10,
'max' => 20,
'eval' => 'trim,required',
),
),
'fax' => array(
'label' => 'Fax',
'config' => array(
'type' => 'input',
'size' => 10,
'max' => 20,
'eval' => 'trim',
),
),
'email' => array(
'label' => 'Email',
'config' => array(
'type' => 'input',
'size' => 25,
'max' => 50,
'eval' => 'trim,required',
),
),
'www' => array(
'label' => 'WWW',
'config' => array(
'type' => 'input',
'size' => 25,
'max' => 50,
'eval' => 'trim',
),
),
'geschaeftsfuehrer' => array(
'label' => 'Geschäftsführer',
'config' => array(
'type' => 'select',
'foreign_table' => 'tx_gpqg_domain_model_person',
'foreign_table_where' => 'AND `tx_gpqg_domain_model_person`.`typ` = \'GESCHAEFTSFUEHRER\'',
),
),
'fachliche_leitung' => array(
'label' => 'Fachliche Leitung',
'config' => array(
'type' => 'select',
'foreign_table' => 'tx_gpqg_domain_model_person',
'foreign_table_where' => 'AND `tx_gpqg_domain_model_person`.`typ` = \'FACHLICHE_LEITUNG\'',
),
),
'ik_nummern' => array(
'label' => 'IK Nummern',
'config' => array(
'type' => 'text',
'cols' => 20,
'rows' => 4,
'eval' => 'required',
),
),
'firma' => array(
'label' => 'Hauptstelle',
'config' => array(
'type' => 'select',
'maxitems' => 1,
'foreign_table' => 'tx_gpqg_domain_model_basefirma',
'foreign_table_where' => 'AND `tx_gpqg_domain_model_basefirma`.`record_type` = \'Tx_Gpqg_Domain_Model_Firma\'',
'items' => array(
array('Keine Hauptstelle zugewiesen!', 0)
),
),
),
'record_type' => array(
'label' => 'Firma / Filiale',
'config' => array(
'type' => 'select',
'items' => array(
array('Firma', 'Tx_Gpqg_Domain_Model_Firma'),
array('Filiale', 'Tx_Gpqg_Domain_Model_Filiale'),
),
'default' => 'Tx_Gpqg_Domain_Model_Firma',
),
),
),
'palettes' => array(
'1' => array('showitem' => 'strasse, hausnummer, plz, land')
),
);
Das SQL für die gemeinsame Tabelle sieht so aus:
CREATE TABLE tx_gpqg_domain_model_basefirma (
uid int(11) unsigned NOT NULL auto_increment,
pid int(11) DEFAULT '0' NOT NULL,
record_type varchar(255) DEFAULT '' NOT NULL,
user int(11) unsigned DEFAULT '0' NOT NULL,
name varchar(200) DEFAULT '' NOT NULL,
adresse int(11) DEFAULT '0' NOT NULL,
telefon varchar(20) DEFAULT '' NOT NULL,
fax varchar(20) DEFAULT '' NOT NULL,
email varchar(50) DEFAULT '' NOT NULL,
www varchar(50) DEFAULT '' NOT NULL,
geschaeftsfuehrer int(11)DEFAULT '0' NOT NULL,
fachliche_leitung int(11) DEFAULT '0'NOT NULL,
ik_nummern text DEFAULT '' NOT NULL,
firma int(11) DEFAULT '0' NOT NULL,
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
crdate int(11) unsigned DEFAULT '0' NOT NULL,
deleted tinyint(4) unsigned DEFAULT '0' NOT NULL,
hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
access_group int(11) DEFAULT '0' NOT NULL,
PRIMARY KEY(uid),
KEY parrent (pid)
);
Für Single Table Inheritance soll man ja noch per TypoScript Einstellungen vornehmen. Das sieht bei mir so aus:
Allerdings bin ich kein Typo3 Spezialist, weshalb mir nicht ganz klar ist, an welcher Stelle das eingefügt werden muss. Ich habe das an die Seite "geklemmt", in der auch das Modul installiert ist.
config.tx_extbase.persistence.classes {
Tx_Gpqg_Domain_Model_Firma {
mapping {
tableName = tx_gpqg_domain_model_basefirma
recordType = Tx_Gpqg_Domain_Model_Firma
}
}
Tx_Gpqg_Domain_Model_Filiale {
mapping {
tableName = tx_gpqg_domain_model_baseFirma
recordType = Tx_Gpqg_Domain_Model_Filiale
}
}
}
Im entsprechenden Controller (z.B. Firma) wird passiert nach folgender Action nichts. Es wird nichts in der Datenbank abgelegt, noch wird eine Fehlermeldung ausgegeben:
Das $firma Objekt ist jedoch korrekt befüllt und enthält alle zuvor im Formular eingegebenen Daten.
/**
* @param Tx_Gpqg_Domain_Model_Firma $firma
* @return void
*/
public function createAction(Tx_Gpqg_Domain_Model_Firma $firma)
{
$firma->setUser($this->frontendUser);
$firma->getAdresse()->setFirma($firma);
$firma->getGeschaeftsfuehrer()->setFirma($firma);
$firma->getFachlicheLeitung()->setFirma($firma);
$this->firmaRepository->add($firma);
$this->redirect('index', 'Firma');
}