proglab/selligent-client-bundle
A Symfony bundle that integrates the Selligent marketing automation client into your application, providing service configuration and a convenient wrapper for Selligent's REST API so you can manage contacts, segments, and campaigns from Symfony services.
The bundle is small (1 star, no dependents) and acts as a thin Symfony service wrapper around the Selligent SOAP/REST client. Treat it as glue code, not a framework.
composer.json before you commit:
composer require proglab/selligent-client-bundle
config/bundles.php (it predates Flex auto-registration in most cases):
Proglab\SelligentClientBundle\SelligentClientBundle::class => ['all' => true],
config/packages/selligent.yaml:
selligent_client:
base_url: '%env(SELLIGENT_BASE_URL)%'
client_id: '%env(SELLIGENT_CLIENT_ID)%'
client_secret: '%env(SELLIGENT_CLIENT_SECRET)%'
DependencyInjection/Configuration.php to see the exact config keys the package actually binds — the README may not match the code. Then autowire the client into a controller or command and make a single, read-only call (e.g. fetch a contact or list segments) to confirm the WSDL/endpoint and auth work before building anything else.The fastest sanity check is a one-line Symfony command:
$this->client->getContact($email);
If that returns a hydrated response, the rest of the API surface is reachable.
Inject the client, don't new it. The bundle exposes a service (typically selligent_client / SelligentClient). Autowire by type or alias it in services.yaml (Proglab\...\Client $selligent: '@selligent_client'). This keeps testability intact and lets you swap in a mock for unit tests.
Wrap calls behind a repository/service layer. Selligent's API is SOAP-flavoured and returns transport-shaped DTOs. Don't let those leak into your domain. Create a SelligentContactRepository that maps your User/Subscriber entity to the payload and back. This is the single highest-value pattern because it isolates every upstream quirk behind one seam.
Use environment-specific configs. Selligent almost always gives you separate pre-prod and production orgs with distinct base_url and credentials. Wire them into per-env .env files (.env.test.local, .env.prod) so an integration test suite can hit the sandbox safely.
Batch and queue for writes. For contact sync, subscribe, or segment updates, don't call Selligent synchronously in a request. Push jobs onto Symfony Messenger and consume them with a worker that owns the Selligent client. You get built-in retry (RetryStrategy in messenger.yaml), failed-message storage, and throttling for free.
Sync-back pattern for reads. For dashboards, cache Selligent lookups behind Symfony Cache with a short TTL. The SOAP roundtrip is slow and the package adds little caching of its own.
Testing: Because this is a small package, stub the client in functional tests with a Symfony service mock ($container->set('selligent_client', $fake)), and reserve real API calls for a dedicated integration test group gated by an env flag.
Maturity risk is real. One star and zero dependents means no community safety net. Pin the version ("proglab/selligent-client-bundle": "~1.2" or the exact commit), read the source in vendor/ once, and be prepared to fork. If it's abandoned, the fork is yours.
SOAP WSDL loading is slow and brittle. The underlying client caches the WSDL in memory — cold requests pay the full fetch. Either warm it in a console command at deploy time (cache:warmup won't do it; write your own), or run a long-lived Messenger worker so the client stays warm. If you're behind a proxy, set SOAP_CLIENT options (timeout, proxy) on the client — check whether the bundle exposes these or whether you need to decorate the service.
Errors are transport failures, not HTTP 4xx. SOAP faults will throw SoapFault or the library's own exception classes, and the bundle may not normalize them. Wrap every call in a single decorator that catches both and rethrows a domain SelligentException, otherwise try/catch logic scatters across your codebase.
Config key drift. The README likely lists keys the Configuration.php doesn't define (or vice versa). Always validate by dumping the container: bin/console debug:container selligent_client --show-arguments. If a key is silently ignored, that's why.
Credentials in config, not env-in-config. Use %env(SELLIGENT_CLIENT_SECRET)% — never a literal secret in selligent.yaml, or you'll leak it to anyone who can read config/ in the repo.
Rate limits and timeouts. Selligent orgs are frequently metered per client. Set conservative RetryStrategy on Messenger (e.g. max_retries: 3, delay: 2000, multiplier: 2), and log every failed payload so you can replay without re-deriving it.
Debugging: enable the underlying library's logging if it supports PSR-3 (check the constructor in vendor/). If not, decorate the client service with a logging wrapper via a compiler pass or services.yaml decorates: — the package's small surface makes it easy to intercept.
Extension points are thin by design. Don't expect events, subscribers, or a rich API. The realistic extension moves are: (a) decorate the client service, (b) fork and add methods, (c) skip the bundle and use the underlying Selligent\Client library directly if the bundle's configuration is in your way. Given its size, option (c) is often cleaner for anything non-trivial.
How can I help you explore Laravel packages today?