Connections

Connecting signals to slots

The Siglot class offers various static methods for connecting a signal to a slot. These methods are named connect<N>, where <N> represents the number of parameters of the signal. The numbering starts from connect0 for signals without parameters and goes up to connect5. In all cases, the first parameter is the signal and the second is the slot. Both are referenced using first-class callable syntax.

Siglot::connect0($button->clicked(...), $receiver->onClick(...));
Siglot::connect1($editor->nameChanged(...), $receiver->onNewName(...));

It is highly discouraged to use something else than first-class callable syntax to connect signals and slots, even if it is technically possible. Refer to the Advanced section for more details.

  • The number of parameters expected by a slot may be less than the number of parameters provided by the signal. Any extra parameters are ignored, similar to regular PHP functions.
  • A signal can be linked to multiple slots, but the order in which they are called is not guaranteed.
  • A slot can be connected to multiple signals.

Chaining signals

It is also possible to chain signals together, using the Siglot::chain<N> methods, where <N> represents the number of parameters of the input signal. When a signal is triggered, chained signals will also be triggered with the same parameters.

Siglot::chain0($button->clicked(...), $component->onSaveButtonClicked(...));
Siglot::chain1($text->changed(...), $component->onTextChanged(...));
  • It is possible for a destination signal to expect fewer parameters than the input signal provides. Any extra parameters are ignored, similar to regular PHP functions.
  • A signal can be chained to multiple signals, but the order in which they are called is not guaranteed.
  • Chaining is compatible with regular slot connections.

Visibility

Signals and slots are regular PHP methods that you can define with any visibility. However, the visibility affects the scope from which signals and slots can be connected. For example, a class can connect a public signal to one of its private slots, or it can connect one of its private signals to a public slot of another class. This is because accessibility is determined when the first-class callable syntax is used, not at execution.

class MyReceiver {
    public function __construct(MyEmitter $emitter) {
        Siglot::connect0($emitter->signal(...), $this->myPrivateSlot(...));
    }

    private function myPrivateSlot(): void {
        // ...
    }
}

If you are not using first-class callable syntax, scope resolution may be performed in Siglot’s code, which will most likely result in failure.

Connection lifetime

Once an emitter or a receiver is destroyed, all connections involving it are automatically removed. It’s important to note that Siglot does not retain any references to connected objects in order to avoid interfering with PHP’s garbage collector. This means you cannot depend on the existence of a connection to keep an object alive.

function attachSignalLogger(MyEmitter $emitter): void {
    $logger = new class() {
        public function log(): void {
            echo "Signal received!\n";
        }
    };
    
    Siglot::connect0($emitter->signal(...), $logger->log(...));
    // ⚠️ $logger is destroyed here !!!
    // Nothing will be printed when the signal is emitted outside of this function.
}