bext.dev
DocsFramework Integrations
Framework Integrations3 min read
On this page

Symfony Integration

The bext/symfony package provides a Symfony Flex bundle that auto-registers bext's cache, real-time, and task services for dependency injection.

Installation#

bash
composer require bext/symfony

Requirements: PHP >= 8.2, Symfony 6.4 or 7.0

The bundle is auto-registered via Symfony Flex — no manual configuration needed.

Autowiring#

Inject bext services into any controller or service:

php
use Bext\Symfony\BextCache;
use Bext\Symfony\BextRealtime;
use Bext\Symfony\BextTasks;

class ProductController extends AbstractController
{
    public function __construct(
        private BextCache $cache,
        private BextRealtime $realtime,
        private BextTasks $tasks,
    ) {}

    #[Route('/api/products/{id}', methods: ['PUT'])]
    public function update(string $id, Request $request): JsonResponse
    {
        $product = $this->productRepo->update($id, $request->toArray());

        $this->cache->invalidate("products");
        $this->realtime->publish("products", [
            "action" => "updated",
            "id" => $id,
        ]);

        return $this->json($product);
    }
}

Container Aliases#

Services are also available via container aliases:

php
$this->container->get('bext.cache');
$this->container->get('bext.realtime');
$this->container->get('bext.tasks');

Global Helpers#

Same helper functions as the Laravel adapter:

php
bext_invalidate("products");
bext_publish("orders", ["id" => 123]);
bext_task("cleanup", "0 2 * * *", "cache::gc");

Cache API#

php
class BextCache
{
    public function invalidate(string $tag): bool;
    public function invalidatePath(string $pattern): bool;
    public function flush(): bool;
}

Real-Time API#

php
class BextRealtime
{
    public function publish(string $topic, mixed $data = null): bool;
}

Task Scheduling API#

php
class BextTasks
{
    public function register(string $name, string $cron, string $command): bool;
    public function list(): array;
    public function cancel(string $name): bool;
}
Tip

If you are running Symfony behind a separate Puma-style process server, see Reverse proxy / multi-app instead. This page covers the embedded PHP worker mode, which keeps the Symfony kernel warm in-process for sub-millisecond per-request overhead.

Worker Mode#

Like the Laravel adapter, Symfony supports worker mode for high-performance request handling.

Setup#

Create a worker.php:

php
<?php
require __DIR__ . '/vendor/autoload.php';

$kernel = new \App\Kernel(
    $_SERVER['APP_ENV'] ?? 'prod',
    (bool) ($_SERVER['APP_DEBUG'] ?? false)
);

\Bext\Symfony\Worker::run($kernel);

Configure in bext.config.toml:

toml
[php]
enabled = true
document_root = "./public"
workers = 4
worker_script = "./worker.php"
max_requests = 10000

Performance#

Mode Per-request overhead
Classic (boots the kernel every request) 1–5 ms
Worker (kernel kept warm in memory) tens of microseconds

The worker keeps Symfony's DI container, route matcher, and event dispatcher loaded in memory. Only request-specific state is re-created per request.

React SSR Bridge#

Render React components from Symfony controllers:

php
use function Bext\Symfony\react;

#[Route('/dashboard')]
public function dashboard(): Response
{
    $html = react("Dashboard", [
        "user" => $this->getUser(),
        "metrics" => $this->metricsService->getSummary(),
    ]);

    return new Response($html);
}

Uses the same FFI-accelerated rendering path as the Laravel adapter when running in worker mode.

Event Subscriber Integration#

You can integrate bext services with Symfony's event system:

php
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class CacheInvalidationSubscriber implements EventSubscriberInterface
{
    public function __construct(private BextCache $cache) {}

    public static function getSubscribedEvents(): array
    {
        return [
            ProductUpdatedEvent::class => 'onProductUpdated',
        ];
    }

    public function onProductUpdated(ProductUpdatedEvent $event): void
    {
        $this->cache->invalidate("products");
        $this->cache->invalidatePath("/products/{$event->getProductId()}");
    }
}
  • Symfony — official Symfony documentation
Edit this page ↗Need a hand? ↗
FIND YOUR NEXT STEP

Start with a topic, a command, or a question.