Usage
Getting Started
Introduction InstallationUsage
Usage Connections Session-manager Logging-caching SecurityReference
Testing Examples Auto-publish EventsUsage
All examples assume use PhpOpcua\LaravelOpcua\Facades\Opcua; at the top of the file.
Reading Values
$client = Opcua::connect();
// String NodeId
$dv = $client->read('i=2259');
echo $dv->getValue(); // 0 = Running
echo $dv->statusCode; // 0 (Good)
// NodeId object
use PhpOpcua\Client\Types\NodeId;
$dv = $client->read(NodeId::numeric(2, 1001));
// Force a fresh read, bypassing the metadata cache
$dv = $client->read('i=2259', refresh: true);
$client->disconnect();v4.0 note:
read()now accepts an optionalbool $refresh = falseparameter. Whentrue, the client bypasses the read metadata cache and fetches the value directly from the server. Whenread_metadata_cacheis enabled in config (default), repeated reads of the same node reuse cached metadata for the data type, avoiding redundant server round-trips.
Reading Multiple Values
$client = Opcua::connect();
// Array syntax
$results = $client->readMulti([
['nodeId' => 'i=2259'],
['nodeId' => 'ns=2;i=1001'],
['nodeId' => 'ns=2;s=Temperature'],
]);
foreach ($results as $dv) {
echo $dv->getValue() . "\n";
}
// Fluent builder
$results = $client->readMulti()
->node('i=2259')->value()
->node('ns=2;i=1001')->displayName()
->execute();
$client->disconnect();Writing Values
use PhpOpcua\Client\Types\BuiltinType;
use PhpOpcua\Client\Types\StatusCode;
$client = Opcua::connect();
// Auto-detect type (v4.0) — the client reads the node's data type from the server
$status = $client->write('ns=2;i=1001', 42);
// Explicit type — still supported when you need to override auto-detection
$status = $client->write('ns=2;i=1001', 42, BuiltinType::Int32);
if (StatusCode::isGood($status)) {
echo 'Write successful';
}
$client->disconnect();v4.0 note: The
$typeparameter is now nullable (?BuiltinType $type = null). When omitted, the client auto-detects the correct OPC UA type by querying the node's data type attribute. This requiresauto_detect_write_typeto be enabled in config (default:true). Pass an explicitBuiltinTypeto skip auto-detection when you already know the type.
Writing Multiple Values
// Array syntax
$results = $client->writeMulti([
['nodeId' => 'ns=2;i=1001', 'value' => 42, 'type' => BuiltinType::Int32],
['nodeId' => 'ns=2;i=1002', 'value' => 'hello', 'type' => BuiltinType::String],
]);
// Fluent builder
$results = $client->writeMulti()
->node('ns=2;i=1001')->int32(42)
->node('ns=2;i=1002')->string('hello')
->execute();Browsing the Address Space
$client = Opcua::connect();
$refs = $client->browse('i=85'); // Objects folder
foreach ($refs as $ref) {
echo "{$ref->displayName} ({$ref->nodeClass->name})\n";
}
$client->disconnect();Browse with Caching
Browse results are cached by default. Control caching per-call:
$refs = $client->browse('i=85', useCache: false); // skip cache
$client->invalidateCache('i=85'); // clear one node
$client->flushCache(); // clear allBrowse All (Automatic Continuation)
$allRefs = $client->browseAll('i=85');Recursive Browse
use PhpOpcua\Client\Types\BrowseNode;
$tree = $client->browseRecursive('i=85', maxDepth: 3);
foreach ($tree as $node) {
echo $node->reference->displayName . "\n";
foreach ($node->children as $child) {
echo " " . $child->reference->displayName . "\n";
}
}Browse with Node Class Filter
use PhpOpcua\Client\Types\NodeClass;
$refs = $client->browse('i=85', nodeClasses: [NodeClass::Variable]);Path Resolution
$nodeId = $client->resolveNodeId('/Objects/Server/ServerStatus');
$dv = $client->read($nodeId);TranslateBrowsePaths
use PhpOpcua\Client\Types\QualifiedName;
// Array syntax
$results = $client->translateBrowsePaths([
[
'startingNodeId' => 'i=84',
'relativePath' => [
['targetName' => new QualifiedName(0, 'Objects')],
['targetName' => new QualifiedName(0, 'Server')],
],
],
]);
echo $results[0]->targets[0]->targetId->identifier; // 2253
// Fluent builder
$results = $client->translateBrowsePaths()
->path('i=84', [['targetName' => new QualifiedName(0, 'Objects')]])
->execute();Calling Methods
use PhpOpcua\Client\Types\Variant;
use PhpOpcua\Client\Types\BuiltinType;
$client = Opcua::connect();
$result = $client->call(
'i=85', // parent object
'ns=2;i=5000', // method
[
new Variant(BuiltinType::Double, 3.0),
new Variant(BuiltinType::Double, 4.0),
],
);
if (StatusCode::isGood($result->statusCode)) {
echo $result->outputArguments[0]->value; // 7.0
}
$client->disconnect();Subscriptions
$client = Opcua::connect();
// Create subscription
$sub = $client->createSubscription(publishingInterval: 500.0);
// Monitor nodes
$monitored = $client->createMonitoredItems($sub->subscriptionId, [
['nodeId' => 'ns=2;i=1001', 'clientHandle' => 1],
]);
// Or use the builder
$monitored = $client->createMonitoredItems($sub->subscriptionId)
->item('ns=2;i=1001', clientHandle: 1)
->item('ns=2;i=1002', clientHandle: 2)
->execute();
// Receive notifications
$pub = $client->publish();
echo $pub->subscriptionId;
echo $pub->sequenceNumber;
foreach ($pub->notifications as $notif) {
echo $notif['dataValue']->getValue() . "\n";
}
// Clean up
$client->deleteSubscription($sub->subscriptionId);
$client->disconnect();Modifying Monitored Items
Change sampling interval, queue size, or filters on existing monitored items without recreating them:
$results = $client->modifyMonitoredItems($sub->subscriptionId, [
['monitoredItemId' => $monitored[0]->monitoredItemId, 'samplingInterval' => 250.0],
['monitoredItemId' => $monitored[1]->monitoredItemId, 'queueSize' => 10],
]);Set Triggering
Configure triggering links so that a reporting monitored item triggers sampling of linked items:
$client->setTriggering(
$sub->subscriptionId,
triggeringItemId: $monitored[0]->monitoredItemId,
linksToAdd: [$monitored[1]->monitoredItemId],
);Subscription Transfer
After a reconnection, transfer existing subscriptions to the new session:
$results = $client->transferSubscriptions([$subscriptionId]);
if (StatusCode::isGood($results[0]->statusCode)) {
echo 'Subscription transferred';
}
// Republish unacknowledged notifications
$result = $client->republish($subscriptionId, $sequenceNumber);Historical Data
$client = Opcua::connect();
// Raw historical data
$history = $client->historyReadRaw(
'ns=2;i=1001',
new \DateTimeImmutable('-1 hour'),
new \DateTimeImmutable('now'),
);
foreach ($history as $dv) {
echo "[{$dv->sourceTimestamp->format('H:i:s')}] {$dv->getValue()}\n";
}
// Processed (aggregated) data
$history = $client->historyReadProcessed(
'ns=2;i=1001',
new \DateTimeImmutable('-1 hour'),
new \DateTimeImmutable('now'),
processingInterval: 60000.0,
aggregateType: NodeId::numeric(0, 2341), // Average
);
// Values at specific timestamps
$history = $client->historyReadAtTime('ns=2;i=1001', [
new \DateTimeImmutable('-30 minutes'),
new \DateTimeImmutable('-15 minutes'),
new \DateTimeImmutable('now'),
]);
$client->disconnect();Type Discovery
Auto-discover server-defined structured types:
$client = Opcua::connect();
$count = $client->discoverDataTypes();
echo "Discovered {$count} custom types";
// Only namespace 2
$count = $client->discoverDataTypes(namespaceIndex: 2);
// Access the codec repository
$repo = $client->getExtensionObjectRepository();
$client->disconnect();Connection State
use PhpOpcua\Client\Types\ConnectionState;
$client = Opcua::connect();
echo $client->isConnected(); // true
echo $client->getConnectionState(); // ConnectionState::Connected
$client->reconnect();
$client->disconnect();
echo $client->getConnectionState(); // ConnectionState::DisconnectedTimeout and Retry
Configure timeout, retry, and batch size through config/opcua.php per connection:
// config/opcua.php
'default' => [
'timeout' => 10.0,
'auto_retry' => 3,
'batch_size' => 100,
],v4.0 breaking change: The
OpcUaClientInterfaceno longer exposes setter methods (setTimeout(),setAutoRetry(),setBatchSize()). In direct mode, these values are set at build time viaClientBuilderand cannot be changed after connection. Configure them inconfig/opcua.phpor pass them as ad-hoc config toconnectTo(). In managed mode, setter methods remain available onManagedClient.
Certificate Trust Management
Manage trusted server certificates at runtime using the trust store:
$client = Opcua::connect();
// Trust a server certificate (DER-encoded binary)
$client->trustCertificate($derCertificateBytes);
// Remove a previously trusted certificate
$client->untrustCertificate($derCertificateBytes);
$client->disconnect();The trust store is configured per connection via trust_store_path (directory), trust_policy, auto_accept, and auto_accept_force. See Installation & Configuration for details.
Endpoint Discovery
$client = Opcua::connect();
$endpoints = $client->getEndpoints('opc.tcp://192.168.1.100:4840');
foreach ($endpoints as $ep) {
echo "{$ep->securityPolicyUri} ({$ep->securityMode->name})\n";
}
$client->disconnect();