Extbase - Signal Slots: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
Zeile 11: Zeile 11:
 
</pre>
 
</pre>
  
 +
== Einführung ==
 +
Quelle: (2015-6)
 +
 +
Genauso wie der Hook besteht das Signal/Slot Pattern aus zwei Bausteinen. Auf der einen Seite sind die '''Slots (Connector, Listener)''' und auf der anderen Seite die '''Signale (Dispatcher)'''. Beide Funktionalität sind '''über die Klasse “Tx_Extbase_SignalSlot_Dispatcher” erreichbar''', welche wir uns zuerst erstellen müssen. Dies geht entweder über Dependency Injection (z.B. im Controller):
 +
 +
<syntaxhighlight lang="php">
 +
/**
 +
* @var Tx_Extbase_SignalSlot_Dispatcher
 +
*/ 
 +
protected $signalSlotDispatcher; 
 +
 
 +
/**
 +
* @param Tx_Extbase_SignalSlot_Dispatcher $signalSlotDispatcher
 +
*/ 
 +
public function injectSignalSlotDispatcher(Tx_Extbase_SignalSlot_Dispatcher $signalSlotDispatcher) { 
 +
    $this->signalSlotDispatcher = $signalSlotDispatcher; 
 +
 +
</syntaxhighlight>
 +
oder aber auch über einfaches erstellen der Instanz:
 +
 +
<syntaxhighlight lang="php">
 +
$this->signalSlotDispatcher = t3lib_div::makeInstance('Tx_Extbase_Object_Manager')->get('Tx_Extbase_SignalSlot_Dispatcher');
 +
<syntaxhighlight lang="php">
 +
Im Anschluss verfügt ihr über ein “Tx_Extbase_SignalSlot_Dispatcher” Objekt mit dem ihr nun Signale senden oder Slots registrieren könnte. Im Folgenden nun die beiden Sichten, welche möglich sind.
 +
Dispatch / Signal
 +
 +
Beispiel: Am Ende eurer Action stellt ihr alle nötigen Variablen der View bereit. Nun befindet ihr euch an einer Stelle, welcher gern erweitert wird, weshalb ihr euch für ein “Signal” entscheidet. Das Signal wird über den Signal/Slot-Dispatcher getriggert und kann von anderen Extensions benutzt werden, um die eigene Action zu ergänzen. Hier der Beispielcode:
 +
<syntaxhighlight lang="php">
 +
$this->signalSlotDispatcher->dispatch(__CLASS__, 'beforeRenderView', array($data, $this)); 
 +
</syntaxhighlight>
 +
Die Funktion hat drei Parameter “Klassenname”, “Signalname” und “Parameter”. '''Der Klassennamen ist ähnlich einem Namespace zu betrachten. “__CLASS__” macht hier meistens Sinn''' – möglich wäre aber auch “get_class($this)”.
 +
 +
Achtung/Tipp: Letzteres hat einen interessanten Vererbungseffekt, sodass eine vererbte Klasse automatisch andere Signale schickt als die Klasse von der geerbt wurde. Evtl. Tricky, deshalb empfehle ich anfangs “__CLASS__”.
 +
 +
Der Signalname ist frei wählbar und sollte die Position und Funktion beschreiben. Bei den Parametern sollten alle nötigen Parameter übergeben werden, sodass diese von einem Externen gut verarbeitet werden können.
 +
Connect / Slot
 +
 +
Beispiel: Wir haben die Action (oben) gesehen und wollen die von außen (aber auch in der selben Extension wäre es möglich!) bearbeiten. Dazu erstellen wir uns ebenfalls den Signal/Slog-Dispatcher und registrieren eine Callback-Function (Slot / Listener) für das Signal. Hierzu gibt es verschiedene Möglichkeiten:
 +
Anonym mit einem Closure,
 +
 +
<syntaxhighlight lang="php">
 +
$this->signalSlotDispatcher->connect( 
 +
      'Tx_Extension_Controller_NameController', 'beforeRenderView', function($data, $obj) { /* ... */ }, NULL, FALSE 
 +
);
 +
</syntaxhighlight>
 +
eine Methode aus dem aktuellen Objekt oder
 +
<syntaxhighlight lang="php">
 +
$this->signalSlotDispatcher->connect( 
 +
    'Tx_Extension_Controller_NameController', 'beforeRenderView', $this, 'addInformation', FALSE 
 +
); 
 +
</syntaxhighlight>
 +
eine Methode aus einem anderen Objekt.
 +
<syntaxhighlight lang="php">
 +
$this->signalSlotDispatcher->connect( 
 +
    'Tx_Extension_Controller_NameController', 'beforeRenderView', 'Tx_OtherExtension_Controller_NameController', 'addOtherInformation', FALSE 
 +
);
 +
</syntaxhighlight>
 +
Wie ihr seht sind die ersten beiden Parameter identisch zu dem “Signal-Aufruf”. Diese diesen der Identifikation des Signals. Über die beiden folgenden Parameter wird die '''Callback-Funktion''' gesteuert. Der letzte Parameter (welcher hier auf FALSE steht) kann auf TRUE gesetzt werden, wenn ihr in der Slot-Klasse zusätzliche Informationen über das Signal benötigt. Diese stehen dann als erster Parameter in der Zielfunktion zur Verfügung.
 +
 +
Fazit
 +
 +
Ein wirklich schönes Pattern – sauberer und einheitlicher als die “üblichen” Hooks. Gerade bei den Hooks war störend, das viele mit “User”-Functions benutzt werden mussten, weshalb die Klassen mit “user_” beginnen mussten. Das neue Pattern ist leicht zu bedienen und schlank im Einsatz. Felix, Vielen Dank dafür. Weitere Informationen bekommt ihr in der API.
 
=== Beispiel Signal Slot beim löschen eines Datensatzes ausführen ===
 
=== Beispiel Signal Slot beim löschen eines Datensatzes ausführen ===
 
localconf.php
 
localconf.php

Version vom 18. Juni 2015, 14:45 Uhr

Links

http://blog.foertel.com/2011/10/using-signalslots-in-extbase/

Typo3 Backend Signals

in typo3/sysext/extbase/Classes/Persistance/Generic/Backend.php

afterRemoveObject
afterUpdateObject
beforeGettingObjectData
afterGettingObjectData
afterInsertObject

Einführung

Quelle: (2015-6)

Genauso wie der Hook besteht das Signal/Slot Pattern aus zwei Bausteinen. Auf der einen Seite sind die Slots (Connector, Listener) und auf der anderen Seite die Signale (Dispatcher). Beide Funktionalität sind über die Klasse “Tx_Extbase_SignalSlot_Dispatcher” erreichbar, welche wir uns zuerst erstellen müssen. Dies geht entweder über Dependency Injection (z.B. im Controller):

/** 
 * @var Tx_Extbase_SignalSlot_Dispatcher
 */  
protected $signalSlotDispatcher;  
  
/** 
 * @param Tx_Extbase_SignalSlot_Dispatcher $signalSlotDispatcher 
 */  
public function injectSignalSlotDispatcher(Tx_Extbase_SignalSlot_Dispatcher $signalSlotDispatcher) {  
    $this->signalSlotDispatcher = $signalSlotDispatcher;  
}

oder aber auch über einfaches erstellen der Instanz:

$this->signalSlotDispatcher = t3lib_div::makeInstance('Tx_Extbase_Object_Manager')->get('Tx_Extbase_SignalSlot_Dispatcher');
<syntaxhighlight lang="php">
Im Anschluss verfügt ihr über ein “Tx_Extbase_SignalSlot_Dispatcher” Objekt mit dem ihr nun Signale senden oder Slots registrieren könnte. Im Folgenden nun die beiden Sichten, welche möglich sind.
Dispatch / Signal

Beispiel: Am Ende eurer Action stellt ihr alle nötigen Variablen der View bereit. Nun befindet ihr euch an einer Stelle, welcher gern erweitert wird, weshalb ihr euch für ein “Signal” entscheidet. Das Signal wird über den Signal/Slot-Dispatcher getriggert und kann von anderen Extensions benutzt werden, um die eigene Action zu ergänzen. Hier der Beispielcode:
<syntaxhighlight lang="php">
$this->signalSlotDispatcher->dispatch(__CLASS__, 'beforeRenderView', array($data, $this));

Die Funktion hat drei Parameter “Klassenname”, “Signalname” und “Parameter”. Der Klassennamen ist ähnlich einem Namespace zu betrachten. “__CLASS__” macht hier meistens Sinn – möglich wäre aber auch “get_class($this)”.

Achtung/Tipp: Letzteres hat einen interessanten Vererbungseffekt, sodass eine vererbte Klasse automatisch andere Signale schickt als die Klasse von der geerbt wurde. Evtl. Tricky, deshalb empfehle ich anfangs “__CLASS__”.

Der Signalname ist frei wählbar und sollte die Position und Funktion beschreiben. Bei den Parametern sollten alle nötigen Parameter übergeben werden, sodass diese von einem Externen gut verarbeitet werden können. Connect / Slot

Beispiel: Wir haben die Action (oben) gesehen und wollen die von außen (aber auch in der selben Extension wäre es möglich!) bearbeiten. Dazu erstellen wir uns ebenfalls den Signal/Slog-Dispatcher und registrieren eine Callback-Function (Slot / Listener) für das Signal. Hierzu gibt es verschiedene Möglichkeiten: Anonym mit einem Closure,

$this->signalSlotDispatcher->connect(  
      'Tx_Extension_Controller_NameController', 'beforeRenderView', function($data, $obj) { /* ... */ }, NULL, FALSE  
);

eine Methode aus dem aktuellen Objekt oder

$this->signalSlotDispatcher->connect(  
     'Tx_Extension_Controller_NameController', 'beforeRenderView', $this, 'addInformation', FALSE  
);

eine Methode aus einem anderen Objekt.

$this->signalSlotDispatcher->connect(  
     'Tx_Extension_Controller_NameController', 'beforeRenderView', 'Tx_OtherExtension_Controller_NameController', 'addOtherInformation', FALSE  
);

Wie ihr seht sind die ersten beiden Parameter identisch zu dem “Signal-Aufruf”. Diese diesen der Identifikation des Signals. Über die beiden folgenden Parameter wird die Callback-Funktion gesteuert. Der letzte Parameter (welcher hier auf FALSE steht) kann auf TRUE gesetzt werden, wenn ihr in der Slot-Klasse zusätzliche Informationen über das Signal benötigt. Diese stehen dann als erster Parameter in der Zielfunktion zur Verfügung.

Fazit

Ein wirklich schönes Pattern – sauberer und einheitlicher als die “üblichen” Hooks. Gerade bei den Hooks war störend, das viele mit “User”-Functions benutzt werden mussten, weshalb die Klassen mit “user_” beginnen mussten. Das neue Pattern ist leicht zu bedienen und schlank im Einsatz. Felix, Vielen Dank dafür. Weitere Informationen bekommt ihr in der API.

Beispiel Signal Slot beim löschen eines Datensatzes ausführen

localconf.php

$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
    'TYPO3\CMS\Extbase\Object\ObjectManager'
)->get(
    'TYPO3\CMS\Extbase\SignalSlot\Dispatcher'
);
$signalSlotDispatcher->connect(
    'TYPO3\CMS\Extbase\Persistence\Generic\Backend',
    'afterRemoveObject',
    'Vendor\MxExtension\Classes\Slots\MyAfterRemoveObjectSlot',
    'myAfterRemoveObjectMethod'
);

im Slotpfad (siehe oben .../myext/Classes/Slots/

namespace Vendor\MxExtension\Slots;
class MyAfterRemoveObjectSlot {
    public function myAfterRemoveObjectMethod($object) {
         // do something
    }
}