maillotf/ardaccess-bridge-bundle
maillotf/ardaccess-bridge-bundle is a PHP bridge bundle for integrating ARD Access into your application. It provides configuration and service wiring to simplify connecting access-control workflows and reduce setup boilerplate. Ideal for Laravel/PHP projects that need a clean integration layer.
This is a Symfony bundle, not a Laravel package — there is no extra.laravel.providers entry, no config publish tag, and no facade. Treat composer require maillotf/ardaccess-bridge-bundle as installing a library you must wire up yourself.
Minimal path in a Laravel app:
composer require maillotf/ardaccess-bridge-bundle (pin the version — see Gotchas).config/services.php (or a dedicated config/ardaccess.php) reading from .env:
'ardaccess' => [
'protocol' => env('ARDACCESS_PROTOCOL', 'http'),
'host' => env('ARDACCESS_HOST'),
'port' => env('ARDACCESS_PORT', 80),
'username' => env('ARDACCESS_USERNAME'),
'password' => env('ARDACCESS_PASSWORD'),
],
services.yaml alias maps MaillotF\Ardaccess\ArdaccessBridgeBundle\Service\ArdaccessService to the internal @ardaccess.service, so mirror that:
$this->app->singleton(ArdaccessService::class, function ($app) {
return new ArdaccessService($app['config']['services.ardaccess']);
});
Check the constructor signature in vendor/maillotf/ardaccess-bridge-bundle/Service/ArdaccessService.php first — the Symfony version takes DI'd config, so you may need to build the underlying client and pass it in.app(ArdaccessService::class)->carrier->ListCarriers(). If that returns without throwing, auth, host, port and protocol are correct; everything else is payload shape.Where to look first: the docs/README.md table of contents on GitHub (the release notes only link it), then Service/ArdaccessService.php to see how carrier, supervision, creator and the smart-object helper are exposed.
Wrap it, don't sprinkle it. Inject ArdaccessService into a small ArdAccess gateway class (or repository per domain: carriers, events, smart objects), and depend on that in controllers and jobs. It keeps the chained magic-API calls out of your HTTP layer and gives you one place to fake in tests.
final class ArdAccessGateway
{
public function __construct(private ArdaccessService $aas) {}
public function carriers(): array
{
return $this->aas->carrier->ListCarriers();
}
}
Two builder idioms, both fluent. Attributes and criteria are accumulated by a builder object and flushed by a terminal call:
creator->addAttribute(...)->...->getAttributes() → array passed to carrier->Carrier(null, 'u', $attributes).creator->newCriterion('date','>',946681200)->addSubCriterion('example','=','value')->addCriterion()->newCriterion(...)->addCriterion()->getCriterionsArray() → passed to supervision->ListEvents(null, $criterions).The addCriterion() call closes the current criterion and returns the creator; keep that ordering (sub-criteria before the closing addCriterion()) and only call getCriterionsArray()/getAttributes() once, at the end. Carrier(null, 'u', ...) uses null for the id and a mode flag ('u') to signal update — treat those string flags as an enum and centralise them in constants so a typo is a compile-time-ish error rather than a silent bad write.
Mutations belong in jobs. Updating carrier attributes or handing back smart objects is a write against a physical access-control system. Push it through a queued job with retry, so a network blip doesn't leave a half-applied user record, and log the payload (minus credentials) for audit.
Smart-object handback is a boolean contract and the docs compare strictly:
if ($aas->getSmartObjectHelper()->handbackSmartObject($id) === true) { ... }
Model this as a Result/exception inside your gateway rather than returning true|false up the stack, so controllers stay declarative.
Caching and read-heavy screens. ListCarriers() and ListEvents() are the calls that will show up in list/filter screens. Cache carrier lists (Cache::remember with a short TTL, busted on your own writes) and never call them per row.
Testing. Because the service is a concrete class with an internal HTTP client, bind a stub in the container in tests: $this->app->instance(ArdaccessService::class, $fake) on the gateway binding, or $this->app->instance(ArdAccessGateway::class, ...) and test around it. Http::fake() will not intercept these calls — the client isn't Laravel's HTTP client. For integration tests, point ARDACCESS_HOST at a local mock server.
vendor:publish, and the documented services.yaml/framework.yaml snippets are dead weight in Laravel. You are hand-rolling the container binding; if the constructor expects a Symfony-configured client rather than an array, wrap it in a small factory and keep that glue in one provider. Also note the release notes put the ardaccess: block under framework.yaml, which is almost certainly a doc slip — it belongs in the bundle's own config file; don't paste it into config/app.php expecting anything to happen.ardaccess.authentication.*, not flat. In Laravel you're flattening it into config/services.php, so decide the array shape once and match whatever the constructor actually reads — mismatch here yields a client pointed at 127.0.0.1:80 and confusing connection errors rather than a validation message.protocol: http, port 80, username/password auth — credentials cross the wire in a Basic header. Keep this on a trusted network segment, force https where the endpoint supports it, and make sure the password never lands in Laravel's exception output (add it to config/app.php's dontflash/log-scrubbing).=== true. Assume the API can return 1, "true" or null depending on version; normalise the return in your gateway instead of copying === true around, or successful handbacks will silently look like failures.begindate/enddate are shown as Unix timestamps (seconds), usergroup as a comma-separated string ('171,233'), rid/uid as integers. The chained addAttribute() does no validation, so a DateTime object or a millisecond timestamp goes straight to the API and fails there, not here. Cast and validate at the edge of your gateway.null ids/mode flags are positional. Wrap calls in try/catch, check for null/empty arrays before iterating, and log the raw response body on unexpected shapes — this is the single biggest time-saver when something returns "nothing".1.0.2 on an early-1.x release with a thin README means BC breaks are plausible between minors. Pin an exact version in composer.json and read the changelog before bumping.ARDACCESS_HOST/PORT at it, and dump the request to see exactly what path, headers and payload the bundle builds — faster than reading the vendor source.ArdaccessService (or decorate it) and rebind the container entry to your subclass; that's the cleanest hook for adding retry, logging or response normalisation without forking the bundle.How can I help you explore Laravel packages today?