cleverage/soap-process-bundle
CleverAge/SoapProcessBundle adds SOAP integration to the CleverAge ProcessBundle, helping Symfony applications configure and run SOAP-based process tasks. Part of CleverAge’s process tooling, MIT licensed, with usage docs included.
cleverage/soap-process-bundle is a Symfony bundle (not a Laravel package) that wires SOAP clients into cleverage/process-bundle pipelines. There is no service provider and no publishable config — the whole value proposition is a soap_request task and a matching transformer you drop into an existing process. If you are in a Laravel codebase, budget for the fact that you are adopting a Symfony process engine alongside it.
Install (PHP ^8.2 — note the constraint is now ^8.2, not >=8.2, so PHP 9 is refused until tested):
composer require cleverage/soap-process-bundle:^3.3
This pulls cleverage/process-bundle ^5.4, psr/log ^2|^3, symfony/service-contracts, the PHP 8.3–8.5 polyfills, and symfony/deprecation-contracts. symfony/finder is no longer needed and symfony/flex is no longer whitelisted — drop both from your plugin allow-list if you copied old docs.
Register the bundle in config/bundles.php (CleverAgeSoapProcessBundle::class => ['all' => true]) and read UPGRADE.md#v33 before you deploy.
First use case — one client, one task. Write a client, give it a code, and reference that code from the task:
namespace App\Soap;
use Cleverage\SoapProcessBundle\Attribute\AsSoapClient;
use Cleverage\SoapProcessBundle\Client\Client;
#[AsSoapClient(code: 'inventory')]
final class InventoryClient extends Client
{
public function getCode(): string
{
return 'inventory';
}
}
getCode() must return the same string as the attribute. Then use task: soap_request in the process that needs it. Look first at RequestTask, RequestTransformer and ClientRegistry in the source — they are the entire public surface.
code attribute or the tag's code attribute — never bare tagsClients are resolved lazily from a service locator keyed by code. A client is only instantiated when a task or transformer actually uses it, which means a broken client configuration no longer fails processes that never touch it. The old eager path still exists but is deprecated:
// Deprecated — ClientRegistry::addClient() will be removed in 4.0
$registry->addClient($client);
// Preferred
#[AsSoapClient(code: 'inventory')] // autoconfiguration
// or, in services.yaml:
// tags: [{ name: 'cleverage.soap.client', code: 'inventory' }]
The code must be unique and non-empty — duplicates and empty strings now fail container compilation, which is a much better failure mode than the previous silent overwrite.
ClientRegistry, don't reach into the containerClientRegistry is autowirable by class name (new optional constructor argument takes the locator), so inject it normally. Fetch the task and transformer by class name, not by their old ids:
use Cleverage\SoapProcessBundle\Task\RequestTask;
use Cleverage\SoapProcessBundle\Transformer\RequestTransformer;
public function __construct(
private RequestTask $task,
private RequestTransformer $transformer,
) {}
cleverage_soap_process.task.request and cleverage_soap_process.transformer.request still work as aliases but are deprecated and removed in 4.0.
Both the task and the transformer carry the code soap_request, so newer cleverage/process-bundle configurations can reference them by code instead of service:. Referencing by service is deprecated upstream — migrate process definitions to task: soap_request now and you avoid doing it twice.
ProcessExceptionInterface, keep your existing catch blocksThe bundle no longer throws raw SPL exceptions. It throws UnexpectedValueException, InvalidArgumentException and RuntimeException that extend the SPL classes and implement ProcessExceptionInterface. Existing catch (\RuntimeException $e) continues to work, but new code should catch the interface so process-level handling stays uniform:
use Cleverage\ProcessBundle\Exception\ProcessExceptionInterface;
try {
// task execution
} catch (ProcessExceptionInterface $e) {
// same handling for every step in the process, not just SOAP
}
MissingClientException::create(string $code) is now typed — it stays open for extension, unlike the rest of the API.
Because clients are lazy, you can unit-test a client in isolation without booting the process engine. For integration tests, assert on the task code and the client code rather than on service ids, and assert the log message Soap call failed for negative paths.
The extension alias is cleverage_soap_process (it was misspelled clever_age_soap_process, and no option was ever read from either key — they were ignored silently). The bundle now ships an intentionally empty Configuration, emits a notice at container compile time if you configure it, and will reject the keys in 4.0.
config/packages/cleverage_soap_process.yaml entirely. WSDL/endpoint settings live on your Client subclass (constructor args, SoapClient options), not in bundle config. Any snippet telling you to publish config/soap_process.php or set clients.example.wsdl is wrong.Documented explicitly in this release: a client marked shared is reused between two process executions in a long-running worker. Any per-call state you stash on the client — headers, tokens, last response, a mutable \SoapClient — leaks into the next job. Either reset it at the start of each task or hold nothing mutable on the client. This is the single most likely source of "works in dev, wrong data in prod" bugs.
RequestTask, RequestTransformer, ClientRegistry, CleverAgeSoapProcessBundle are @final since 3.3. Extending them now logs a deprecation through Symfony's DebugClassLoader. Only Client and MissingClientException are meant to be extended — put your customisation there.CleverAgeSoapProcessExtension and RegisterClientsPass are @internal; do not compile-pass against them.container.private — fetching them directly from the container is deprecated and they go private in 4.0.SYMFONY_DEPRECATIONS_HELPER=max[self]=0 for a release cycle to catch all of the above early.Two things changed, one of which will silently break dashboards:
RequestTask previously reported failures as Empty resultset for query, which was misleading. It now logs Soap call failed — same level, same log context. Grep your log-based alerts and saved searches for the old string.monolog.logger and therefore logged on the app channel, without process context. It now injects logger and logs on the cleverage_process_task channel of its monolog.logger tag. If you were filtering on app, those entries have moved — and they now actually appear in the process execution logs in the UI.trace on the underlying SoapClient options in your client subclass and dump the raw request/response from inside the task — there is no bundle-level toggle.cleverage_process_task, not app.code matches getCode() exactly — a mismatch between the attribute and the method is the most common misconfiguration.psr/log ^2|^3 is required directly: TaskLogger and the test loggers use typed LoggerInterface signatures, and psr/log 1 is a fatal error, not a warning.dist archive excludes .github/, .docker/, tests/, quality tooling and PHPUnit configs via .gitattributes — do not expect to read the tests from vendor/.^8.2 even though the code may use 8.3–8.5 functions (via symfony/polyfill-php83/84/85). Don't assume the presence of a polyfilled function means the polyfill package is optional.How can I help you explore Laravel packages today?