Signals and slots are a possibility within TYPO3 to extend the functionality of an object. In this article I explain the theoretical basics and show you the practical details.
Signal – slot basics
Signals and slots is a software development pattern, where two objects communicate with each other. One object fires a signal. Any other object, which implements a slot, receives that signal and can react to it. Regarding software theory, this is an implementation of the observer pattern.
For TYPO3 this is the third possibility for extending functionality besides hooks (old) and XClasses (very old).
Basically three steps are required:
- create the signal
- create the slot
- register the slot
In the fourth chapter I will write about how to pass values to and from a slot.
Create the signal
The first step is to build the signal. It is created in the class, which should trigger another action. It can be put anywhere in the code and is just two lines long.
$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(Dispatcher::class); $signalSlotDispatcher->dispatch(CLASS, 'DoSomeThing', [$customValue1, $customValue2]);
The first line creates the class for the dispatcher. The second line dispatches the signal. The dispatch needs at least two arguments: The emitting class and the name of the signal. The name of the signal is an arbitrary string. The third (optional) argument takes the variables, which are passed to the slot. Further details are described in the last chapter.
Create the slot
The slot is a class, that receives the signal and takes the arguments. It does something with the data and can return a result.
The class should reside in the directory your_extension/Classes/Slot/
. A very basic implementation looks like this:
<?php namespace YourNameSpace\YourExtension\Slot; class DoSomeThingSlot { public function doSomeThingFunction($customValue1, $customValue2) { /* Do something */ } }
Register the slot
The last step is to register the slot. This is done in the file ext_localconf.php
. It connects the slot to the signal. Like the creation of the signal it takes also only two lines of code:
$signalSlotDispatcher = TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(Dispatcher::class); $signalSlotDispatcher->connect( \Name\Space\Signal\SignalClassName::class, 'DoSomeThing', YourNameSpace\YourExtension\Slot\DoSomeThingSlot::class, 'doSomeThingFunction' );
The connect function needs four arguments. The first argument is the class that contains the signal. The second argument is the name of the signal. The third one is the name of the class, that contains the slot and the fourth is the function name, which is called to process the signal.
Passing and returning values
As already said, the third argument of the signal dispatcher is an array and used to passed variables to the slot. An element of this array can be of any type: Scalar, array or object. For passing and returning values there are three possibilities: Nothing, pass by reference, pass by value.
void
This is the most simple type. It was in the example above. Values can be passed to the slot, but nothing is modified within the original data or returned. This can be useful to implement logging function, for example.
By reference
Values in the array can be passed by reference. So the variables in the array must be prepended by an ampersand “&” …. ok, you know that already ;-) But … if the passed variable is not an object, the function signature of the slot must also contain an ampersand. If it is not an object, the changed values might get lost somewhere. [I have no prove of this “bug”, but rumors say so (TM) ]
A second temptation could be to pass the complete object, which is sending the signal, as a reference to the slot. This is a very bad idea, because nearly everything could be done with the instance, without a chance to validate the changes.
This is where the third option comes in: Passing and returning by value.
Returning values
In all examples, I found on the web, regarding this topic, variables were always passed and modified by reference. But it is also possible to pass them by value. The function in the slot must return an array. This array must contain the same number of element in the same order, as they were passed to the slots. The returned values can then be validated and evaluated further.
Conclusion
I hope, that this post was interesting for you. If so or if you know somebody, who could profit from it, please share this post via your favorite social network. For your convenience I added some share buttons at the end of this page.
Credits
I want to thank my supporters via patreon.com, who make this blog post possible:
- Lime Flavour
- Daniel Tondera
If you appreciate my blog and want to support me, you can say “Thank You!”. Find out the possibilities here:
I found the blog post image on unsplash . It was published by Carlos Alberto Gómez Iñiguez (@iniguez) under the Unsplash license. I modified it myself using pablo on buffer.
4
Hallo Marcus
Danke für den sehr interessanten Artikel.
Wollte dies umsetzen, habe deinen Code verwendet.
Die Definition von $signalSlotDispatcher führt zu einem kompletten Absturz von Typo3.
Abschnitt: Create the signal
Slot Dispatcher (Zeile 1)
$signalSlotDispatcher = GeneralUtility::makeInstance(Dispatcher::class);
Bei einem solche Code-Schnippsel bräuchte es dann doch den ganzen Pfad.
$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class);
Gruss Päde
Thanks for your feedback.
Yes, you are right. But you can also use a “use” statement at the beginning of the class.
I will adaot the code snippet.