Oihana PHP System

Signal implements Signaler

A fast and flexible signal/slot implementation for event-driven programming.

This class provides a robust observer pattern implementation with priority-based execution, auto-disconnect capability, and support for both callable functions and Receiver objects. It is ideal for event-driven architectures and decoupled communication between components.

Features:

  • Priority-based receiver execution (higher priority executes first)
  • Auto-disconnect for one-time listeners
  • Type-safe receiver management
  • Efficient sorting and execution order
  • Supports both object receivers implementing Receiver and PHP callables

WeakReferences are used for object receivers to allow proper garbage collection without preventing objects from being destroyed.

Tags
example

Basic usage with callables and Receiver objects

use oihana\signals\Signal;
use oihana\signals\Receiver;

// Define a Receiver class
class NotificationHandler implements Receiver
{
    public function receive( mixed ...$values ) :void
    {
        echo 'Notification: ' . implode(', ', $values) . PHP_EOL;
    }
}

// Create receivers
$logger = function( mixed ...$values )
{
    echo 'Log: ' . implode(', ', $values) . PHP_EOL;
};

$handler = new NotificationHandler();

// Setup signal
$signal = new Signal();

// Connect with different priorities
$signal->connect( $logger  , priority: 10 ); // Executes first
$signal->connect( $handler , priority: 5 ); // Executes second

// Emit values to all connected receivers
$signal->emit( 'User logged in', 'user123' );

// One-time listener
$signal->connect
(
    fn() => echo 'First emit only!' . PHP_EOL,
    autoDisconnect: true
);
example

Advanced usage with priority and auto-disconnect

$signal = new Signal();

// High priority handler (executes first)
$signal->connect
(
    fn($msg) => echo "URGENT: $msg" . PHP_EOL,
    priority: 100
);

// One-time handler (disconnects after first emit)
$signal->connect
(
    fn($msg) => echo "Initialization: $msg" . PHP_EOL,
    priority: 50,
    autoDisconnect: true
);

// Normal priority handler
$signal->connect
(
    fn($msg) => echo "Info: $msg" . PHP_EOL
);

// First emit - all three handlers execute
$signal->emit('System started');

// Second emit - only two handlers execute (auto-disconnect removed one)
$signal->emit('Processing data');
author

Marc Alcaraz (ekameleon)

since
1.0.0

Table of Contents

Interfaces

Signaler

Constants

RECEIVE  = 'receive'
The method name used when calling Receiver objects.

Properties

$length  : int
The number of currently connected receivers.
$throwable  : bool
Indicates whether exceptions from receivers are propagated.
$receivers  : array<string|int, SignalEntry>
Internal storage for connected receivers.

Methods

__construct()  : mixed
Creates a new Signal instance.
connect()  : bool
Connects a receiver to this signal.
connected()  : bool
Checks if any receivers are connected to this signal.
disconnect()  : bool
Disconnects one or all receivers from this signal.
emit()  : void
Emits a signal, calling all connected receivers with the provided values.
hasReceiver()  : bool
Checks if a specific receiver is connected to this signal.
toArray()  : array<string|int, callable>
Returns an array of all connected receivers.

Constants

RECEIVE

The method name used when calling Receiver objects.

public mixed RECEIVE = 'receive'

Properties

$length read-only virtual

The number of currently connected receivers.

public int $length

Read-only property that returns the count of active receivers.

Tags
example
$signal = new Signal();
echo $signal->length; // 0

$signal->connect( fn() => echo 'test' );
echo $signal->length; // 1
Hooks
public int get

$throwable

Indicates whether exceptions from receivers are propagated.

public bool $throwable = true

$receivers

Internal storage for connected receivers.

protected array<string|int, SignalEntry> $receivers

Each element is a SignalEntry object containing the receiver callable, its priority, and auto-disconnect flag.

Methods

__construct()

Creates a new Signal instance.

public __construct([array<string|int, callable|Receiver>|null $receivers = null ][, bool $throwable = true ]) : mixed
Parameters
$receivers : array<string|int, callable|Receiver>|null = null

Optional array of initial receivers to connect. Each receiver will be connected with default priority (0).

$throwable : bool = true

Indicates if the signal should throw exceptions when a receiver fails (default true).

Tags
example
// Create empty signal
$signal = new Signal();

// Create signal with initial receivers
$signal = new Signal([
    fn() => echo 'Handler 1',
    fn() => echo 'Handler 2'
]);

connect()

Connects a receiver to this signal.

public connect(callable|Receiver $receiver[, int $priority = 0 ][, bool $autoDisconnect = false ]) : bool

Receivers are executed in order of priority (highest first). Duplicate receivers are ignored.

Parameters
$receiver : callable|Receiver

The receiver to connect.

$priority : int = 0

Execution priority (higher values execute first). Default: 0

$autoDisconnect : bool = false

Auto-disconnect after first execution. Default: false

Tags
example
$signal = new Signal();

// Connect a closure
$signal->connect( fn($data) => echo $data );

// Connect with high priority
$signal->connect( fn() => echo 'First!', priority: 100 );

// Connect a one-time listener
$signal->connect(
    fn() => echo 'Once only',
    autoDisconnect: true
);

// Duplicate connection returns false
$handler = fn() => echo 'test';
$signal->connect( $handler ); // true
$signal->connect( $handler ); // false (already connected)
Return values
bool

True if successfully connected, false if duplicate or invalid receiver.

connected()

Checks if any receivers are connected to this signal.

public connected() : bool
Tags
example
$signal = new Signal();

if ( !$signal->connected() ) {
    echo 'No listeners attached';
}

$signal->connect( fn() => echo 'test' );

if ( $signal->connected() ) {
    $signal->emit( 'data' ); // Safe to emit
}
Return values
bool

True if at least one receiver is connected, false otherwise.

disconnect()

Disconnects one or all receivers from this signal.

public disconnect([callable|Receiver|null $receiver = null ]) : bool
Parameters
$receiver : callable|Receiver|null = null

The receiver to disconnect. Null disconnects all.

Tags
example
$signal = new Signal();
$handler1 = fn() => echo 'A';
$handler2 = fn() => echo 'B';

$signal->connect( $handler1 );
$signal->connect( $handler2 );

// Disconnect specific receiver
$signal->disconnect( $handler1 ); // true
$signal->disconnect( $handler1 ); // false (already disconnected)

// Disconnect all receivers
$signal->disconnect(); // true
$signal->disconnect(); // false (no receivers to disconnect)
Return values
bool

True if disconnection occurred, false otherwise.

emit()

Emits a signal, calling all connected receivers with the provided values.

public emit(mixed ...$values) : void

Receivers are called in priority order (highest to lowest). Receivers marked with autoDisconnect are automatically removed after being called.

Parameters
$values : mixed

Zero or more values to pass to each receiver.

Tags
throws
Throwable

If a receiver throws and $throwable is true.

example
$signal = new Signal();

$signal->connect( fn($name, $age) =>
    echo "User: $name, Age: $age" . PHP_EOL
);

// Emit with multiple parameters
$signal->emit( 'Alice', 30 );
// Output: User: Alice, Age: 30

// Emit with no parameters
$signal->connect( fn() => echo 'Triggered!' . PHP_EOL );
$signal->emit();
// Output: Triggered!

// Auto-disconnect example
$signal->connect(
    fn() => echo 'Once!' . PHP_EOL,
    autoDisconnect: true
);
$signal->emit(); // Prints "Once!"
$signal->emit(); // Doesn't print (already disconnected)

hasReceiver()

Checks if a specific receiver is connected to this signal.

public hasReceiver(callable|Receiver $receiver) : bool
Parameters
$receiver : callable|Receiver

The receiver to check.

Tags
example
$signal = new Signal();
$handler = fn() => echo 'test';

echo $signal->hasReceiver( $handler ); // false

$signal->connect( $handler );
echo $signal->hasReceiver( $handler ); // true

$signal->disconnect( $handler );
echo $signal->hasReceiver( $handler ); // false
Return values
bool

True if connected, false otherwise.

toArray()

Returns an array of all connected receivers.

public toArray() : array<string|int, callable>

The returned array contains the actual callable references, not the SignalEntry wrapper objects.

Tags
example
$signal = new Signal();
$handler1 = fn() => echo 'A';
$handler2 = fn() => echo 'B';

$signal->connect( $handler1, priority: 10 );
$signal->connect( $handler2, priority: 5 );

$receivers = $signal->toArray();
// Returns: [$handler1, $handler2] (in priority order)

echo count($receivers); // 2
Return values
array<string|int, callable>

Array of receiver callables in priority order.


        
On this page

Search results