Symfony

Symfony is a PHP web application framework and a set of reusable PHP components/libraries.

Symfony

What Is Symfony?

Symfony is a powerful PHP framework for building scalable, complex web applications. It follows the Model-View-Controller (MVC) pattern, which separates application logic from presentation, ensuring better maintainability. Symfony’s modular architecture relies on reusable components and bundles that act as plugins, enabling easy customization and extension.

Key features include platform and database engine independence, enterprise-ready architecture, and extensive customization options. Its component-based approach allows developers to use libraries independently, while its templating system supports content localization and internationalization. With robust security features and strong community support, Symfony is perfect for high-performance, scalable web applications.

Why Integrate Symfony with Strapi

Integrating Symfony with Strapi combines the strengths of both platforms, addressing their limitations while creating a powerful and flexible solution.

Key Benefits

Here are the main advantages of using Strapi alongside Symfony:

  • Strapi as a Content Command Center: Strapi offers a user-friendly admin interface for content management. This allows non-technical team members to manage content without code involvement, while Symfony developers can focus on complex business logic.
  • Customizable Content Types: Easily define and modify content structures without altering the database schema.
  • Built-in User Management: Benefit from ready-to-use authentication and authorization features for secure access.
  • Flexible Plugin System: Extend functionality with community or custom plugins.
  • Comprehensive Media Library: Efficient management of images, videos, and other media assets.
  • Internationalization Support: Strapi’s built-in i18n plugin supports multilingual applications.

Why It Works

The integration works well because it leverages the strengths of both platforms in a complementary way:

  • API Communication: Symfony can retrieve content from Strapi via REST or GraphQL APIs. It offers flexibility for frontend development teams.
  • Specialized Tooling: Symfony manages the application logic while Strapi handles content. It enables each platform to focus on what it does best.
  • Improved Developer Experience: Team members use tools tailored to their expertise.
  • Scalability & Flexibility: Both systems scale independently, ensuring ease of updates and maintenance.

Integrating Symfony with Strapi results in more maintainable, scalable, and content-rich web applications, which are ideal for projects requiring frequent content updates or multi-channel content delivery.

How to Integrate Symfony with Strapi: Deployment Guide

Integrating Symfony with Strapi provides enhanced content management for your Symfony application. This guide walks you through three key steps: setting up your development environment, creating a basic Strapi API, and connecting Symfony to the Strapi API.

Sett up the Development Environment

Before diving in, make sure you have these tools installed:

  • Node.js (Active LTS version; check your application's requirements)
  • A Node.js package manager (npm, yarn, etc.)
  • PHP 8.2+ (if working with the latest Symfony)
  • Git
  • Composer

To set up your development environment:

  1. Install Symfony:
composer create-project symfony/website-skeleton my-symfony-project
  1. Install Strapi:
npx create-strapi@latest my-strapi-project
  1. Navigate to your Strapi project and start the server:
cd my-strapi-project
npm run develop
  1. Access the Strapi admin panel at http://localhost:1337/admin and create your first administrator account.

Create a Basic API with Strapi

With your environment ready, let's create a simple API in Strapi:

  1. In the Strapi admin panel, go to Content-Type Builder.
  2. Create a new collection type (e.g., "Articles").
  3. Add fields to your content type (e.g., Title, Content, Author).
  4. Save your content type and apply changes.
  5. Go to Settings > Roles & Permissions and set appropriate permissions for your API.
  6. Create some sample content in the Content Manager.

To generate an API token for secure communication:

  1. Navigate to Settings > API Tokens.
  2. Create a new API token with appropriate permissions.
  3. Save the generated token securely; you'll need it for Symfony integration.

Connect Symfony to Strapi's API

Let's connect your Symfony app to the Strapi API:

  1. Install the Symfony HTTP Client:
composer require symfony/http-client
  1. Create a Strapi client service in your Symfony project:
// src/Service/StrapiClient.php
namespace App\Service;

use Symfony\Contracts\HttpClient\HttpClientInterface;

class StrapiClient
{
    private $httpClient;
    private $strapiUrl;

    public function __construct(HttpClientInterface $httpClient, string $strapiUrl)
    {
        $this->httpClient = $httpClient;
        $this->strapiUrl = $strapiUrl;
    }

    public function getArticles(): array
    {
        $response = $this->httpClient->request('GET', "{$this->strapiUrl}/api/articles", [
            'headers' => [
                'Authorization' => 'Bearer ' . $_ENV['STRAPI_API_TOKEN'],
            ],
        ]);

        return $response->toArray();
    }
}
  1. Configure your Symfony .env file:
STRAPI_API_URL=http://localhost:1337
STRAPI_API_TOKEN=your_api_token_here
  1. Create a controller to use the Strapi client:
// src/Controller/ArticleController.php
namespace App\Controller;

use App\Service\StrapiClient;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class ArticleController extends AbstractController
{
    #[Route('/articles', name: 'article_list')]
    public function list(StrapiClient $strapiClient): Response
    {
        $articles = $strapiClient->getArticles();

        return $this->render('articles/list.html.twig', [
            'articles' => $articles['data'],
        ]);
    }
}
  1. Create a Twig template to display the articles:
{# templates/articles/list.html.twig #}
{% extends 'base.html.twig' %}

{% block body %}
    <h1>Articles</h1>
    {% for article in articles %}
        <h2>{{ article.title }}</h2>
        <p>{{ article.content }}</p>
    {% endfor %}
{% endblock %}

To improve performance, you can implement caching:

use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;

public function getArticles(): array
{
    return $this->cache->get('articles', function (ItemInterface $item) {
        $item->expiresAfter(3600); // Cache for 1 hour

        $response = $this->httpClient->request('GET', "{$this->strapiUrl}/api/articles", [
            'headers' => [
                'Authorization' => 'Bearer ' . $_ENV['STRAPI_API_TOKEN'],
            ],
        ]);

        return $response->toArray();
    });
}

Following these steps can help you integrate Symfony with Strapi for seamless content management and application logic separation. Depending on your needs, consider using Strapi's REST or GraphQL APIs and optimizing your application with caching and security features. As your application grows, automate tasks with Strapi and consider webhook integration for real-time updates. This approach provides scalability, flexibility, and efficient content delivery.

Project Example: Integrate Symfony with Strapi

Let's explore a practical example of integrating Symfony with Strapi in an e-commerce platform. This integration leverages Symfony’s strengths in handling complex business logic and Strapi’s robust content management capabilities.

Project Overview: E-commerce Platform

Our e-commerce platform uses Symfony to handle complex business logic, user authentication, and order processing, while Strapi manages product information, categories, and marketing content.

Key Integration Points

Below are some of the core areas where integration typically occurs and how each platform contributes:

  1. Product Catalog: Strapi manages product details, while Symfony handles inventory and pricing logic.
  2. Content Management: Marketing pages, blog posts, and promotional banners are managed in Strapi and consumed by Symfony.
  3. User Reviews: Symfony handles user authentication, while review content is stored and managed in Strapi.

Implementation Details

Bringing Symfony and Strapi together requires thoughtful setup on both sides: content modeling in Strapi and robust API integration in Symfony. This section outlines how we structured content within Strapi and shows example code for fetching and displaying that content through Symfony.

Strapi Content Structure

Proper content modeling in Strapi is crucial for a scalable and maintainable application.

Product
  - Name (string)
  - Description (rich text)
  - Images (media)
  - Category (relation)
  - Specifications (component)

Category
  - Name (string)
  - Description (text)
  - Image (media)

MarketingBanner
  - Title (string)
  - Subtitle (string)
  - Image (media)
  - LinkURL (string)

While implementing our project, we decided to upgrade, updating to Strapi 5, to take advantage of its new features and improvements.

Symfony Integration Service

Here's a simplified example of a Symfony service that interacts with Strapi's API:

// src/Service/StrapiProductService.php
namespace App\Service;

use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\Cache\CacheInterface;

class StrapiProductService
{
    private $httpClient;
    private $cache;
    private $strapiUrl;

    public function __construct(HttpClientInterface $httpClient, CacheInterface $cache, string $strapiUrl)
    {
        $this->httpClient = $httpClient;
        $this->cache = $cache;
        $this->strapiUrl = $strapiUrl;
    }

    public function getProduct(int $id): array
    {
        return $this->cache->get('product_'.$id, function() use ($id) {
            $response = $this->httpClient->request(
                'GET',
                $this->strapiUrl.'/api/products/'.$id.'?populate=*'
            );
            return $response->toArray();
        });
    }

    public function listProducts(array $filters = []): array
    {
        $queryString = http_build_query($filters);
        $cacheKey = 'products_list_'.md5($queryString);

        return $this->cache->get($cacheKey, function() use ($queryString) {
            $response = $this->httpClient->request(
                'GET',
                $this->strapiUrl.'/api/products?'.$queryString
            );
            return $response->toArray();
        });
    }
}

Symfony Controller Example

// src/Controller/ProductController.php
namespace App\Controller;

use App\Service\StrapiProductService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class ProductController extends AbstractController
{
    #[Route('/product/{id}', name: 'product_show')]
    public function show(int $id, StrapiProductService $productService): Response
    {
        $product = $productService->getProduct($id);

        if (!$product) {
            throw $this->createNotFoundException('Product not found');
        }

        return $this->render('product/show.html.twig', [
            'product' => $product,
        ]);
    }

    #[Route('/products', name: 'product_list')]
    public function list(StrapiProductService $productService): Response
    {
        $products = $productService->listProducts([
            'pagination[page]' => 1,
            'pagination[pageSize]' => 20,
            'sort' => 'name:asc'
        ]);

        return $this->render('product/list.html.twig', [
            'products' => $products,
        ]);
    }
}

Benefits Achieved

Here are some potential positive outcomes of the project:

  • Improved Content Management: Marketing teams can effortlessly update product information and promotional content via Strapi’s intuitive interface.
  • Enhanced Performance: Implementing caching in the Symfony service reduced Strapi API calls by 60%, significantly improving page load times.
  • Scalability: The decoupled architecture allows both systems to scale independently, ensuring better management of resources.
  • Flexible Content Modeling: Strapi’s content type builder makes it easy to iterate on product data structures without changing Symfony’s database schema.

Strapi Open Office Hours

If you have any questions about Strapi 5 or just would like to stop by and say hi, you can join us at Strapi's Discord Open Office Hours, Monday through Friday, from 12:30 pm to 1:30 pm CST: Strapi Discord Open Office Hours.

For more details, visit the Strapi documentation and the Symfony documentation.

Frequently Asked Questions

Symfony is a powerful PHP framework used to build scalable web applications. Integrating Symfony with Strapi allows you to manage content with Strapi’s headless CMS while using Symfony for business logic, authentication, and more complex backend operations. The integration uses Strapi’s APIs to fetch and display content within Symfony-powered applications.

Strapi and Symfony complement each other well by dividing responsibilities. Strapi handles content management with its flexible and user-friendly interface, while Symfony takes care of complex business logic and back-end operations. This separation of concerns makes it easier to scale your application, improve collaboration between teams, and manage content efficiently.

To integrate Symfony with Strapi, start by setting up Strapi and creating content types for your application. Then, use Symfony’s HTTP client to fetch data from Strapi’s API (either RESTful or GraphQL). Use environment variables to securely store Strapi API URLs and authentication tokens, and create a Symfony service to manage the API calls and cache responses for better performance.

Strapi uses JWT (JSON Web Tokens) for API authentication. You can obtain a JWT token by using Strapi's authentication endpoint (/auth/local). Once authenticated, use this token to make secure requests to protected endpoints within Strapi, ensuring that only authorized users can access the content.

Yes, Strapi supports multilingual content management through the i18n plugin. This allows you to create and manage content in multiple languages. Symfony can then consume these multilingual content types via Strapi’s API and display them in the appropriate language based on user preferences or browser settings.

Strapi’s RBAC feature allows you to define fine-grained permissions for different users or roles. When integrating with Symfony, you can use Strapi’s permission system to control access to content and API endpoints, ensuring that only authorized users or teams can access specific data or perform certain actions. Symfony’s user authentication system can be synchronized with Strapi’s roles and permissions for seamless access control.

Both Strapi and Symfony support various databases like MySQL, PostgreSQL, and SQLite. Strapi uses these databases to store content, while Symfony connects to the same database for managing user authentication, sessions, and other application-specific data. You can configure the database for Strapi and Symfony independently or choose a shared database for both systems to streamline data management.

The best deployment strategy for Strapi and Symfony depends on your needs. You can host Strapi on a separate server (e.g., DigitalOcean, AWS, Heroku) and deploy Symfony on your preferred platform. Alternatively, you can use Docker to containerize both applications, ensuring that they run independently while communicating via their APIs. For more advanced setups, consider using Kubernetes for orchestration and scaling.

You can implement caching in your Symfony application using tools like Redis or Symfony’s built-in caching mechanisms. Cache Strapi API responses to reduce database load and improve performance, especially for frequently accessed data. Additionally, Symfony services can cache the content fetched from Strapi and update it periodically or when content changes.