Symfony integration
This guide targets Symfony 6.4+ running on PHP 8.2 or later. The avsbhq/avsb-phppackage includes a Symfony Bundle that registers the SDK in Symfony's dependency-injection container, wires per-request context scoping as an event subscriber, and exposes the client for injection into controllers and services. By the end you will be reading flags via constructor injection and tracking events with zero boilerplate.
Install
1composer require avsbhq/avsb-phpObtain your SDK key
Open your A vs B project, go to Settings → Environments, and copy the Server SDK key. Store it in your .env file and reference it from the bundle config:
1AVSB_SDK_KEY=sdk_production_...Enable the bundle
1<?php2
3return [4 // ... existing bundles ...5 Avsb\Symfony\AvsbBundle::class => ['all' => true],6];Configure the bundle
1avsb:2 sdk_key: '%env(AVSB_SDK_KEY)%'3
4 # Optional: build the EvalContext from the current Request.5 # This callable is called once per request by the event subscriber.6 context_from: App\Avsb\RequestContextFactoryCreate the context factory class referenced above:
1<?php2
3namespace App\Avsb;4
5use Avsb\Symfony\ContextFactoryInterface;6use Symfony\Component\HttpFoundation\Request;7
8final class RequestContextFactory implements ContextFactoryInterface9{10 public function fromRequest(Request $request): array11 {12 $user = $request->attributes->get('_user');13
14 return [15 'kind' => 'user',16 'key' => $user?->getId() ?? 'anon',17 'plan' => $user?->getPlan() ?? 'free',18 ];19 }20}Inject the client into a controller
Type-hint Avsb\Client in your controller constructor. Symfony autowires the request-scoped instance that the bundle registered.
1<?php2
3namespace App\Controller;4
5use Avsb\Client as AvsbClient;6use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;7use Symfony\Component\HttpFoundation\JsonResponse;8use Symfony\Component\Routing\Annotation\Route;9
10final class CheckoutController extends AbstractController11{12 public function __construct(private readonly AvsbClient $avsb) {}13
14 #[Route('/checkout', name: 'checkout')]15 public function show(): JsonResponse16 {17 $showNew = $this->avsb->getBoolFlag('checkout-v2', false);18 $theme = $this->avsb->getStringFlag('ui-theme', 'default');19
20 return $this->json([21 'showNewCheckout' => $showNew,22 'theme' => $theme,23 ]);24 }25}Track an event
1$this->avsb->track('purchase', ['value' => 149.99, 'properties' => ['currency' => 'usd']]);Identify a user
The injected $avsb client is already scoped to the context built by your RequestContextFactory. If you need to evaluate against a different identity mid-controller — for example after a manual token exchange — inject Avsb\AvsbServer and call forUser:
1use Avsb\AvsbServer;2
3// In your service / controller4public function __construct(private readonly AvsbServer $server) {}5
6// Inside a method7$scoped = $this->server->forUser([8 'kind' => 'user',9 'key' => $user->getId(),10 'plan' => $user->getPlan(),11]);12$showNew = $scoped->getBoolFlag('checkout-v2', false);Using flags in Twig templates
The bundle registers a Twig extension that exposes the avsb_flagfunction and avsb global:
1{# avsb_flag(key, defaultValue) returns the typed value #}2{% if avsb_flag('checkout-v2', false) %}3 {{ include('checkout/_new.html.twig') }}4{% else %}5 {{ include('checkout/_legacy.html.twig') }}6{% endif %}Graceful shutdown
The bundle registers a kernel terminate listener that flushes pending events after the response is sent (kernel.terminate event). For CLI commands and Symfony Messenger workers, the bundle also listens to the console.terminate event. No additional configuration is required.
Testing
1<?php2
3namespace App\Tests\Controller;4
5use Avsb\Symfony\Testing\AvsbTestClient;6use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;7
8final class CheckoutControllerTest extends WebTestCase9{10 public function testShowsNewCheckout(): void11 {12 $client = static::createClient();13
14 // Override flags inside the test container15 AvsbTestClient::flagOn('checkout-v2');16
17 $client->request('GET', '/checkout');18
19 $this->assertResponseIsSuccessful();20 $data = json_decode($client->getResponse()->getContent(), true);21 $this->assertTrue($data['showNewCheckout']);22 }23}AvsbTestClient decorates the Avsb\Client service definition in the test environment. It stores overrides in memory and resets them after each test — no network calls are made.What's next
- Laravel integration — Laravel Facade and ServiceProvider for PHP.
- PHP SDK reference — full
AvsbServerAPI. - Multi-context targeting — combine user and organisation attributes in one evaluation.