Quick start
Connect, read an attribute, browse a folder, and disconnect — five minutes from a fresh install to a working integration.
This page builds the smallest useful integration: connect to a server,
read its product name, list the children of the Objects folder, and
disconnect. Every later page in these docs assumes you have run code
shaped like this at least once.
The whole thing
<?php
require __DIR__ . '/vendor/autoload.php';
use PhpOpcua\Client\ClientBuilder;
use PhpOpcua\Client\Types\NodeId;
use PhpOpcua\Client\Types\StatusCode;
$client = ClientBuilder::create()
->connect('opc.tcp://localhost:4840');
// Read the server's product-name attribute (a well-known node).
$productName = $client->read(NodeId::numeric(0, 2261));
if (StatusCode::isGood($productName->statusCode)) {
echo "Connected to: " . $productName->getValue() . "\n";
}
// List the children of the Objects folder.
foreach ($client->browse(NodeId::numeric(0, 85)) as $ref) {
echo " • {$ref->displayName->text} ({$ref->nodeId})\n";
}
$client->disconnect();
Run it. You should see the server's name and a short list of folders
(Server, DeviceSet, vendor-specific roots, …).
What just happened
-
01
The builder created a client.
ClientBuilder::create()returns a fresh builder with safe defaults — no security, no authentication, aNullLogger, aNullEventDispatcher, anInMemoryCache, and the eight built-in service modules wired in. -
02
`connect()` opened a secure channel and a session.
Internally the client runs a TCP handshake (HEL/ACK), opens an OPC UA secure channel (OPN, sign/encrypt as configured), creates a session (
CreateSession), and activates it (ActivateSession). The returnedClientis inConnectionState::Connected. -
03
`read()` issued a single Read service call.
NodeId::numeric(0, 2261)builds the standard NodeId for the server's product name (namespace 0, identifier 2261). The reply is aDataValuecarrying the value, aStatusCode, and timestamps. The result is also cached in the in-memory PSR-16 store, keyed by endpoint + NodeId + attribute. -
04
`browse()` walked the address space one level.
Started at the well-known
Objectsfolder (NodeId::numeric(0, 85)), returned an array ofReferenceDescriptionobjects — one per child node — fully decoded. -
05
`disconnect()` closed the session and channel.
The client sent
CloseSessionandCloseSecureChannel, then closed the TCP socket. Subsequent calls would raiseConnectionExceptionunless you callreconnect().
NodeId strings
NodeId::numeric(0, 85) is the typed factory. The same call accepts a
string shorthand wherever the API takes a NodeId|string:
$client->read('i=2261'); // numeric, namespace 0
$client->read('ns=2;s=Devices/PLC/Speed'); // string identifier, ns 2
$client->read('ns=0;g=72962B91-FA75-4AE6-8D28-B404DC7DAE63'); // GUID
The grammar follows OPC UA Part 6. See Types · NodeId for the full set of factories and accepted formats.
Next steps
You have run a real OPC UA round-trip. The natural next reads, in order:
- Thinking in OPC UA — twenty minutes on the model (sessions, channels, address space, services). The single most useful page if you have not worked with OPC UA before.
- Connection · Opening and closing
— the lifecycle in detail, including
reconnect(). - Operations · Reading attributes
—
read(),readMulti(), the fluent builder, attribute IDs.
Tip
Run with setLogger(new \Monolog\Logger('opcua')) while you learn. The
client logs every protocol step at debug level — that is how the
mental model takes shape fastest.