Twig is a go-to templating engine for rendering HTML when developing web applications with Symfony.
However, Twig’s flexibility extends beyond generating just HTML pages. It can be a powerful tool for delivering content across multiple channels, such as generating Markdown files, JSON outputs, and even plain text, all from the same set of content.
This adaptability allows you to create content for different channels.
You can use Twig for generating HTML, Markdown, JSON, Text etc
Use case: fetching and rendering a recipe as Markdown with Symfony
In this example, we use Symfony's HTTP Client to fetch a recipe from an external API (https://dummyjson.com/recipes/1) and render it as a Markdown document using Twig.
This approach shows how you can combine Symfony's powerful packages, like the Symfony HTTP client for external data retrieval and Twig for rendering views, to deliver content across multiple channels, such as Markdown reports in a command-line tool.
The command/script we are going to build fetches the recipe data (title, description, ingredients, and instructions) from the API, processes it, and then uses Twig to output the content in a structured Markdown format. This practical use case illustrates how to use Twig beyond web templates, making it versatile for generating content in various formats.
So, we are going to use:
- Symfony Console Component https://symfony.com/doc/current/components/console.html for building a command line tool
- Symfony HTTP Client https://symfony.com/doc/current/http_client.html for fetching and consuming HTTP API
- Symfony Twig https://twig.symfony.com/doc/3.x/intro.html#installation for rendering data
- The recipes API: we will pick one "dummy" recipe https://dummyjson.com/recipes/1 to show and demonstrate the process for retrieving a structured JSON and converting it to a markdown file.
Installing necessary Symfony components
Ensure that you have the required components installed for HTTP requests and creating commands:
composer require symfony/http-client symfony/console twig/twig
Create a Symfony command
First, let's create a new Symfony command.
If you want to read more about how to create a command line tool using the Symfony Command component, I wrote a specific article about this: https://dev.to/robertobutti/building-a-command-line-tool-with-php-and-symfony-console-4n6g
Commands classes, typically go into the src/Commands
directory.
# create a new empty directory
mkdir -p src/Commands
# create a new empty file
touch src/Commands/FetchRecipeCommand.php
Command Class (e.g., src/Commands/FetchRecipeCommand.php
):
<?php
namespace MyExample\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpClient\HttpClient;
class FetchRecipeCommand extends Command
{
private $twig;
public function __construct()
{
$this
->setName('recipe')
->setDescription('Prints a recipe in Markdown')
->setHelp('This command prints a simple recipe in Markdown.');
// Step 1: loading the Twig environment
$loader = new \Twig\Loader\FilesystemLoader(__DIR__ . '/../resources/views');
$twig = new \Twig\Environment(
$loader,
// Optional: Enable caching for better performance
/*[
'cache' => __DIR__ . '/../../cache',
]*/
);
$this->twig = $twig;
parent::__construct();
}
protected function configure()
{
$this->setDescription('Fetches a recipe from an API and renders it as Markdown');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
// Step 2: Initialize the HTTP client and fetch the recipe
$client = HttpClient::create();
$response = $client->request('GET', 'https://dummyjson.com/recipes/1');
// Step 3: obtain the array of info
$recipeData = $response->toArray();
// Step 4: Render the template using Twig, returning a string
$markdownOutput = $this->twig->render('recipe.md.twig', $recipeData);
// Step 5: Output the generated Markdown
$output->writeln($markdownOutput);
return Command::SUCCESS;
}
}
Here’s a detailed explanation of each step in the FetchRecipeCommand
example.
Step-by-step breakdown
Step 1: Loading the twig environment
To use Twig outside its typical web context, such as in a PHP command-line tool, you first need to initialize it manually via the Twig\Environment
class. Here's an example setup for Twig in a console command:
$loader = new \Twig\Loader\FilesystemLoader(__DIR__ . '/../resources/views');
$twig = new \Twig\Environment(
$loader,
// Optional: Enable caching for better performance
/*[
'cache' => __DIR__ . '/../../cache',
]*/
);
$this->twig = $twig;
Explanation:
- The twig environment is initialized by creating a
FilesystemLoader
that tells Twig where to find the templates. This case points to thesrc/resources/views
folder where your Twig templates are stored. - Then, the
$twig
environment is instantiated and responsible for rendering the templates. Optional caching can be enabled to improve performance by storing precompiled templates. - Finally, the initialized
$twig
environment is assigned to$this->twig
for later use (in theexecute()
method).
Step 2: initializing the HTTP Client and fetch the recipe
$client = HttpClient::create();
$response = $client->request('GET', 'https://dummyjson.com/recipes/1');
Explanation:
- The Symfony HTTP client is created using the
HttpClient::create()
method, which allows the command to perform HTTP requests. - To fetch a recipe, the
request()
method performs aGET
request to the specified URL (https://dummyjson.com/recipes/1). - The API returns a JSON response stored in the
$response
variable.
Step 3: obtaining the array of information
$recipeData = $response->toArray();
Explanation:
- The
toArray()
method converts the JSON response from the API into a PHP array. This array contains the recipe’s data (e.g., name, ingredients, instructions), which will be used to populate the Twig template in the next step.
Step 4: rendering the template using Twig
$markdownOutput = $this->twig->render('recipe.md.twig', $recipeData);
Explanation:
- The Twig environment's
render()
method generates the Markdown output. It loads the template (recipe.md.twig
) from thesrc/resources/views
folder. - The recipe data fetched from the API (
$recipeData
) is passed into the template, where it will replace placeholders such as the recipe name, ingredients, and instructions, creating a fully formatted Markdown file. - The rendered Markdown content (the string returned by the
render()
method) is stored in the$markdownOutput
variable.
Step 5: generating output for the generated Markdown
$output->writeln($markdownOutput);
Explanation:
- The final Markdown content is printed to the console using the
$output->writeln()
method. This method outputs the string to the console, allowing users to see the formatted recipe in Markdown format (eventually, you can redirect the output into a file in the shell).
Creating the starter file
You have to create a starter file to allow the user to launch your Symfony command directly from the shell. (In this article, we are not creating a Symfony application; we are building a PHP script using the Symfony packages.)
In the project directory, where you have the composer.json
file and where you have the src
directory, you can create a my-app
file.
#!/usr/bin/env php
<?php
use MyExample\Commands\FetchRecipeCommand;
use Symfony\Component\Console\Application;
if (file_exists(__DIR__ . '/../../autoload.php')) {
require __DIR__ . '/../../autoload.php';
} else {
require __DIR__ . '/vendor/autoload.php';
}
/**
* Start the console application.
*/
$app = new Application('Recipe to Markdown', '1.0.0');
$app->setDefaultCommand("recipe");
$app->add(new FetchRecipeCommand());
$app->run();
To use correctly the namespaces and the classes be sure to set the autoload
section in the composer.json
file:
{
"require": {
"symfony/http-client": "^7.1",
"symfony/console": "^7.1",
"twig/twig": "^3.14"
},
"autoload": {
"psr-4": {
"MyExample\\": "src/"
}
}
}
If you change the autoload
section I suggest to dump the autoload file:
composer dump-autoload
Now, you have to create the Twig template/view to render the data retrieved by the API.
Create a Twig template/view for the recipe
Next, create a Twig template/view to render the recipe in Markdown format.
This template should go in the views
directory (e.g., src/resources/view/recipe.md.twig
).
# Recipe: {{ name }}
- Preparation time: {{ prepTimeMinutes }} minutes
- Cooking time {{ cookTimeMinutes }} minutes
- Difficulty level: {{ difficulty }}
- Cuisine: {{ cuisine }}
- Servings {{ servings }} people, with {{ caloriesPerServing }} calories per person
## Ingredients:
{% for ingredient in ingredients %}
- {{ ingredient }}
{% endfor %}
## Instructions:
{% for instruction in instructions %}
- {{ instruction }}
{% endfor %}
Enjoy!
This Twig view file will render the recipe in Markdown format, with sections for the recipe's name, ingredients, and instructions.
Running the command
To execute the command, run the following in the terminal:
php my-app
In the case you have more than one command, you can launch:
php m-app recipe
To see all the available commands:
php my-app list
Conclusion
With this approach, you can easily retrieve data from an external API using Symfony's HTTP client, process the response, and render the output in a structured format using Twig. In this case, the command outputs a recipe as Markdown, but this technique can be adapted to any other content or data type you need to process.
Enjoy your recipe!
Top comments (0)