With the introduction of Symfony 4, a lot of components were updated and therefore the backwards compatibility were dropped as well. But, what has Symfony to do with Silex ? Yeah well, silex works basically with symfony components, like in the case of the Forms. With silex, using the FormServiceProvider you will be able to create forms in your silex application integrating protection against csrf attacks.
The exception that you see when you implement a very simple form using silex and the Twig Bridge (to be able to render the form in a view) is caused by a deprecation in the TwigRenderer module, for example given the following controller:
// Register the index route
$app->get('/', function () use ($app) {
// Create a form using the form factory
$form = $app['form.factory']->createBuilder(FormType::class, array())
->add('name')
->add('email')
->add('billing_plan', ChoiceType::class, array(
'choices' => array(
'free' => 1,
'small business' => 2,
'corporate' => 3
),
'expanded' => true,
))
->add('submit', SubmitType::class, [
'label' => 'Save',
])
->getForm();
// Use the Twig templating engine to render the PHP file
return $app['twig']->render('index.html.twig', array(
"form" => $form->createView()
));
})->bind('homepage');
And in this case our index.html.twig
file will have the following content:
{# index.html.twig #}
{% extends "layout.html.twig" %}
{% block content %}
{{ form_start(form) }}
{{ form_end(form)}}
{% endblock %}
Twig would throw the exception if you are using the latest version of the Twig Bridge and the Form component of Symfony. The solution however is pretty simple, instead of using the Twig Renderer, you should provide the Form Renderer of symfony to prevent the exception with the following code:
use Symfony\Component\Form\FormRenderer;
$app->extend('twig.runtimes', function ($runtimes, $app) {
return array_merge($runtimes, [
FormRenderer::class => 'twig.form.renderer',
]);
});
The previous snippet simply indicates that the Form renderer class of Symfony should be used to render the form.
Full example
If you still without understand where to place the code of the solution, with a full example it will be easier to do. For example, using the default skeleton of Silex, you will have an app.php file where all the service providers are loaded, here you could replace the form renderer:
<?php
// src/app.php or the file where you store the configuration of the silex project
// This namespace is to load the Form provider
use Silex\Provider\FormServiceProvider;
// Import the form renderer of Symfony used to solve the mentioned issue
use Symfony\Component\Form\FormRenderer;
// Usually you should have at least the following configuration in your project
// to be able to work with symfony forms
$app->register(new FormServiceProvider());
$app->register(new Silex\Provider\TranslationServiceProvider(), array(
'translator.domains' => array(),
));
$app["locale"] = "en";
// And the reason why you are reading this article:
//
// Important: to fix the error, replace the TwigRenderer deprecated from the version 3.4 of symfony
// with the Form Renderer of symfony instead
$app->extend('twig.runtimes', function ($runtimes, $app) {
return array_merge($runtimes, [
FormRenderer::class => 'twig.form.renderer',
]);
});
Happy coding ❤️!