I'm using Symfony2 to generate forms, or actually Twig, which uses Symfony's functions, so the view looks like this:
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
This generates HTML code without any newlines or indentation. This is unreadable when I look into HTML source code.
Is there any way to force Symfony/Twig to format the generated HTML?
This link explains form customization in twig beautifully. There are numerous ways of applying css styling to form elements. For example, if you have a form with a field name you can add a css class to it this way:
{# render a widget, but add a "foo" class to it #}
{{ form_widget(form.name, {'attr': {'class': 'foo'}}) }}
or to the label:
{{ form_label(form.name, 'Your Name', {'label_attr': {'class': 'foo'}}) }}
Then you can use the css classes to render form elements as per your design. Hope you get the idea. The docs and link provided in the answer are both useful in this regard.
Update: the below "solution" made me a headache precisely this line:
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
It converts all non-ascii characters to entities, which is not very smart. Javascript's confirm
and alert
functions don't convert it back to UTF-8, they display strings as they are.
Thanks everybody, but I think I wasn't clear enough:) I didn't mean formatting by css or generally changing how the rendered page looks like, but rather changing HTML source code.
Anyway, with these two articles I finally managed to do what I wanted:
How do you format DOM structures in PHP?
http://php-and-symfony.matthiasnoback.nl/2011/10/symfony2-create-a-response-filter-and-set-extra-response-headers/
Step 1.
So, first the response listener, in (for example) AppBundle/EventListener/ResponseListener.php:
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
class ResponseListener {
private $container;
public function __construct(Container $container) {
$this->container = $container;
}
function tidyHtml($html)
{
$dom = new \DOMDocument();
if (libxml_use_internal_errors(true) === true)
{
libxml_clear_errors();
}
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
$html = preg_replace(array('~\R~u', '~>[[:space:]]++<~m'), array("\n", '><'), $html);
if ((empty($html) !== true) && ($dom->loadHTML($html) === true))
{
$dom->formatOutput = true;
if (($html = $dom->saveXML($dom->documentElement, LIBXML_NOEMPTYTAG)) !== false)
{
$regex = array
(
'~' . preg_quote('<![CDATA[', '~') . '~' => '',
'~' . preg_quote(']]>', '~') . '~' => '',
'~></(?:area|base(?:font)?|br|col|command|embed|frame|hr|img|input|keygen|link|meta|param|source|track|wbr)>~' => ' />',
);
return '<!DOCTYPE html>' . "\n" . preg_replace(array_keys($regex), $regex, $html);
}
}
return false;
}
public function onKernelResponse(FilterResponseEvent $event) {
$request = $event->getRequest();
//only when format == html and environment == dev
if ($request->getRequestFormat() == 'html' && $this->container->get('kernel')->getEnvironment() == 'dev') {
$event->getResponse()->setContent($this->tidyHtml($event->getResponse()->getContent()));
}
}
}
Step 2.
In services.yml:
response_listener:
class: AppBundle\EventListener\ResponseListener
arguments: ['@service_container']
tags:
- { name: kernel.event_listener, event: kernel.response, method : onKernelResponse }