SPA with Symfony? Yes Please

Abdulbasit Rubeiyya
3 min readJan 18, 2024

--

credits: symfony

Symfony, a robust PHP web application framework, has long been a favourite among developers for building scalable and maintainable web applications. In this guide, we’ll explore how to enhance the user experience of Symfony applications by integrating Hotwire Turbo, A set of complementary techniques for speeding up page changes and form submissions and turbocharging the way we build dynamic web applications.

Prerequisites:

Before diving into the integration process, make sure you have the following prerequisites in place:

1. Symfony Project:

Set up a Symfony project using either Symfony CLI or Symfony Flex.

2. Turbo Installation:

Install Turbo.js and Turbo-Streams.js in your project. You can include these scripts via npm or utilize CDN links in your HTML file.

<!-- Add these script tags to your base template (base.html.twig) -->
<script src="https://cdn.skypack.dev/@hotwired/turbo"></script>

Now, let’s proceed with the step-by-step integration of Hotwire Turbo with Symfony.

3. Update Symfony Controller:

Begin by preparing and or modifying your Symfony controller to return Turbo Stream responses for Turbo Frame updates.

// src/Controller/MyController.php

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;

class MyController extends AbstractController
{
public function myTurboFunction(): Response
{
// whatever other something u wanna add here (app logic)

// Render Turbo Stream response (we'll change it later)
return $this->render('my_template.html.twig', [], new Response(null, Response::HTTP_OK, ['Turbo-Frame' => 'your-frame']));
}
}

4. Update Twig Templates:

Adjust your Twig templates to include Turbo Frame tags.

{# my_template.html.twig #}

{% extends 'base.html.twig' %}

{% block content %}
<h1>Your Content</h1>

{# Turbo Frame tag with the specified id #}
{# You can specify ur own id #}
<turbo-frame id="dynamic-frame">
<p>Content to be updated dynamically.</p>
</turbo-frame>
{% endblock %}

5. Handle Turbo Streams:

Handle Turbo Streams in your Symfony controller (MyController) for dynamic updates.

// src/Controller/MyController.php

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;

class MyController extends AbstractController
{
public function myTurboFunction(): Response
{
// whatever other something u wanna add here (app logic)

// Create a Turbo Stream response (modified as promised ✌️)
$response = new Response(null, Response::HTTP_OK, ['Content-Type' => 'text/html; turbo-stream']);
$response->setContent(json_encode([
'turbo-stream' => [
'replace' => [
'dynamic-frame' => $this->renderView('dynamic_content.html.twig'),
],
],
]));

return $response;
}
}

6. Update Routes:

Now let’s add a route that handles the Turbo Streams Requests.

# config/routes.yaml

route_name:
path: /your/path
controller: App\Controller\MyController::myTurboFunction
methods: ['GET']

Congratulations 🥳, you’ve successfully unlocked a new level of dynamism for your Symfony application by integrating Hotwire Turbo! This combo brings the best of both worlds, leveraging Symfony’s robust architecture and Hotwire Turbo’s real-time capabilities to elevate your web application’s responsiveness.

All in all your journey does not end here, keep an eye on the official documentation for both Symfony and Hotwire Turbo for any updates or improvements, and don’t hesitate to explore further enhancements to make your Symfony application even more powerful and efficient. Happy coding!

PS. If you’re interested in a comprehensive and more complex guide, Symfony also provides an official integration guide between the two, visit https://symfony.com/bundles/ux-turbo/current/index.html

--

--