Pg get notify: примеры (PHP)
pg_get_notify(PgSql\Connection $connection, int $mode = PGSQL_ASSOC): array|falseФункция pg_get_notify в PHP
Функция pg_get_notify предназначена для получения асинхронных уведомлений, отправленных сервером PostgreSQL с помощью команды NOTIFY. Она используется в приложениях, которым требуется реакция на события, происходящие в базе данных, без постоянного выполнения запросов.
Функция применяется при работе с механизмом уведомлений PostgreSQL (LISTEN/NOTIFY). Она позволяет PHP-скрипту получать сообщения, которые были отправлены другими процессами (например, триггерами или административными задачами) в реальном времени.
pg_get_notify(resource $connection, int $result_type = PGSQL_ASSOC): array|false
- $connection (ресурс) – Обязательный параметр. Ресурс подключения к базе данных PostgreSQL, полученный с помощью
pg_connect()илиpg_pconnect(). - $result_type (целое число) – Необязательный параметр, определяет формат возвращаемого массива. Может принимать значения:
PGSQL_ASSOC(по умолчанию) – возвращает ассоциативный массив.PGSQL_NUM– возвращает индексированный массив.
Функция возвращает массив с уведомлением, содержащим ключи 'message' (текст уведомления) и 'pid' (PID серверного процесса), либо false, если уведомлений нет.
Примеры использования pg_get_notify
Код для получения уведомления в ассоциативном массиве.
<?php
$conn = pg_connect('host=localhost dbname=test user=postgres');
pg_query($conn, 'LISTEN mychannel;');
// В другом процессе выполняется: NOTIFY mychannel, 'Hello!';
$notify = pg_get_notify($conn);
if ($notify) {
echo 'Канал: ' . $notify['message'] . '\n';
echo 'PID: ' . $notify['pid'] . '\n';
}
?>Канал: Hello!
PID: 12345<?php
$notify = pg_get_notify($conn, PGSQL_NUM);
if ($notify) {
echo 'Канал: ' . $notify[0] . '\n';
echo 'PID: ' . $notify[1] . '\n';
}
?>Канал: Hello!
PID: 12345<?php
$notify = pg_get_notify($conn);
var_dump($notify);
?>bool(false)Похожие функции в PHP
Функция pg_get_pid возвращает идентификатор серверного процесса. Она может использоваться вместе с pg_get_notify для отладки или управления подключениями. Предпочтительнее использовать pg_get_notify для получения уведомлений, а pg_get_pid – для получения информации о подключении.
Функция pg_socket возвращает файловый дескриптор сокета подключения. Это позволяет организовать неблокирующий опрос уведомлений с помощью stream_select. Такой подход полезен в асинхронных приложениях, где необходимо обрабатывать несколько подключений одновременно.
Альтернативы в других языках
В Python для получения уведомлений используется метод notifies объекта соединения. Он возвращает список уведомлений, что отличается от PHP, где функция возвращает одно уведомление за вызов.
import psycopg2
conn = psycopg2.connect('host=localhost dbname=test')
conn.autocommit = True
cur = conn.cursor()
cur.execute('LISTEN mychannel;')
conn.poll()
if conn.notifies:
notify = conn.notifies.pop()
print(f"Канал: {notify.payload}")
print(f"PID: {notify.pid}")Канал: Hello!
PID: 12345В Node.js с библиотекой pg уведомления обрабатываются через событие notification на клиенте. Это событийный подход, в отличие от процедурного в PHP.
const { Client } = require('pg');
const client = new Client();
client.connect();
client.query('LISTEN mychannel');
client.on('notification', (msg) => {
console.log(`Канал: ${msg.payload}`);
console.log(`PID: ${msg.processId}`);
});Pg get notify в MySQL
В MySQL отсутствует прямой аналог механизма LISTEN/NOTIFY. Для похожей функциональности обычно используются таблицы-очереди или события, которые проверяются периодически, что менее эффективно для реального времени.
Типичные ошибки
Если не выполнить команду LISTEN для канала, уведомления не будут поступать.
<?php
$conn = pg_connect('host=localhost dbname=test');
$notify = pg_get_notify($conn); // Всегда false
?>Функция pg_get_notify неблокирующая. Если уведомлений нет, она сразу возвращает false. Для ожидания уведомлений необходимо использовать цикл с задержкой, что может привести к высокой нагрузке.
<?php
while (true) {
$notify = pg_get_notify($conn);
if ($notify) break;
sleep(1); // Плохая практика для продакшена
}
?>Функция требует ресурс подключения, а не результат запроса.
<?php
$result = pg_query($conn, 'SELECT 1');
$notify = pg_get_notify($result); // Ошибка
?>Изменения в версиях PHP
В PHP 8.0 было обновлено расширение pgsql, но для функции pg_get_notify значительных изменений не произошло. В более ранних версиях, начиная с PHP 5.0, сигнатура функции оставалась стабильной. Важно отметить, что в PHP 8.0 многие функции расширения pgsql стали более строгими к типам аргументов, но это не затронуло поведение pg_get_notify.
Расширенные примеры
Функция pg_get_notify возвращает одно уведомление за вызов. Для получения всех накопленных уведомлений используется цикл.
<?php
while ($notify = pg_get_notify($conn)) {
echo 'Получено: ' . $notify['message'] . ' от ' . $notify['pid'] . "\n";
}
?>Этот пример позволяет избежать активного ожидания и снизить нагрузку на CPU.
<?php
$socket = pg_socket($conn);
$read = [$socket];
$write = $except = null;
if (stream_select($read, $write, $except, 5) > 0) {
$notify = pg_get_notify($conn);
if ($notify) {
// Обработка уведомления
}
}
?>Уведомления можно использовать для запуска действий в приложении при изменении данных.
<?php
pg_query($conn, 'LISTEN record_updated;');
$notify = pg_get_notify($conn);
if ($notify && $notify['message'] === 'record_updated') {
// Обновление кэша или отправка данных клиенту
echo 'Данные обновлены';
}
?>Скрипт может постоянно ожидать уведомлений для обработки фоновых задач.
<?php
declare(ticks=1);
pcntl_signal(SIGTERM, function() { global $running; $running = false; });
$running = true;
while ($running) {
if ($notify = pg_get_notify($conn)) {
// Обработка задачи из уведомления
file_put_contents('log.txt', $notify['message'], FILE_APPEND);
}
usleep(100000); // Пауза 0.1 секунды
}
?>