php-opcua/symfony-opcua
Symfony bundle for integrating OPC UA client functionality into Symfony apps. It provides configuration and service wiring to connect to OPC UA servers, browse nodes, and read or write industrial automation data from PHP services.
Architecture fit
php-opcua/opcua-client + opcua-session-manager. v4.3.0 does not change that layering; it extends the observability seam (OpcuaManager now owns logger resolution) and hands more wire/protocol behaviour to the upstream client.config('logger') → config('log_channel') → default logger. This is a sensible Laravel-shaped design (channel names in config, LoggerInterface resolved at runtime), and the bundle-side ServiceLocator → monolog.logger.<channel> wiring means OPC UA connection logs can land in the same channels as the rest of the app. That is a genuine operational win for a Laravel shop: no bespoke log plumbing, existing config/logging.php conventions apply.useConsoleLogger() with millisecond timestamps is aimed at artisan/daemon contexts. For us the realistic use is scheduled commands and the long-lived daemon, not HTTP requests.?\Closure $loggerResolver 5th constructor arg is BC-safe by signature, but it does mean OpcuaManager is now harder to construct by hand in tests — expect to go through the container or the provided factory in our own test suite.Integration feasibility
composer.json before we commit; that is the single most likely blocker.Technical risk
unserialize() is removed from every cache path; WireCacheCodec (JSON, allowlist-gated) is the new default. Pre-v4.3 entries are silently discarded on first access, and persistent caches must be flushed. Two distinct risks:
unserialize(). Rollback is therefore not clean unless we flush again on the way back. Treat the cache as version-scoped.NodeManagementModule re-enters the default module list. Node add/delete and reference add/delete become reachable through the manager by default. On servers lacking the service set, the first call raises ServiceUnsupportedException. It is a subclass of ServiceException, so existing broad catch (ServiceException) handlers still match — which is exactly the hazard: handlers written for transport failures will now silently absorb "this server doesn't do NodeManagement", and callers may proceed believing a node was created. We should narrow our catches on the write paths.ServiceFault now decodes to ServiceException instead of EncodingException: Buffer underflow. Better semantics; but any alert or dashboard keyed on EncodingException / "Buffer underflow" text will go quiet. Alert rules need auditing.RequestHeader.timestamp as valid UtcTime, anonymous policyId discovery across security modes, NodeManagement TypeIds pointing at DefaultBinary encodings, ECC sequence numbers per OPC UA 1.05.4) mean open62541 and other strict stacks that previously failed will now connect. Good news, but it means new endpoints and new traffic may appear at runtime, and previously "known-bad" servers in our inventory may start succeeding.umask(0077), NDJSON 64 KiB per-frame cap, socket path length validation pre-bind, PID-check fallback, --version, credential/path redaction) is net-positive security posture, but the 64 KiB cap is a hard behavioural limit — any consumer streaming large payloads through the daemon will now be truncated/rejected at the frame boundary. Must be validated against our largest browse/read responses.Key questions
config/opcua.php expose log_channel per connection, and is that key validated? What happens when monolog.logger.<channel> does not exist in config/logging.php — exception at connect time, or silent fallback to default?loggerResolver closure mandatory for log_channel to work, or does the provider wire the ServiceLocator automatically? (i.e. do we get the feature for free, or must we republish config/provider bindings?)setLogger() propagation to existing connections is described as "best-effort" — which connections are missed, and are they missed silently?NodeManagementModule out of the default list (config flag or builder method)? If not, this is a capability expansion we cannot opt out of.php-opcua/opcua-client ^4.2.0 → ^4.3.0 resolved with any transitive bumps that overlap our existing pins? Is there a coordinated release note on the client side for the cache codec?--version output map to the client library version, and can we assert it in health checks?Stack fit
config/opcua.php published per environment, logging through the framework's channel system. Nothing here fights Laravel conventions and nothing introduces a new runtime (no queue worker, no sidecar) beyond the daemon we would already run for persistent sessions.monolog.logger.<channel> mapping means OPC UA logs inherit our existing retention, formatting, and shipping pipeline — no new log sink, no new parser.useConsoleLogger() fits the "artisan command that talks to a PLC" pattern, which is the majority of our use cases.Migration path
composer update --dry-run on a scratch branch. Read the upstream opcua-client 4.3.0 changelog for the codec and NodeManagement defaults.config/opcua.php to pick up log_channel; explicitly define the channels we intend to use in config/logging.php before referencing them; add a boot-time assertion (or a config test) that every configured log_channel resolves to a defined channel.EncodingException, Buffer underflow, ServiceException, and ServiceFault. Decide per call site whether ServiceUnsupportedException should be caught locally (NodeManagement paths) or allowed to surface.DaemonException).Compatibility
OpcuaManager directly is unaffected (optional 5th param), but subclass overrides of the constructor must be updated.ServiceFault-shaped errors must be re-verified: same class family, different originating condition.Sequencing
--version; confirm log volume and timestamp format downstream.Maintenance
log_channel per connection, loggerResolver closure, optional setCacheCodec() override). Each is a place where an environment can drift from the others, so config should stay in version control with the channel-existence test alongside it.^4.2 to ^4.3.0/^4.3.1; that is a normal minor-bump cadence but the codec change makes this release equivalent in risk to a major.Support
useConsoleLogger()'s millisecond default is a support-friendly default (correlating OPC UA calls with application logs was previously guesswork). Keep it.username no longer leaked via daemon list, Windows path/URL scrubbing in errors) reduce our exposure when customers paste logs into tickets. Worth calling out to the support team as a reason to prefer v4.3 logs over older ones.Scaling
setLogger() override is best-effort across existing connections — in a high-connection-count process the override may not reach every live connection, so treat it as an incident-time convenience, not a reliable fleet-wide switch.NodeManagementModule default-on means every manager instance carries a slightly larger module set; negligible, but it also means every connection is now capable of browse-tree mutation. Governance, not CPU, is the constraint.unserialize() to allowlisted JSON: expect somewhat larger cache entries and slower decode, but no unserialize() deserialization attack surface and no class-loading side effects. If we cache aggressively across many tags, this is a modest size/storage increase worth quantifying in staging.Failure modes
ServiceException catch on NodeManagement paths: node creation silently "succeeds" against servers without the service set. This is a correctness failure with a long detection latency — the node simply isn't there weeks later.DaemonException instead of a kernel-truncated bind. Still a startup failure, and one that will surface on first deploy if any environment sits near the path limit. Check envs with long storage_path./proc is in play, the daemon may behave conservatively — verify it doesn't refuse to start where it previously did.EncodingException: Buffer underflow go silent — a monitoring failure mode, not a runtime one, which is precisely why it will be missed.Ramp-up
setLogger, getLogger, useConsoleLogger) and needs no Monolog knowledge in config files — that is the explicit design goal of log_channel.--version, socket path validation, frame caps, and the reclassification of previously "unsupported" servers all change operational expectations.How can I help you explore Laravel packages today?