| eyebrow | Docs · Operations | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| lede | Write one tag or many. The library detects the right OPC UA type for you by default; pass an explicit BuiltinType when you need to override that decision. | |||||||||||||||
| see_also |
|
|||||||||||||||
| prev |
|
|||||||||||||||
| next |
|
write() updates a node's Value attribute. Attribute-level writes
(e.g. changing a DisplayName) are theoretically possible via the OPC
UA Write service but rare in practice and not exposed on this library's
typed API — for those, drop down to a custom module.
The target node.
The PHP value to write. Accepts bool, int, float, string,
DateTimeImmutable, NodeId, Variant, ExtensionObject, and arrays
of any of the above.
Override the OPC UA type used on the wire. When null, the library
auto-detects the type — see "Type detection" below.
use PhpOpcua\Client\Types\StatusCode;
$status = $client->write('ns=2;s=Devices/PLC/Setpoint', 42.5);
if (! StatusCode::isGood($status)) {
throw new RuntimeException(
'Write rejected: ' . StatusCode::getName($status)
);
}The return value is the per-item StatusCode (an int). A Good
status (0) means the server accepted the write. Common bad statuses:
| StatusCode | Meaning |
|---|---|
BadNodeIdUnknown |
The node does not exist on this server |
BadUserAccessDenied |
Session is not authorised to write |
BadTypeMismatch |
The value does not match the node's DataType |
BadOutOfRange |
Value is outside the declared engineering range |
BadWriteNotSupported |
The attribute is read-only on this server |
By default, the builder enables write-type auto-detection
(setAutoDetectWriteType(true)). When $type is omitted, the client:
-
Checks the metadata cache.
If the node's
DataTypeis already cached, use it directly — no server round-trip. -
Otherwise, reads the node's
DataTypeattribute.Dispatches
WriteTypeDetecting, issues a Read, and caches the result. The detection adds one round-trip on the first write to each node. -
Maps the OPC UA
DataTypeNodeId to aBuiltinType.Standard built-ins (
Boolean,Int32,Double,String, …) map directly. Custom DataTypes that resolve to a built-in via their supertype chain also map. -
Encodes the PHP value as that built-in.
Dispatches
WriteTypeDetectedwith the chosen type and afromCacheflag, then sends the WriteRequest.
Disable detection when you want absolute control:
$client = ClientBuilder::create()
->setAutoDetectWriteType(false)
->connect('opc.tcp://plc.local:4840');
// Now $type is mandatory.
$client->write('ns=2;s=Tag', 42, BuiltinType::Int32);WriteTypeDetectionException is raised when:
- The
DataTyperead returns a bad status. - The DataType cannot be mapped to a
BuiltinType(a structure without a registered codec, an unknown abstract type).
WriteTypeMismatchException is reserved for cases where an explicit
$type passed by the caller would clash with a known DataType. The
library does not currently raise it during normal write paths — the
class exists for custom validation code and future static-analysis
hooks.
use PhpOpcua\Client\Types\BuiltinType;
$statuses = $client->writeMulti([
['nodeId' => 'ns=2;s=Setpoint', 'value' => 42.5],
['nodeId' => 'ns=2;s=Mode', 'value' => 1, 'type' => BuiltinType::Int32],
['nodeId' => 'ns=2;s=Label', 'value' => 'auto'],
]);
foreach ($statuses as $i => $status) {
if (! StatusCode::isGood($status)) {
// Inspect the i-th entry
}
}The return is an int[] parallel to the request array.
$statuses = $client->writeMulti()
->node('ns=2;s=Setpoint')->value(42.5)
->node('ns=2;s=Mode')->int32(1)
->node('ns=2;s=Label')->string('auto')
->execute();The builder exposes one method per BuiltinType (boolean, byte,
int16, uint16, int32, uint32, int64, uint64, float,
double, string, …). Each fixes the wire-type for that entry and
skips auto-detection.
| Builder method | OPC UA type |
|---|---|
value(mixed) |
auto-detected |
typed(mixed, BuiltinType) |
explicit |
boolean(bool) |
Boolean |
sbyte(int) / byte(int) |
SByte / Byte |
int16(int) / uint16(int) |
Int16 / UInt16 |
int32(int) / uint32(int) |
Int32 / UInt32 |
int64(int) / uint64(int) |
Int64 / UInt64 |
float(float) |
Float |
double(float) |
Double |
string(string) |
String |
For any built-in type without a dedicated method (ByteString,
DateTime, LocalizedText, NodeId, Variant, …) reach for
typed($value, BuiltinType::ByteString) (or the matching BuiltinType
case) instead.
Arrays use the corresponding Variant array form. The library detects
"array of T" automatically when auto-detect is on; with explicit types,
the same BuiltinType applies to every element.
$client->write('ns=2;s=Setpoints', [10.0, 20.0, 30.0]);
// Auto-detected as Variant<Double[]> if the node's DataType is Double.
$client->write('ns=2;s=Setpoints', [10.0, 20.0, 30.0], BuiltinType::Double);
// Explicit — works even when auto-detect is off.For mixed-type arrays, use Variant directly or write multiple
individual values. See Recipes · Writing typed
arrays.
The write path dispatches three PSR-14 events:
WriteTypeDetecting— before detection starts (carries the node)WriteTypeDetected— after detection (carriesdetectedTypeandfromCache)NodeValueWritten— on success (carries the value and the status code)NodeValueWriteFailed— on a bad status code (carries the failure details)
Wire a dispatcher to instrument write traffic — see Observability · Events.