How to get formatted HTML generated by Symfony

2019-06-14 09:59发布

问题:

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?

回答1:

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.



回答2:

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 }


标签: symfony twig