laravel-opcua · v4.3.x
Docs · Using the client

Using builders

Fluent builders for read, write, browse, and monitored items. You get them by calling readMulti() / writeMulti() / createMonitoredItems() / translateBrowsePaths() with no arguments. Same surface as opcua-client — through the Laravel facade.

opcua-client exposes fluent builders for the batched operations. The convention is the same on every batch method: call it with no arguments to get the builder, call it with an array to run immediately.

Builder Got from Finaliser Returns
ReadMultiBuilder Opcua::readMulti() execute() DataValue[]
WriteMultiBuilder Opcua::writeMulti() execute() int[]
MonitoredItemsBuilder Opcua::createMonitoredItems($subId) execute() MonitoredItemResult[]
BrowsePathsBuilder Opcua::translateBrowsePaths() execute() BrowsePathResult[]

There is no readBuilder() / writeBuilder() / browseBuilder() / callBuilder() / historyBuilder() on the facade. The one-shot methods (read, write, browse, call, historyRead*) take their own positional arguments and don't return a builder.

Read — one-shot vs builder

php one-shot read
$dv = Opcua::read('ns=2;s=Speed');                     // Value
$dv = Opcua::read('ns=2;s=Speed', AttributeId::DisplayName);  // any attribute

Batched read via readMulti():

php builder — batch read
$values = Opcua::readMulti()
    ->node('ns=2;s=Speed')
    ->node('ns=2;s=Temperature')
    ->node('ns=2;s=Pressure')
    ->execute();

// $values is array<int, DataValue>, indexed in the order added

execute() always returns an array, even for one entry.

Write — one-shot vs builder

php one-shot write
$status = Opcua::write('ns=2;s=Setpoint', 75.0);
// Or with an explicit BuiltinType:
$status = Opcua::write('ns=2;s=Setpoint', 75.0, BuiltinType::Float);

Batched write via writeMulti(). Each item is a node() followed by either value() (auto-detect) or typed() (explicit BuiltinType):

php builder — batch write
use PhpOpcua\Client\Types\BuiltinType;

$statuses = Opcua::writeMulti()
    ->node('ns=2;s=Setpoint')->value(75.0)
    ->node('ns=2;s=Mode')->value('Auto')
    ->node('ns=2;s=EnableAlarm')->typed(true, BuiltinType::Boolean)
    ->execute();

See Operations · Writing for the type detection rules.

Browse

browse() and browseRecursive() are positional — no fluent builder. Use the positional BrowseDirection, referenceTypeId, includeSubtypes, and nodeClasses arguments to filter:

php filtered browse
use PhpOpcua\Client\Types\BrowseDirection;
use PhpOpcua\Client\Types\NodeClass;
use PhpOpcua\Client\Types\NodeId;

$results = Opcua::browse(
    nodeId:          'ns=2;s=Folder',
    direction:       BrowseDirection::Forward,
    referenceTypeId: NodeId::numeric(0, 35),       // Organizes
    includeSubtypes: true,
    nodeClasses:     [NodeClass::Variable],
);

Recursive browse — useful for tag discovery ($maxDepth is the third positional argument, so use the named form):

php browseRecursive
$tree = Opcua::browseRecursive('ns=4;s=Tags', maxDepth: 5);

See Operations · Browsing.

Translate browse paths

php translate browse paths
$results = Opcua::translateBrowsePaths()
    ->add(startingNodeId: 'ns=2;s=Folder', browsePath: '/Speed')
    ->add(startingNodeId: 'ns=2;s=Folder', browsePath: '/Temperature')
    ->execute();

Subscriptions / monitored items

Subscriptions are created with createSubscription(); monitored items are attached with createMonitoredItems() (which returns the MonitoredItemsBuilder when called with no $items array):

php subscription + monitored items
$sub = Opcua::createSubscription(publishingInterval: 500.0);

Opcua::createMonitoredItems($sub->subscriptionId)
    ->add('ns=2;s=Speed',       clientHandle: 1)
    ->add('ns=2;s=Temperature', clientHandle: 2)
    ->execute();

Listen via Event::listen(DataChangeReceived::class, …) for notifications. See Operations · Subscriptions and Events · Data events.

Method calls

call() takes its arguments positionally — no callBuilder():

php method call
$result = Opcua::call(
    objectId:        'ns=2;s=Recipe',
    methodId:        'ns=2;s=Recipe.Load',
    inputArguments:  ['NewRecipe', 42],
);

// $result->statusCode + $result->outputArguments

See Operations · Method calls.

Chainable with connection()

Builders are rooted in a connection — call them on the result of Opcua::connection('name'):

php builder on named connection
$values = Opcua::connection('historian')
    ->readMulti()
    ->node('ns=4;s=Tag1')
    ->node('ns=4;s=Tag2')
    ->execute();

The chain reads left-to-right: choose connection, open the builder, add items, execute.

Async / queued builders

There's no async builder. PHP OPC UA is synchronous. To run a read off the request thread, dispatch a job:

php job → builder
class SampleBatch implements ShouldQueue
{
    public function __construct(public array $nodeIds) {}

    public function handle(OpcuaManager $opcua): void
    {
        $b = $opcua->readMulti();
        foreach ($this->nodeIds as $node) {
            $b->node($node);
        }
        $values = $b->execute();
        // ... persist
    }
}

See Horizon and queues.

When to skip the builder

If the call is one node, one value, one attribute — use the shortcut form. The builder is for batching.

Operation Shortcut Use builder when…
Read one Value Opcua::read() Batching multiple nodes
Write one Value Opcua::write() Batching multiple writes
Browse one folder Opcua::browse() No builder — use positional filters
Method call Opcua::call() No builder
History read Opcua::historyReadRaw() / etc. No builder — three flat methods

Reference

The builder classes are documented in opcua-client's reference docs. The Laravel package adds nothing on top — the chain you call through Opcua::readMulti() (etc.) is the same one documented upstream.

You've finished Using the client. Move on to Operations for the per-operation deep dives.

Documentation