gianfriaur/opcua-php-client-session-manager

This package is abandoned and no longer maintained. The author suggests using the https://github.com/php-opcua/opcua-session-manager package instead.

Session manager daemon for persistent OPC UA connections in PHP — Unix socket IPC, automatic session recovery, subscription transfer

Maintainers

Package info

github.com/php-opcua/opcua-session-manager

Documentation

pkg:composer/gianfriaur/opcua-php-client-session-manager

Statistics

Installs: 83

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

v4.0.0 2026-03-26 17:41 UTC

This package is auto-updated.

Last update: 2026-03-26 17:43:53 UTC


README

OPC UA Session Manager

Tests Coverage Latest Version PHP Version License

Keep OPC UA sessions alive across PHP requests. A daemon-based session manager for opcua-client that eliminates the 50–200ms connection handshake overhead on every HTTP request.

PHP's request/response model destroys all state — including network connections — at the end of every request. OPC UA requires a 5-step handshake (TCP → Hello/Ack → OpenSecureChannel → CreateSession → ActivateSession) that must be repeated every single time. This package solves the problem with a long-running ReactPHP daemon that holds sessions in memory, communicating with PHP applications via a lightweight Unix socket IPC protocol.

What you get:

  • Session persistence — OPC UA connections survive across HTTP requests. Pay the handshake cost once, reuse forever
  • Drop-in replacementManagedClient implements the same OpcUaClientInterface as the direct Client. Swap one line, keep all your code
  • All OPC UA operations — browse, read, write, method calls, subscriptions, history, path resolution, type discovery
  • Security hardening — method whitelist, IPC authentication, credential stripping, error sanitization, connection limits
  • Automatic cleanup — expired sessions are disconnected after configurable inactivity timeout
  • Graceful shutdown — SIGTERM/SIGINT cleanly disconnect all active sessions

A note on versioning: We're aware of the rapid major releases in a short time frame. This library is under active, full-time development right now — the goal is to reach a production-stable state as quickly as possible. Breaking changes are being bundled and shipped deliberately to avoid dragging them out across many minor releases. Once the API surface settles, major version bumps will become rare. Thanks for your patience.

Quick Start

composer require php-opcua/opcua-session-manager

1. Start the daemon

php bin/opcua-session-manager

2. Use ManagedClient in your PHP code

use PhpOpcua\SessionManager\Client\ManagedClient;

$client = new ManagedClient();
$client->connect('opc.tcp://localhost:4840');

$value = $client->read('i=2259');
echo $value->getValue(); // 0 = Running

$client->disconnect();

That's it. Same API as the direct Client, but the session stays alive between requests.

See It in Action

Session persistence across requests

// Request 1: open session — handshake happens once
$client = new ManagedClient();
$client->connect('opc.tcp://localhost:4840');
$_SESSION['opcua'] = $client->getSessionId();
// Do NOT call disconnect() — session stays alive in daemon

// Request 2: reuse the same session — no handshake needed
$client = new ManagedClient();
$client->connect('opc.tcp://localhost:4840');
$value = $client->read('i=2259'); // ~5ms instead of ~155ms

Browse and read

$refs = $client->browse('i=85');
foreach ($refs as $ref) {
    echo "{$ref->displayName} ({$ref->nodeId})\n";
}

$nodeId = $client->resolveNodeId('/Objects/Server/ServerStatus');
$status = $client->read($nodeId);

Read multiple values with fluent builder

$results = $client->readMulti()
    ->node('i=2259')->value()
    ->node('ns=2;i=1001')->displayName()
    ->execute();

Write to a PLC

// Auto-detection (v4) — type inferred automatically
$client->write('ns=2;i=1001', 42);

// Explicit type (still supported)
use PhpOpcua\Client\Types\BuiltinType;
$client->write('ns=2;i=1001', 42, BuiltinType::Int32);

Subscribe to data changes

$sub = $client->createSubscription(publishingInterval: 500.0);

$client->createMonitoredItems($sub->subscriptionId, [
    ['nodeId' => 'ns=2;i=1001'],
]);

$response = $client->publish();
foreach ($response->notifications as $notif) {
    echo $notif['dataValue']->getValue() . "\n";
}

Secure connection with authentication

use PhpOpcua\Client\Security\SecurityPolicy;
use PhpOpcua\Client\Security\SecurityMode;

$client = new ManagedClient(
    socketPath: '/var/run/opcua-session-manager.sock',
    authToken: trim(file_get_contents('/etc/opcua/daemon.token')),
);

$client->setSecurityPolicy(SecurityPolicy::Basic256Sha256);
$client->setSecurityMode(SecurityMode::SignAndEncrypt);
$client->setClientCertificate('/certs/client.pem', '/certs/client.key');
$client->setUserCredentials('operator', 'secret');
$client->connect('opc.tcp://192.168.1.100:4840');

Tip: Skip setClientCertificate() and a self-signed cert gets auto-generated in memory — perfect for quick tests or servers with auto-accept.

How It Works

┌──────────────┐         ┌──────────────────────────────┐         ┌──────────────┐
│  PHP Request │ ──IPC──►│  Session Manager Daemon      │ ──TCP──►│  OPC UA      │
│  (short-     │◄──IPC── │                              │◄──TCP── │  Server      │
│   lived)     │         │  ● ReactPHP event loop       │         │              │
└──────────────┘         │  ● Sessions in memory        │         └──────────────┘
                         │  ● Periodic cleanup timer    │
┌──────────────┐         │  ● Signal handlers           │
│  PHP Request │ ──IPC──►│                              │
│  (reuses     │◄──IPC── │  Sessions:                   │
│   session)   │         │   [sess-a1b2] → Client (TCP) │
└──────────────┘         │   [sess-c3d4] → Client (TCP) │
                         └──────────────────────────────┘

Without the session manager:

Request 1:  [connect 150ms] [read 5ms] [disconnect]  → total ~155ms
Request 2:  [connect 150ms] [read 5ms] [disconnect]  → total ~155ms

With the session manager:

Request 1:  [open session 150ms] [read 5ms]           → total ~155ms  (first time only)
Request 2:                       [read 5ms]           → total ~5ms
Request N:                       [read 5ms]           → total ~5ms

Features

Feature What it does
Drop-in Replacement ManagedClient implements the same OpcUaClientInterface as the direct Client
Session Persistence OPC UA sessions survive across PHP requests via the daemon
All OPC UA Operations Browse, read, write, method calls, subscriptions, history, path resolution
String NodeIds All methods accept 'i=2259' or 'ns=2;s=MyNode' in addition to NodeId objects
Fluent Builder API readMulti(), writeMulti(), createMonitoredItems(), translateBrowsePaths() support chainable builders
Typed Returns All service responses return public readonly DTOs — SubscriptionResult, CallResult, BrowseResultSet, etc.
Type Discovery discoverDataTypes() auto-detects custom server structures
Transfer & Recovery transferSubscriptions() and republish() for session migration
PSR-3 Logging Optional structured logging via any PSR-3 logger
PSR-16 Cache Cache management forwarded to daemon — invalidateCache(), flushCache()
Security 6 policies, 3 auth modes, IPC authentication, method whitelist
Auto-Retry Automatic reconnect on connection failures
Auto-Batching Transparent batching for readMulti()/writeMulti()
Automatic Cleanup Expired sessions closed after inactivity timeout
Graceful Shutdown SIGTERM/SIGINT disconnect all sessions cleanly

Daemon Options

php bin/opcua-session-manager [options]
Option Default Description
--socket <path> /tmp/opcua-session-manager.sock Unix socket path
--timeout <sec> 600 Session inactivity timeout
--cleanup-interval <sec> 30 Expired session cleanup interval
--auth-token <token> (none) Shared secret for IPC authentication
--auth-token-file <path> (none) Read auth token from file (recommended)
--max-sessions <n> 100 Maximum concurrent sessions
--socket-mode <octal> 0600 Socket file permissions
--allowed-cert-dirs <dirs> (none) Comma-separated allowed certificate directories

Auth token priority: OPCUA_AUTH_TOKEN env var > --auth-token-file > --auth-token.

Security

The daemon implements multiple layers of security hardening:

  • IPC authentication — shared-secret token validated with timing-safe hash_equals()
  • Socket permissions0600 by default (owner-only)
  • Method whitelist — only 37 documented OPC UA operations allowed via query
  • Credential protection — passwords and private key paths stripped immediately after connection
  • Session limits — configurable maximum to prevent resource exhaustion
  • Certificate path restrictions--allowed-cert-dirs constrains certificate directories
  • Input size limit — IPC requests capped at 1MB
  • Connection protection — 30s per-connection timeout, max 50 concurrent IPC connections
  • Error sanitization — messages truncated, file paths stripped
  • PID file lock — prevents multiple daemon instances

Recommended production setup

openssl rand -hex 32 > /etc/opcua/daemon.token
chmod 600 /etc/opcua/daemon.token

OPCUA_AUTH_TOKEN=$(cat /etc/opcua/daemon.token) php bin/opcua-session-manager \
    --socket /var/run/opcua-session-manager.sock \
    --socket-mode 0660 \
    --max-sessions 50 \
    --allowed-cert-dirs /etc/opcua/certs

Comparison

Direct Client ManagedClient
Connection Direct TCP Via daemon (Unix socket)
Session lifetime Dies with PHP process Persists across requests
Per-operation overhead ~1–5ms ~5–15ms
Connection overhead ~50–200ms every request ~50–200ms first time only
Subscriptions Lost between requests Maintained by daemon
Certificate paths Relative or absolute Absolute only

Documentation

# Document Covers
01 Introduction Overview, requirements, quick start
02 Overview & Architecture Problem, solution, components
03 Installation Requirements, Composer setup, project structure
04 Daemon CLI options, security, systemd/Supervisor, internals
05 ManagedClient API Full API reference, configuration, session persistence
06 IPC Protocol Transport, commands, authentication, wire format
07 Type Serialization JSON conversion for all OPC UA types and DTOs
08 Testing Test infrastructure, helper class, running tests
09 Examples Complete code examples for all features

Testing

./vendor/bin/pest                                          # everything
./vendor/bin/pest tests/Unit/                              # unit only
./vendor/bin/pest tests/Integration/ --group=integration   # integration only

340+ tests (unit + integration) covering browse, read/write, subscriptions, method calls, path resolution, connection state, security, type serialization, session persistence, session recovery, and all v4.0.0 DTOs.

Note on coverage: SessionManagerDaemon is excluded from coverage reports because it runs as a separate long-lived process (ReactPHP event loop). PHP coverage tools (pcov, xdebug) only instrument the test runner process — they cannot track code executing inside a subprocess started via proc_open(). The daemon is fully tested by the integration suite, which starts a real daemon, sends IPC commands, and verifies responses. This is a known limitation shared by other daemon-based PHP packages (Laravel Horizon, Symfony Messenger, RoadRunner workers).

Ecosystem

Package Description
opcua-client Pure PHP OPC UA client — the core protocol implementation
opcua-session-manager Session persistence daemon (this package)
opcua-laravel-client Laravel integration — service provider, facade, config
opcua-test-server-suite Docker-based OPC UA test servers for integration testing

Roadmap

See ROADMAP.md for what's coming next.

Contributing

Contributions welcome — see CONTRIBUTING.md.

Changelog

See CHANGELOG.md.

License

MIT