Start · Sprachen · PHP · Referenz · pg_socket

pg_socket

Funktion

Gibt ein Nur-Lese-Handle auf das Netzwerk-Socket der PostgreSQL-Verbindung zurück, um asynchrone I/O-Operationen zu ermöglichen.

seit PHP 5.6.0 Kategorie: db

Signatur

pg_socket(PgSql\Connection $connection): Socket|false

Beschreibung

pg_socket() liefert ein Socket-Handle für die angegebene PostgreSQL-Verbindung. Das zurückgegebene Handle ist ein Nur-Lese-Handle – es darf also nicht zum Schreiben verwendet werden. Der primäre Anwendungsfall ist die Kombination mit stream_select() oder ähnlichen Stream-Funktionen, um nicht-blockierendes, asynchrones Warten auf PostgreSQL-Ergebnisse zu implementieren.

Dies ist besonders nützlich in Kombination mit pg_send_query(), pg_send_execute() oder pg_send_query_params(): Man schickt eine Abfrage asynchron ab und wartet dann mit stream_select() auf das Socket, bis Daten verfügbar sind – anstatt den Prozess mit pg_get_result() blockierend zu blockieren.

Das zurückgegebene Handle ist vom Typ Socket (seit PHP 8.0, davor eine Ressource). Es darf nicht geschlossen werden, da es zur internen PostgreSQL-Verbindungsressource gehört. Das Schließen würde die Verbindung beschädigen.

Typische Einsatzszenarien sind Event-Loop-Architekturen oder Server-seitige PHP-Prozesse, die mehrere Datenbankverbindungen gleichzeitig überwachen müssen, ohne für jede einzeln blockieren zu wollen.

Parameter

Name Typ Default Beschreibung
$connection Pflicht PgSql\Connection Eine aktive PostgreSQL-Verbindungsinstanz, die zuvor mit pg_connect() oder pg_pconnect() erstellt wurde.

Rückgabewert

Typ
Socket|false
Beschreibung
Gibt ein Socket-Handle zurück, das das interne Verbindungs-Socket der PostgreSQL-Verbindung repräsentiert. Im Fehlerfall wird false zurückgegeben. Das Handle darf nur lesend mit stream_select() o. Ä. verwendet werden, nicht zum Schreiben und nicht geschlossen werden.

Beispiele

Asynchrone Abfrage mit stream_select() und pg_socket()

<?php
$conn = pg_connect('host=localhost dbname=testdb user=postgres password=secret');
if (!$conn) {
    die('Verbindung fehlgeschlagen');
}

// Asynchrone Abfrage senden
if (!pg_send_query($conn, 'SELECT pg_sleep(1), 42 AS answer')) {
    die('Abfrage konnte nicht gesendet werden');
}

// Socket-Handle holen
$socket = pg_socket($conn);
if ($socket === false) {
    die('Socket konnte nicht ermittelt werden');
}

// Warten, bis Daten verfügbar sind (max. 5 Sekunden)
$read   = [$socket];
$write  = null;
$except = null;

while (true) {
    $ready = stream_select($read, $write, $except, 5);
    if ($ready === false) {
        die('stream_select() Fehler');
    }
    if ($ready > 0) {
        // Verbindungsstatus aktualisieren
        pg_consume_input($conn);
        if (!pg_connection_busy($conn)) {
            break; // Ergebnis bereit
        }
    }
    $read = [$socket]; // stream_select() leert das Array – zurücksetzen
}

$result = pg_get_result($conn);
if ($result) {
    $row = pg_fetch_assoc($result);
    echo 'Antwort: ' . $row['answer'] . PHP_EOL;
}

pg_close($conn);
Antwort: 42

Mehrere PostgreSQL-Verbindungen gleichzeitig überwachen

<?php
$dsn = 'host=localhost dbname=testdb user=postgres password=secret';

$conn1 = pg_connect($dsn . ' connect_timeout=5');
$conn2 = pg_connect($dsn . ' connect_timeout=5 options=\'--application_name=conn2\'');

pg_send_query($conn1, 'SELECT 1 AS id');
pg_send_query($conn2, 'SELECT 2 AS id');

$sockets = [
    pg_socket($conn1),
    pg_socket($conn2),
];
$connections = [$conn1, $conn2];

$read   = $sockets;
$write  = null;
$except = null;

$done = 0;
while ($done < 2) {
    $ready = stream_select($read, $write, $except, 5);
    if ($ready > 0) {
        foreach ($connections as $i => $conn) {
            pg_consume_input($conn);
            if (!pg_connection_busy($conn)) {
                $result = pg_get_result($conn);
                if ($result && !isset($fetched[$i])) {
                    $row = pg_fetch_assoc($result);
                    echo "Verbindung $i lieferte: " . $row['id'] . PHP_EOL;
                    $fetched[$i] = true;
                    $done++;
                }
            }
        }
    }
    $read = $sockets; // zurücksetzen
}

pg_close($conn1);
pg_close($conn2);
Verbindung 0 lieferte: 1 Verbindung 1 lieferte: 2

// Wichtig · Fallstricke

Nicht schließen: Das von pg_socket() zurückgegebene Socket-Handle gehört der internen PostgreSQL-Verbindungsressource. Ein Aufruf von fclose() oder socket_close() auf diesem Handle würde die PostgreSQL-Verbindung beschädigen und zu undefiniertem Verhalten führen.

Nur lesend: Das Handle ist als Nur-Lese-Handle konzipiert. Es darf nicht zum Senden von Daten direkt auf das Socket verwendet werden – alle Kommunikation mit PostgreSQL muss über die pg_*()-Funktionen erfolgen.

pg_consume_input() nicht vergessen: Nach dem Erkennen von Aktivität auf dem Socket sollte pg_consume_input() aufgerufen werden, bevor pg_connection_busy() geprüft wird, um den internen Puffer der libpq-Bibliothek zu aktualisieren.

PHP 8.0+: Ab PHP 8.0 wird PgSql\Connection statt einer Ressource verwendet. Das zurückgegebene Socket-Objekt ist vom Typ Socket (ehemals Ressource vom Typ stream).