PHPackages                             gianfriaur/opcua-php-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. gianfriaur/opcua-php-client

Abandoned → [https://github.com/php-opcua/opcua-client](/?search=https%3A%2F%2Fgithub.com%2Fphp-opcua%2Fopcua-client)Library[HTTP &amp; Networking](/categories/http)

gianfriaur/opcua-php-client
===========================

Pure PHP OPC UA client — binary protocol over TCP, 6 security policies, browse/read/write/subscribe/history, zero external dependencies

v4.4.0(3w ago)7157↓77.8%1MITPHPPHP ^8.2

Since Mar 16Pushed 3w ago1 watchersCompare

[ Source](https://github.com/php-opcua/opcua-client)[ Packagist](https://packagist.org/packages/gianfriaur/opcua-php-client)[ Docs](https://github.com/php-opcua/opcua-client)[ RSS](/packages/gianfriaur-opcua-php-client/feed)WikiDiscussions master Synced 3w ago

READMEChangelog (10)Dependencies (13)Versions (19)Used By (1)

**OPC UA PHP Client**
=====================

[](#opc-ua-php-client)

    ![OPC UA PHP Client](assets/logo-light.svg)

 [![Tests](https://camo.githubusercontent.com/d9e58f729bc30c0731127401cbabdd83b0ad0484d7fe3eab6912f477bc2978b3/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7068702d6f706375612f6f706375612d636c69656e742f74657374732e796d6c3f6272616e63683d6d6173746572266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/php-opcua/opcua-client/actions/workflows/tests.yml) [![Coverage](https://camo.githubusercontent.com/6c68bebe4b397b46d7c869d348cf05e8cd01c1a67f70551b29aff70f6b24b855/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f7068702d6f706375612f6f706375612d636c69656e743f7374796c653d666c61742d737175617265266c6f676f3d636f6465636f76)](https://codecov.io/gh/php-opcua/opcua-client) [![Latest Version](https://camo.githubusercontent.com/253d0bbd7e11176d21a27bd493bafe15a29972240e0674e8253de5fc448717fc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7068702d6f706375612f6f706375612d636c69656e743f7374796c653d666c61742d737175617265266c6162656c3d7061636b6167697374)](https://packagist.org/packages/php-opcua/opcua-client) [![PHP Version](https://camo.githubusercontent.com/cfd49b0799860fbe03016d3d435c8417b0fc0a0916e46aa957e6685168ca74be/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f7068702d6f706375612f6f706375612d636c69656e743f7374796c653d666c61742d737175617265)](https://packagist.org/packages/php-opcua/opcua-client) [![License](https://camo.githubusercontent.com/da9e2105e0777950a9364f48671db9cc274b6d33e39b72eb4ff0cc961de86ff3/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f7068702d6f706375612f6f706375612d636c69656e743f7374796c653d666c61742d737175617265)](LICENSE)

 [![Linux](https://camo.githubusercontent.com/88a96af546255df6414fb878e65861f03abd9cd7c69fe0c652b32d10e1dc2b84/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f4c696e75782de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d6c696e7578266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/88a96af546255df6414fb878e65861f03abd9cd7c69fe0c652b32d10e1dc2b84/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f4c696e75782de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d6c696e7578266c6f676f436f6c6f723d7768697465) [![macOS](https://camo.githubusercontent.com/9abd62edee5c8e38df116839daa54deb7e5b2054d4bcb856529f5cd92ada8b74/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f6d61634f532de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d6170706c65266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/9abd62edee5c8e38df116839daa54deb7e5b2054d4bcb856529f5cd92ada8b74/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f6d61634f532de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d6170706c65266c6f676f436f6c6f723d7768697465) [![Windows](https://camo.githubusercontent.com/67b9f3090b3bbef27712496e616a0a0f0ead78d1a3a092a80b74df716dda8a6b/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f57696e646f77732de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d77696e646f77733131266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/67b9f3090b3bbef27712496e616a0a0f0ead78d1a3a092a80b74df716dda8a6b/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f57696e646f77732de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d77696e646f77733131266c6f676f436f6c6f723d7768697465)

---

Connect your PHP application directly to industrial PLCs, SCADA systems, sensors, historians, and IoT devices using the [OPC UA](https://opcfoundation.org/about/opc-technologies/opc-ua/) standard — without any C/C++ extensions, HTTP gateways, or middleware in between.

This library implements the full OPC UA binary protocol stack in pure PHP: TCP transport, binary encoding/decoding, secure channel establishment with asymmetric and symmetric encryption, session management, and all the major OPC UA services. Just `composer require` and you're talking to PLCs from your Laravel app, your Symfony worker, or a plain PHP script.

**What you can do with it:**

- **Read and write** process variables from any OPC UA-compliant device — temperatures, pressures, motor speeds, setpoints, counters, anything the server exposes
- **Browse** the entire address space to discover what's available, build tree views, or auto-map variables
- **Subscribe** to data changes and events in real time — get notified when a sensor value changes or an alarm fires
- **Call methods** on the server — trigger operations, run diagnostics, execute commands on the PLC
- **Query historical data** — pull raw logs, aggregated trends (min, max, average), or interpolated values at specific timestamps
- **Secure everything** — 10 security policies: 6 RSA (plaintext to AES-256 with RSA-PSS) + 4 ECC (NIST P-256/P-384 and Brainpool P-256/P-384 with ECDSA/ECDH), plus anonymous, username/password, or X.509 certificate authentication \*

All of this with zero external dependencies beyond `ext-openssl`, and full support for PHP 8.2 through 8.5.

> **Note:** OPC UA relies on persistent sessions and long-lived connections. PHP's request/response model means connections are short-lived by default. For use cases like continuous monitoring or subscription polling, pair this with [`opcua-session-manager`](https://github.com/php-opcua/opcua-session-manager) to persist sessions across requests — or use it in a long-running worker process.
>
> The session manager is a **separate package by design** — it runs as a daemon process using ReactPHP and Unix sockets, which would break this library's zero-dependency, cross-platform philosophy if bundled here. See the [Ecosystem](#ecosystem) section for details.

\* **ECC note:** The 4 ECC policies are implemented per OPC UA 1.05 spec but should be considered **experimental**. No commercial OPC UA server vendor has released devices with ECC endpoints yet — this is an ecosystem-wide gap. ECC support has been developed and tested exclusively against [UA-.NETStandard](https://github.com/OPCFoundation/UA-.NETStandard) (the OPC Foundation reference implementation). The implementation follows the 1.05.3 specification and is aligned with 1.05.4 regarding `ReceiverCertificateThumbprint`, HKDF salt encoding, and `LegacySequenceNumbers = FALSE` for ECC (sequence numbers start at 0 and wrap at `UInt32.MaxValue`; landed in v4.3.0). One ECC-specific change from 1.05.4 (per-message IV derivation) is not yet implemented — it is coupled to the future AEAD policy variants. See the [ECC 1.05.4 Compliance](ROADMAP.md#ecc-1054-compliance) section in the roadmap for a detailed analysis. For production deployments, use the RSA policies. If you ever manage to connect this library to a real industrial device with ECC OPC UA, let us know — we owe you a coffee :) See the [Security documentation](docs/security/overview.md) for details.

### Tested against the OPC UA reference implementation

[](#tested-against-the-opc-ua-reference-implementation)

This library is integration-tested against **[UA-.NETStandard](https://github.com/OPCFoundation/UA-.NETStandard)** — the **reference implementation** maintained by the OPC Foundation, the organization that defines the OPC UA specification. This is the same stack used by major industrial vendors to certify their products.

1300+ tests (1040+ unit, 250+ integration) run via [uanetstandard-test-suite](https://github.com/php-opcua/uanetstandard-test-suite) against 8 server instances covering every security policy, authentication method, data type, method call, subscription, event, alarm, and historical read defined by the spec — with 99%+ unit test code coverage. Unit tests run on **Linux, macOS, and Windows** across PHP 8.2–8.5. NodeManagement integration tests run against an additional `open62541` server (UA-.NETStandard does not implement that service set) — see [testing docs](docs/testing/integration.md).

**This library is already used in production with real industrial equipment** in factory automation and process control environments.

---

Quick Start
-----------

[](#quick-start)

```
composer require php-opcua/opcua-client
```

```
use PhpOpcua\Client\ClientBuilder;
use PhpOpcua\Client\Types\NodeId;

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

// Read server status — string format
$status = $client->read('i=2259');
echo $status->getValue(); // 0 = Running

// NodeId objects work too
$status = $client->read(NodeId::numeric(0, 2259));

$client->disconnect();
```

That's it. Three lines to build, connect, and read. No config files, no service containers, no XML.

> **Tip:** All client methods accept NodeId strings like `'i=2259'`, `'ns=2;i=1001'`, or `'ns=2;s=MyNode'` anywhere a `NodeId` is expected. Invalid strings throw `InvalidNodeIdException`.

See It in Action
----------------

[](#see-it-in-action)

### Browse the address space

[](#browse-the-address-space)

```
$refs = $client->browse('i=85'); // Objects folder

foreach ($refs as $ref) {
    echo "{$ref->displayName} ({$ref->nodeId})\n";
    //=> Server (ns=0;i=2253)
    //=> MyPLC (ns=2;i=1000)
}
```

### Read multiple values

[](#read-multiple-values)

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

foreach ($results as $dataValue) {
    echo $dataValue->getValue() . "\n";
}
```

> **Tip:** You can also pass an array to `readMulti([...])` -- the builder is just a fluent alternative.

### Get server info

[](#get-server-info)

```
// All at once
$info = $client->getServerBuildInfo();
echo $info->productName;        // e.g. "UA-.NETStandard"
echo $info->manufacturerName;   // e.g. "OPC Foundation"
echo $info->softwareVersion;    // e.g. "1.5.374.126"

// Or individual fields
$client->getServerProductName();        // ?string
$client->getServerSoftwareVersion();    // ?string
$client->getServerBuildDate();          // ?DateTimeImmutable
```

### Resolve a path and read a value

[](#resolve-a-path-and-read-a-value)

```
$nodeId = $client->resolveNodeId('/Objects/MyPLC/Temperature');
$value = $client->read($nodeId);

echo $value->getValue();        // 23.5
echo $value->statusCode;        // 0 (Good)
echo $value->sourceTimestamp;    // DateTimeImmutable
```

### Write to a PLC

[](#write-to-a-plc)

```
use PhpOpcua\Client\Types\BuiltinType;

// Auto-detect type (reads the node first, caches the type)
$client->write('ns=2;i=1001', 42);

// Explicit type (validated against the node when auto-detect is on)
$client->write('ns=2;i=1001', 42, BuiltinType::Int32);
```

### Call a method on the server

[](#call-a-method-on-the-server)

```
use PhpOpcua\Client\Types\Variant;

$result = $client->call(
    'i=2253',   // Server object
    'i=11492',  // GetMonitoredItems
    [new Variant(BuiltinType::UInt32, 1)],
);

echo $result->statusCode;                   // 0
echo $result->outputArguments[0]->value;    // [1001, 1002, ...]
```

### Subscribe to data changes

[](#subscribe-to-data-changes)

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

$client->createMonitoredItems($sub->subscriptionId, [
    ['nodeId' => NodeId::numeric(2, 1001)],
]);

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

### Read historical data

[](#read-historical-data)

```
$values = $client->historyReadRaw(
    'ns=2;i=1001',
    startTime: new DateTimeImmutable('-1 hour'),
    endTime: new DateTimeImmutable(),
);

foreach ($values as $dv) {
    echo "[{$dv->sourceTimestamp->format('H:i:s')}] {$dv->getValue()}\n";
}
```

### Manage nodes at runtime

[](#manage-nodes-at-runtime)

```
use PhpOpcua\Client\Types\NodeClass;
use PhpOpcua\Client\Types\QualifiedName;
use PhpOpcua\Client\Types\StatusCode;

// Add a variable node
$results = $client->addNodes([
    [
        'parentNodeId'       => 'i=85',                              // Objects folder
        'referenceTypeId'    => 'i=35',                              // Organizes
        'requestedNewNodeId' => 'ns=2;s=MyVariable',
        'browseName'         => new QualifiedName(2, 'MyVariable'),
        'nodeClass'          => NodeClass::Variable,
        'typeDefinition'     => 'i=63',                              // BaseDataVariableType
    ],
]);

echo StatusCode::getName($results[0]->statusCode); // Good
echo $results[0]->addedNodeId;                     // ns=2;s=MyVariable

// Clean up when done
$client->deleteNodes([['nodeId' => 'ns=2;s=MyVariable']]);
```

Supports all 8 node classes. See [Node Management documentation](docs/operations/managing-nodes.md) for adding references, class-specific attributes, and error handling.

### Connect with full security

[](#connect-with-full-security)

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

$client = ClientBuilder::create()
    ->setSecurityPolicy(SecurityPolicy::Basic256Sha256)
    ->setSecurityMode(SecurityMode::SignAndEncrypt)
    ->setClientCertificate('/certs/client.pem', '/certs/client.key', '/certs/ca.pem')
    ->setUserCredentials('operator', 'secret')
    ->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.

### Decode custom structures with codecs

[](#decode-custom-structures-with-codecs)

```
use PhpOpcua\Client\ClientBuilder;
use PhpOpcua\Client\Repository\ExtensionObjectRepository;

$repo = new ExtensionObjectRepository();
$repo->register(NodeId::numeric(2, 5001), MyPointCodec::class);

$client = ClientBuilder::create($repo)
    ->connect('opc.tcp://localhost:4840');

$point = $client->read($pointNodeId)->getValue();
// ['x' => 1.5, 'y' => 2.5, 'z' => 3.5]
```

Each client gets its own isolated codec registry — no global state, no cross-contamination.

### Test without a real server

[](#test-without-a-real-server)

```
use PhpOpcua\Client\Testing\MockClient;
use PhpOpcua\Client\Types\DataValue;

$client = MockClient::create();

// Register a handler for read operations
$client->onRead(function (NodeId $nodeId) {
    return DataValue::ofDouble(23.5);
});

// Use the same API as a real client
$value = $client->read('ns=2;s=Temperature');
echo $value->getValue(); // 23.5

// Verify what was called
echo $client->callCount('read'); // 1
```

`MockClient` implements `OpcUaClientInterface` with no TCP connection. Register handlers with `onRead()`, `onWrite()`, `onBrowse()`, `onCall()`, and `onResolveNodeId()`. Track calls with `getCalls()`, `getCallsFor($method)`, `callCount($method)`, and `resetCalls()`. Works with fluent builders (`readMulti()`, `writeMulti()`, etc.).

### Add structured logging

[](#add-structured-logging)

```
use PhpOpcua\Client\ClientBuilder;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$logger = new Logger('opcua');
$logger->pushHandler(new StreamHandler('php://stderr', Logger::DEBUG));

$client = ClientBuilder::create()
    ->setLogger($logger)
    ->connect('opc.tcp://localhost:4840');
// Logs: handshake, secure channel, session creation, reads, retries, errors...
```

Any [PSR-3](https://www.php-fig.org/psr/psr-3/) logger works — Monolog, Laravel's logger, or your own. Without one, logging is silently disabled (`NullLogger`).

### React to events (PSR-14)

[](#react-to-events-psr-14)

```
use PhpOpcua\Client\ClientBuilder;
use PhpOpcua\Client\Event\DataChangeReceived;
use PhpOpcua\Client\Event\AlarmActivated;

// Set any PSR-14 event dispatcher on the builder
$client = ClientBuilder::create()
    ->setEventDispatcher($yourDispatcher)
    ->connect('opc.tcp://localhost:4840');

// In your listener:
class HandleDataChange {
    public function __invoke(DataChangeReceived $event): void {
        echo "Node changed on subscription {$event->subscriptionId}: "
            . $event->dataValue->getValue() . "\n";
    }
}
```

47 granular events covering connection, session, subscription, data change, alarms, read/write, browse, cache, and retry. Zero overhead with the default `NullEventDispatcher`. See [Events documentation](docs/observability/events.md) for the full list.

### Monitor alarms in real time

[](#monitor-alarms-in-real-time)

```
use PhpOpcua\Client\Event\AlarmActivated;
use PhpOpcua\Client\Event\AlarmSeverityChanged;

// Listen for alarm activation
class AlarmHandler {
    public function handleActivated(AlarmActivated $event): void {
        Log::critical("Alarm active: {$event->sourceName} (severity: {$event->severity})");
    }

    public function handleSeverity(AlarmSeverityChanged $event): void {
        if ($event->severity >= 800) {
            Notification::send($operators, new HighSeverityAlarm($event));
        }
    }
}
```

### Explore from the terminal

[](#explore-from-the-terminal)

```
composer require php-opcua/opcua-cli
```

```
# Browse the address space
opcua-cli browse opc.tcp://192.168.1.10:4840 /Objects

# Read a value
opcua-cli read opc.tcp://192.168.1.10:4840 "ns=2;i=1001"

# Watch a value in real time
opcua-cli watch opc.tcp://192.168.1.10:4840 "ns=2;i=1001"

# Discover endpoints
opcua-cli endpoints opc.tcp://192.168.1.10:4840
```

Full security support, JSON output, debug logging, NodeSet2.xml code generation, and more. See [`php-opcua/opcua-cli`](https://github.com/php-opcua/opcua-cli) for full documentation.

### Trust server certificates

[](#trust-server-certificates)

```
use PhpOpcua\Client\ClientBuilder;
use PhpOpcua\Client\TrustStore\FileTrustStore;
use PhpOpcua\Client\TrustStore\TrustPolicy;

$client = ClientBuilder::create()
    ->setTrustStore(new FileTrustStore())           // ~/.opcua/trusted/
    ->setTrustPolicy(TrustPolicy::Fingerprint)      // or FingerprintAndExpiry, Full
    ->connect('opc.tcp://192.168.1.100:4840');       // throws UntrustedCertificateException if not trusted
```

Trust on first use (TOFU):

```
$builder = ClientBuilder::create()
    ->setTrustStore(new FileTrustStore())
    ->autoAccept(true);                    // accept new certificates
    // ->autoAccept(true, force: true);    // also accept changed certificates
$client = $builder->connect('opc.tcp://192.168.1.100:4840');
```

Disable trust validation:

```
$client = ClientBuilder::create()
    ->setTrustPolicy(null)                // no trust policy
    ->connect('opc.tcp://192.168.1.100:4840');
```

Or manage from the CLI with [`php-opcua/opcua-cli`](https://github.com/php-opcua/opcua-cli):

```
opcua-cli trust opc.tcp://server:4840          # download and trust
opcua-cli trust:list                            # list trusted certs
opcua-cli trust:remove AB:CD:12:34:...          # remove a cert
```

### Auto-discover custom types

[](#auto-discover-custom-types)

```
$client = ClientBuilder::create()
    ->connect('opc.tcp://localhost:4840');
$client->discoverDataTypes();

$point = $client->read($pointNodeId)->getValue();
// ['x' => 1.5, 'y' => 2.5, 'z' => 3.5] — no codec needed
```

### Extend the client with custom modules

[](#extend-the-client-with-custom-modules)

```
use PhpOpcua\Client\ClientBuilder;
use PhpOpcua\Client\Module\ReadWrite\ReadWriteModule;

// Add a custom module
$client = ClientBuilder::create()
    ->addModule(new MyQueryServiceModule())
    ->connect('opc.tcp://localhost:4840');

$client->queryFirst(...); // custom method from your module

// Replace a built-in module
$client = ClientBuilder::create()
    ->replaceModule(ReadWriteModule::class, new MyCustomReadWriteModule())
    ->connect('opc.tcp://localhost:4840');

$client->read(...); // uses your custom implementation

// Introspection
$client->hasMethod('read');                 // true
$client->hasModule(ReadWriteModule::class); // true
```

The client ships with 8 built-in modules (ReadWrite, Browse, Subscription, History, NodeManagement, TranslateBrowsePath, ServerInfo, TypeDiscovery). Add your own or swap built-ins with `addModule()` and `replaceModule()`. See [Modules](docs/extensibility/modules.md) for details.

### Use pre-built OPC UA companion types

[](#use-pre-built-opc-ua-companion-types)

Instead of writing codecs by hand or relying on runtime discovery, install [`opcua-client-nodeset`](https://github.com/php-opcua/opcua-client-nodeset) to get pre-generated PHP types for 51 OPC Foundation companion specifications — DI, Robotics, Machinery, MachineTool, ISA-95, CNC, MTConnect, and many more:

```
composer require php-opcua/opcua-client-nodeset
```

```
use PhpOpcua\Client\ClientBuilder;
use PhpOpcua\Nodeset\Robotics\RoboticsRegistrar;
use PhpOpcua\Nodeset\Robotics\RoboticsNodeIds;
use PhpOpcua\Nodeset\Robotics\Enums\OperationalModeEnumeration;

$client = ClientBuilder::create()
    ->loadGeneratedTypes(new RoboticsRegistrar())  // loads DI + IA dependencies automatically
    ->connect('opc.tcp://192.168.1.100:4840');

// Enum values are auto-cast to PHP BackedEnum
$mode = $client->read(RoboticsNodeIds::OperationalMode)->getValue();
// OperationalModeEnumeration::MANUAL_REDUCED_SPEED (not int 1)

// Structured types return typed DTOs with property access
$data = $client->read(RoboticsNodeIds::SomeStructuredNode)->getValue();
$data->Manufacturer;   // string — IDE autocomplete works
$data->Status;         // OperatingStateEnum — not a raw int
```

Each Registrar automatically loads its NodeSet dependencies. Use `only: true` to skip dependency loading if you manage them yourself.

> **Tip:** You can also generate types from your own custom NodeSet2.xml files using [`opcua-cli generate:nodeset`](https://github.com/php-opcua/opcua-cli).

Why This Library?
-----------------

[](#why-this-library)

- **Zero runtime dependencies** — only `ext-openssl`. Optional PSR-3 logging, PSR-16 caching, and PSR-14 events via any compatible implementation.
- **PHP 8.2+** — runs on any modern PHP.
- **Native binary protocol** — speaks OPC UA directly over TCP. No HTTP gateway, no REST bridge, no sidecar.
- **Full security stack** — 10 policies: 6 RSA up to Aes256Sha256RsaPss + 4 ECC (NIST and Brainpool), 3 auth modes, auto-generated certs, persistent certificate trust store with TOFU.
- **Industrial-ready** — server certificate trust management, alarm event deduction, subscription recovery, auto-retry — built for certified industrial deployments.
- **Batteries included** — browse, read, write, call, subscriptions, events, history, path resolution, batching, retry, CLI tool.
- **Cross-platform** — tested on Linux, macOS, and Windows via CI. No FFI, no COM. Uses `DIRECTORY_SEPARATOR` and platform-aware defaults throughout.
- **Thoroughly tested** — 1300+ tests (1040+ unit, 250+ integration), 99%+ unit test code coverage across PHP 8.2, 8.3, 8.4, and 8.5 on all three platforms.
- **Typed everywhere** — all service responses return `public readonly` DTOs, not arrays.
- **Session persistence** — keep OPC UA connections alive across PHP requests via [`opcua-session-manager`](https://github.com/php-opcua/opcua-session-manager).
- **Laravel-ready** — drop-in via [`opcua-laravel-client`](https://github.com/php-opcua/laravel-opcua).

Features
--------

[](#features)

FeatureWhat it does**Browse**Navigate the address space — recursive, automatic continuation, tree building**Path Resolution**Resolve `/Objects/MyPLC/Temperature` to a NodeId in one call**Read / Write**Single and multi operations, all OPC UA data types, automatic type detection with caching**Server BuildInfo**`getServerBuildInfo()` returns product name, manufacturer, version, build number, and build date in one call**Node Management**Add/delete nodes and references at runtime — all 8 node classes, automatic attribute encoding**Method Call**Invoke server methods with typed arguments and results**Subscriptions**Data change and event monitoring with publish/acknowledge, modify monitored items, conditional triggering**Transfer &amp; Recovery**Transfer subscriptions across sessions and republish unacknowledged notifications**History Read**Raw, processed (aggregated), and at-time historical queries**Endpoint Discovery**Discover available endpoints and security policies**Security**10 policies: 6 RSA (None through Aes256Sha256RsaPss) + 4 ECC (NIST P-256/P-384, Brainpool P-256/P-384)**Authentication**Anonymous, Username/Password, X.509 Certificate**Auto-Retry**Automatic reconnect on connection failures**Fluent Builder API**Chain `readMulti()`, `writeMulti()`, `createMonitoredItems()`, and `translateBrowsePaths()` calls with a fluent builder**Auto-Batching**Transparent batching for `readMulti`/`writeMulti`**ExtensionObject Codecs**Pluggable per-client codec system for custom structures**Auto-Discovery**`discoverDataTypes()` auto-detects custom structures without manual codecs**Modular Architecture**8 built-in service modules (ReadWrite, Browse, Subscription, History, NodeManagement, TranslateBrowsePath, ServerInfo, TypeDiscovery). Add custom modules with `addModule()`, swap built-ins with `replaceModule()`**Wire Serialization**Every core / module DTO implements `WireSerializable` for safe JSON-based IPC (`opcua-session-manager` + future transports). Registry-gated `__t` discriminators enforce an explicit type allowlist at decode time**Client Introspection**`hasMethod()`, `hasModule()`, `getRegisteredMethods()`, `getLoadedModules()` surface the live method/module set for runtime dispatch decisions (used by `ManagedClient::__call()` for transparent third-party module access)**MockClient**In-memory test double — register handlers, assert calls, no TCP connection needed**Logging**Optional structured logging via any PSR-3 logger — connect, retry, errors, protocol details**Cache**Browse, resolve, and metadata read results cached (InMemoryCache, 300s TTL). Plug in any PSR-16 driver (FileCache, Laravel, Redis). Metadata cache opt-in via `setReadMetadataCache(true)`. Values are stored through `WireCacheCodec` (JSON + registry-gated type allowlist — no `unserialize()`), overridable via `setCacheCodec()`**Events**47 granular PSR-14 events — connection, session, subscription, data change, alarms, read/write, browse, cache, retry. Zero overhead when unused**Trust Store**Persistent server certificate validation — file-based trust store, 3 policies (fingerprint/expiry/full CA chain), TOFU auto-accept, CLI management**CLI Tool**[`opcua-cli`](https://github.com/php-opcua/opcua-cli) — browse, read, write, watch, discover endpoints, manage trusted certificates, and generate code from NodeSet2.xml (separate package)Documentation
-------------

[](#documentation)

Full documentation is available in [`docs/`](docs/index.md). Highlights:

SectionCovers**Getting started** — [Overview](docs/overview.md) · [Installation](docs/getting-started/installation.md) · [Quick start](docs/getting-started/quick-start.md) · [Thinking in OPC UA](docs/getting-started/thinking-in-opc-ua.md)Concepts, install, first connection**Connection** — [Endpoints &amp; discovery](docs/connection/endpoints-and-discovery.md) · [Opening &amp; closing](docs/connection/opening-and-closing.md) · [Timeouts &amp; retry](docs/connection/timeouts-and-retry.md)Connection lifecycle, discovery, retry**Operations** — [Reading](docs/operations/reading-attributes.md) · [Writing](docs/operations/writing-values.md) · [Browsing](docs/operations/browsing.md) · [Resolving paths](docs/operations/resolving-paths.md) · [Methods](docs/operations/calling-methods.md) · [Subscriptions](docs/operations/subscriptions.md) · [Monitored items](docs/operations/monitored-items.md) · [History](docs/operations/history-reads.md) · [Managing nodes](docs/operations/managing-nodes.md)Read/write, browse, subscribe, history, node management**Security** — [Overview](docs/security/overview.md) · [Policies](docs/security/policies.md) · [Certificates](docs/security/certificates.md) · [Authentication](docs/security/authentication.md) · [Trust store](docs/security/trust-store.md) · [Cache hardening](docs/security/cache-path-hardening.md)Security policies, certs, trust, cache hardening**Types** — [Overview](docs/types/overview.md) · [NodeId](docs/types/node-id.md) · [DataValue &amp; Variant](docs/types/data-value-and-variant.md) · [Extension objects](docs/types/extension-objects.md) · [Built-in types](docs/types/built-in-types.md)Type system reference**Extensibility** — [Modules](docs/extensibility/modules.md) · [Replacing modules](docs/extensibility/replacing-modules.md) · [Extension object codecs](docs/extensibility/extension-object-codecs.md) · [Type discovery](docs/extensibility/type-discovery.md) · [Wire serialization](docs/extensibility/wire-serialization.md)Modules, codecs, custom types**Observability** — [Logging](docs/observability/logging.md) · [Events](docs/observability/events.md) · [Event reference](docs/observability/event-reference.md) · [Caching](docs/observability/caching.md)Logging, PSR-14 events, caching**Testing** — [MockClient](docs/testing/mock-client.md) · [Handlers](docs/testing/handlers.md) · [Integration](docs/testing/integration.md)Test fixtures and integration suites**Reference** — [Client API](docs/reference/client-api.md) · [Builder API](docs/reference/builder-api.md) · [Exceptions](docs/reference/exceptions.md) · [Enums](docs/reference/enums.md)Public API surface**Recipes** — [Upgrading to v4.4](docs/recipes/upgrading-to-v4.4.md) · [Upgrading to v4.3](docs/recipes/upgrading-to-v4.3.md) · [Disconnection recovery](docs/recipes/disconnection-recovery.md) · [Unsupported services](docs/recipes/service-unsupported.md) · [Recursive browse](docs/recipes/browsing-recursively.md) · [Subscribing to data changes](docs/recipes/subscribing-to-data-changes.md) · [Typed arrays](docs/recipes/writing-typed-arrays.md) · [Server capabilities](docs/recipes/detecting-server-capabilities.md)Task-oriented walkthroughsTesting
-------

[](#testing)

1300+ tests with **99%+ code coverage**. Unit tests cover encoding, crypto, protocol services, and error paths. Integration tests run against [uanetstandard-test-suite](https://github.com/php-opcua/uanetstandard-test-suite) — a Docker-based OPC UA environment built on the OPC Foundation's UA-.NETStandard reference implementation, with multiple security configs, custom types, and real-world scenarios.

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

CI runs on PHP 8.2, 8.3, 8.4, and 8.5 via GitHub Actions.

Alternatives &amp; Comparison
-----------------------------

[](#alternatives--comparison)

### PHP

[](#php)

LibraryPHPDependenciesSecurity PoliciesHistory ReadAuto-BatchingNotes**php-opcua/opcua-client**8.2+`ext-openssl` only10 (6 RSA + 4 ECC)YesYesZero external deps, full binary protocol[techdock/opcua](https://github.com/TECHDOCK-CH/php-opc-ua)8.4+phpseclib, symfony/cache, monolog, ...Basic256Sha256NoYesHeavier dependency tree, still v0.2[techdock/opcua-webapi-client](https://packagist.org/packages/techdock/opcua-webapi-client)8.1+GuzzleN/A (HTTP)NoNoNeeds an OPC UA WebAPI gateway, not binary protocol[QuickOPC](https://opclabs.com/products/quickopc)COMWindows + COMYesYesN/ACommercial, Windows-only, not a real PHP packageEcosystem
---------

[](#ecosystem)

PackageDescription[opcua-client](https://github.com/php-opcua/opcua-client)Pure PHP OPC UA client (this package)[opcua-cli](https://github.com/php-opcua/opcua-cli)CLI tool — browse, read, write, watch, discover endpoints, manage certificates, generate code from NodeSet2.xml[opcua-session-manager](https://github.com/php-opcua/opcua-session-manager)Daemon-based session persistence across PHP requests. Keeps OPC UA connections alive between short-lived PHP processes via a ReactPHP daemon and Unix sockets. Separate package by design — see [ROADMAP.md](ROADMAP.md#session-manager-integration-here) for rationale.[opcua-client-nodeset](https://github.com/php-opcua/opcua-client-nodeset)Pre-generated PHP types from 51 OPC Foundation companion specifications (DI, Robotics, Machinery, MachineTool, ISA-95, CNC, MTConnect, and more). 807 PHP files — NodeId constants, enums, typed DTOs, codecs, registrars with automatic dependency resolution. Just `composer require` and `loadGeneratedTypes()`.[laravel-opcua](https://github.com/php-opcua/laravel-opcua)Laravel integration — service provider, facade, config[uanetstandard-test-suite](https://github.com/php-opcua/uanetstandard-test-suite)Docker-based OPC UA test servers (UA-.NETStandard) for integration testingCommunity
---------

[](#community)

Have questions, ideas, or want to share what you've built? Join the [GitHub Discussions](https://github.com/php-opcua/opcua-client/discussions).

**Connected a PLC, SCADA system, or OPC UA server?** We're building a community-driven list of tested hardware and software. Share your experience in [Tested Hardware &amp; Software](https://github.com/php-opcua/opcua-client/discussions/categories/tested-hardware-software) — even a one-liner like "Siemens S7-1500, works fine" helps other users know what to expect.

AI-Ready
--------

[](#ai-ready)

This package ships with machine-readable documentation designed for AI coding assistants (Claude, Cursor, Copilot, ChatGPT, and others). Feed these files to your AI so it knows how to use the library correctly:

FilePurpose[`llms.txt`](llms.txt)Compact project summary — architecture, key classes, API signatures, and configuration. Optimized for LLM context windows with minimal token usage.[`llms-full.txt`](llms-full.txt)Comprehensive technical reference — every class, method, DTO, encoding detail, security layer, and protocol service. For deep dives and complex questions.[`llms-skills.md`](llms-skills.md)Task-oriented recipes — step-by-step instructions for common tasks (connect, read, write, browse, subscribe, security, testing, Laravel integration). Written so an AI can generate correct, production-ready code from a user's intent.**How to use:** copy the files you need into your project's AI configuration directory. The files are located in `vendor/php-opcua/opcua-client/` after `composer install`.

- **Claude Code**: reference per-session with `--add-file vendor/php-opcua/opcua-client/llms-skills.md`
- **Cursor**: copy into your project's rules directory — `cp vendor/php-opcua/opcua-client/llms-skills.md .cursor/rules/opcua-client.md`
- **GitHub Copilot**: copy or append the content into your project's `.github/copilot-instructions.md` file (create the file and directory if they don't exist). Copilot reads this file automatically for project-specific context
- **Other tools**: paste the content into your system prompt, project knowledge base, or context configuration

Roadmap
-------

[](#roadmap)

See [ROADMAP.md](ROADMAP.md) for what's coming next.

Contributing
------------

[](#contributing)

Contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md).

License
-------

[](#license)

[MIT](LICENSE)

###  Health Score

46

—

FairBetter than 92% of packages

Maintenance94

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

18

Last Release

26d ago

Major Versions

v1.1.1 → v2.0.02026-03-19

v2.0.0 → v3.0.02026-03-22

v3.0.0 → v4.0.02026-03-26

### Community

Maintainers

![](https://www.gravatar.com/avatar/fb72ba5d2c05eec08d9556c0007f17a7d657d5187de1025a4a0525ace4ac8000?d=identicon)[GianfriAur](/maintainers/GianfriAur)

---

Top Contributors

[![GianfriAur](https://avatars.githubusercontent.com/u/16904504?v=4)](https://github.com/GianfriAur "GianfriAur (143 commits)")

---

Tags

iiotindustrial-automationindustry-4-0iotopc-uaopc-ua-clientopc-ua-phpopc-ua-php-clientphpclientautomationiotmodbusplcopcuaopc-uaindustrialscadasensormesIIoThmibinary-protocolhistorianindustry-4.0

###  Code Quality

TestsPest

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/gianfriaur-opcua-php-client/health.svg)

```
[![Health](https://phpackages.com/badges/gianfriaur-opcua-php-client/health.svg)](https://phpackages.com/packages/gianfriaur-opcua-php-client)
```

###  Alternatives

[symfony/symfony

The Symfony PHP framework

31.4k86.9M2.2k](/packages/symfony-symfony)[algolia/algoliasearch-client-php

API powering the features of Algolia.

69634.4M144](/packages/algolia-algoliasearch-client-php)[shopware/platform

The Shopware e-commerce core

3.4k1.5M3](/packages/shopware-platform)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.4M514](/packages/shopware-core)[web-auth/webauthn-lib

FIDO2/Webauthn Support For PHP

1237.8M120](/packages/web-auth-webauthn-lib)[web-auth/webauthn-framework

FIDO2/Webauthn library for PHP and Symfony Bundle.

51090.8k2](/packages/web-auth-webauthn-framework)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
