Schlagwort-Archiv: Typo3

Kommagetrennte Liste in Datenbanken…

Prominentes Beispiel für kommagetrennte Listen auf Datenbank-Ebene ist Typo3. Dort werden 1:N-Relationen auch durch eine kommagetrennte Liste repräsentiert. Es gibt dann z. B. eine Spalte books in einem Datensatz author. In dieser Spalte werden kommagetrennt die UIDs der referenzierten Datensätze (Bücher) hinterlegt.

Die Frage ist nun, wie über solch eine Spalte Abfragen durchgeführt werden können. Beispielsweise möchte man alle Autoren eines bestimmten Buches abfragen…

Die Lösung ist unter MySQL die String-Funktion FIND_IN_SET. Sie nimmt zwei Parameter entgegen:

mysql> SELECT FIND_IN_SET('b','a,b,c,d');
        -> 2

 

Extbase: update funktioniert nicht

Während der Entwicklung einer Extension unter Typo 4.7.4 habe ich mich strikt an die Blog Example Extension gehalten. Ich habe brav meine ext_table.sql angelegt, die ext_tables.php angepasst und das dort referenzierte “dynamicConfigFile” akribisch ergänzt und kontrolliert.

Im Typo3 Backend kann ich die Datensätze ohne Probleme anlegen, bearbeiten und löschen.

Für das Frontend habe ich ein Model und ein Repository angelegt. Nichts kompliziertes, da ich mit keinen Relationen zu tun habe. Anschließend ging es an den Controller. Ich habe natürlich vorher die ext_localconf.php angepasst:

Tx_Extbase_Utility_Extension::configurePlugin(
    $_EXTKEY,
    'Navigation',
    array(
        'Navigation' => 'list,new,create,edit,update,delete'
    ),
    // non-cacheable actions
    array(
        'Navigation' => 'list,new,create,edit,update,delete'
    )
);

Dann ging es im Controller weiter. Ich habe die list-Action implementiert – geht. Ich habe die new und die create-Aktion implementiert – geht. Auch die delete-Action macht keine Probleme. Nun die edit- und update-Action…. geht nicht!!!

Diese sieht so aus:

/**
 * Updates an existing navigation entity
 *
 * @param Tx_MyExtension_Domain_Model_Navigation $navigation
 * @return void
 */
 public function updateAction(Tx_MyExtension_Domain_Model_Navigation $navigation)
 {
   $this->navigationRepository->update($navigation);
   $this->addFlashMessage('update'); // see blog_example
   $this->redirect('list');
 }

Erst dachte ich: Wahrscheinlich kommen falsche Werte an. Ein Ausgabe über folgende Funktion sollte mich belehren:

Tx_Extbase_Utility_Debugger::var_dump($navigation);

Das Model hatte alle Werte korrekt aus dem Request übernommen. Also hab ich mir die update-Methode genauer angeschaut. Diese befindet sich in der Klasse Tx_Extbase_Persistence_Repository und ruft ihrerseits die replace-Methode der selben Klasse auf. In dieser Funktion wird vom Persistence Manager das Backend geholt und anschließend wird die Methode replaceObject aufgerufen:

/* @var Tx_Extbase_Persistence_Backend */
$backend = $this->persistenceManager->getBackend();
...
$backend->replaceObject($existingObject, $newObject);

Anschließend kommt eine if/elseif-Konstrukt:

if ($this->removedObjects->contains($existingObject)) {
  ..
} 
elseif ($this->addedObjects->contains($existingObject)) 
{
  ...
}

Genau dort liegt das Problem. Keine der beiden Bedingungen greift und somit passiert…… gar nix. Ich bin nach etwas längerem Suchen darauf gestoßen, dass das ursprüngliche Objekt nicht in der Identity Map enthalten ist. Leider habe ich den Grund dafür bisher nicht gefunden. Als Workaround habe ich die updateAction-Methode leicht angepasst:

/**
 * Updates an existing navigation entity
 *
 * @param Tx_MyExtension_Domain_Model_Navigation $navigation
 * @return void
 */
 public function updateAction(Tx_MyExtension_Domain_Model_Navigation $navigation)
 {
   // FIXME: updateAction do not work, I don't no why...
   /* @var $persistenceManager Tx_Extbase_Persistence_Manager */
   $persistenceManager=$this->objectManager->get('Tx_Extbase_Persistence_Manager');
   $backend=$persistenceManager->getBackend();
   $identityMap=$backend->getIdentityMap();
   $identityMap->registerObject($navigation, $navigation->getUid());
   // FIXEND
 
   $this->navigationRepository->update($navigation);
   $this->addFlashMessage('update'); // see blog_example
   $this->redirect('list');
 }

Vielleicht stoßt ja ein Typo3-Guru auf diesen Blogeintrag und hat einen Tipp für mich… ansonst hilft es vielleicht dem einen oder anderen, der dieses Problem auch hat.

 Update 26.09.2012:

Der Fix oben funktioniert leider nur, wenn jemand im Backend angemeldet ist. Warum das nicht die remove- bzw. die add-Methode betrifft, kann ich leider nicht sagen. Ich habe für mich im Repository die update-Methode überschrieben. Um die Daten in die Datenbank zu schreiben verwende ich dort die Methode

$GLOBALS['TYPO3_DB']->exec_UPDATEquery('table', 'uid='.$uid, $hash);

 

Frontend-Benutzer in Extbase abfragen

Meiner Meinung nach ist das Abrufen eines Frontend-Benutzers innerhalb Extbase (Typo3 Version 4.7.4) etwas umständlich. Deshalb ist das hier kurz dokumentiert:

TypoScript

plugin.tx_blogexample 
  persistence {
    Tx_Extbase_Domain_Model_FrontendUser {
      mapping {
        tableName = fe_users
        recordType = Tx_Extbase_Domain_Model_FrontendUser
      }
    }
  }
}

Backend

Im Backend muß der Datensatztyp auf Tx_Extbase_Domain_Model_FrontendUser gesetzt werden, sonst wird kein Datensatz zurückgeliefert.

Einstellungen im Backend: fe_user
Einstellungen im Backend: fe_user

Controller

Im Controller erhalten wir das Repository über Dependency Injection:

 /**
  * @var Tx_Extbase_Domain_Repository_FrontendUserRepository
  * @inject
  */
 protected $frontendUserRepository;

Das Model erhalten wir anschließend durch eine einfache Abfrage:

$user=$GLOBALS['TSFE']->fe_user->user; 
$this->user=$this->frontendUserRepository->findByUid($user['uid']);

Vorher sollte man ggf. noch abfragen, ob wirklich ein Frontendbenutzer angemeldet ist.

Dependency Injection in Typo3 4.7

Bis Typo3 Version 4.6 konnte man ein Repository über eine Funktion im Controller erhalten:

/**
  * @param Tx_ExampleUser_Domain_Repository_Navigation
  */
  public function injectNavigationRepository(
    Tx_ExampleUser_Domain_Repository_Navigation $repository)
  {
    $this->navigationRepository = $repository;
  }

Seit Version 4.7 geht das noch komfortabler:

 /**
   * @var Tx_ExampleUser_Domain_Repository_Navigation
   * @inject
   */
  protected $navigationRepository;

Typo3 Debug

Die Funktion

t3lib_div::debug()

ist seit Typo3 4.7 entfernt worden.

Die neue Funktion heißt nun

t3lib_utility_Debug::debug($var)

und nimmt die gleichen Parameter entgegen, wie die alte Funktion. Es gibt aber auch (ab Version 4.7) die Möglichkeit über den Backport des Flow3 Debuggers:

Tx_Extbase_Utility_Debugger::var_dump($var);

TYPO3 4.7.4 – Sorry, you didn’t have proper permissions to perform this change.

Der Tip von Martin Hesse für Typo3 Version 4.7.2 ist auch für Version 4.7.4 noch gültig.

Die Fehlermeldung kommt, wenn man TemplaVoilá verwendet und versucht ein Seitenelement einzufügen.

Um diesen Fehler zu umgehen könnt ihr entweder die Listen-Ansicht verwenden, oder ihr führt folgenden SQL-Befehl aus:

ALTER TABLE pages ADD t3ver_swapmode tinyint(4) NOT NULL default '0'