1

I am looking for a seamless way to do this.

With Symfony 3.4, I need a way to, having a rendered page, know, for any element/text, which twig template it comes from.

NOTE: I have checked Twig - display template names if debug mode is enabled, but that thread is about using Twig but no Symfony. I have been following the examples there but without results.

I would like to not just add tracing data in every template, but to have the minimum possible invasive code needed to, for example, add to the starting point of a twig file and at the end of the file.

As there are blocks as well, the same but something like <trace twig="…" block="…"/>, etc, to each one of those blocks.

(Of course style=“display:none” in those marks)

-------------- attempts

I have put the other quoted question template at templates/DebugTemplate.php, app/templates/debugTemplate.php, and src/AppBundle/Twig/DebugTemplate.php

I went to app/config/config.yml and added twig->base_template_class, but I do not know how to correctly make this configuration work.

I have understood that you just have to write the template name directly like:

# Twig Configuration
twig:
    debug: '%kernel.debug%'
    strict_variables: '%kernel.debug%'
    base_template_class: DebugTemplate

But it crashes with Unexpected characters (}) at line 116 (near "base_template_class: {'DebugTemplate'}")

Same with

base_template_class: Twig\DebugTemplate
base_template_class: 'Twig\DebugTemplate'
base_template_class: {'Twig\DebugTemplate'}
base_template_class: 'DebugTemplate'
base_template_class: "%kernel.root_dir%/templates/DebugTemplate"
base_template_class: "%kernel.root_dir%\\templates\\DebugTemplate"  
base_template_class: templates\\DebugTemplate

Checking config via console: php bin/console debug:config twig

Current configuration for extension with alias "twig"
=====================================================
twig:
    debug: true
    strict_variables: true
    base_template_class: DebugTemplate
    exception_controller: 'twig.controller.exception:showAction'
    form_themes:
        - form_div_layout.html.twig
    globals: {  }
    autoescape: name
    autoescape_service: null
    autoescape_service_method: null
    cache: /NFS/code/nabc/abc_frontal_service/var/cache/dev/twig
    charset: UTF-8
    default_path: /NFS/code/nabc/abc_frontal_service/templates
    paths: {  }
    date:
        format: 'F j, Y H:i'
        interval_format: '%d days'
        timezone: null
    number_format:
        decimals: 0
        decimal_point: .
        thousands_separator: ','

Using the next config example (others do not generate the cache file): base_template_class: templates\DebugTemplate

It is generated, in cache, a class that tryes to extend the configurated template:

class __TwigTemplate_f3b8c130edb93e6c111c9714c114a4cede8e75482f6253fab3adbfd0ccca6c5e extends \templates\\DebugTemplate

This class is not always renewed when I change the config, so I suppose that what I typed in the config was not considered valid.

So I have two problems:

  • the DebugTemplate.php is neither nowhere near to be found in the cache.
  • I do not know how to set a valid path in that config field
LanderTaker
  • 55
  • 1
  • 8
  • Did you actually read the answers/comments in the question we've marked as your duplicate? [See this comment](https://stackoverflow.com/questions/35156570/twig-display-template-names-if-debug-mode-is-enabled#comment77827814_35549527). This can't be natively done in Symfony and you will have to use another base template for twig in order to hack this into the rendered templates – DarkBee Nov 08 '21 at 10:21
  • Yeah, I checked it thoughtfully, looked for those strings in all my solution to see if I could register the template, but to no avail. Looked as well in all over the internet doing a search, and nothing. Another base template? do you mean using something like: {%- extends 'my special template.twig' -%} ??? – LanderTaker Nov 08 '21 at 10:50
  • For starters, you just copy/pasted your old question while the best practice was to update your old question with new information, such as which solutions you've tried out. Did you try to change the base template in the symfony configs as shown in the comment I've linked? – DarkBee Nov 08 '21 at 11:04
  • 1
    The other answers are referring to twig's base template, the template that is used to compile all twig templates to `PHP`. You can change/configure it in symfony's config files - [reference](https://symfony.com/doc/3.4/reference/configuration/twig.html#base-template-class) – DarkBee Nov 08 '21 at 11:49
  • TY @DarkBee, with this, I have a path to follow, because the other question answers solutions implied touching things that, in my solution, I can only find in vendors. ... I have done the config solution you said, but I have not been capable of getting it to work. I have updated the Question up there with the things I have seen. – LanderTaker Nov 08 '21 at 14:19
  • 1
    Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/238992/discussion-between-darkbee-and-landertaker). – DarkBee Nov 08 '21 at 14:23
  • TY @DarkBee!! I LOVE YOU! :-D Namespace was the thing! Updating the question. Or Answering my own question... – LanderTaker Nov 08 '21 at 16:23

2 Answers2

1

base_template_class no longer works with Twig 3, but similar could be achieved in the following way.

src/Twig/DebugExtension.php

<?php

namespace App\Twig;

use Twig\Extension\AbstractExtension;

class DebugExtension extends AbstractExtension {

    public function getNodeVisitors()
    {
        return [new DebugCommenterNodeVisitor()];
    }

}

src/Twig/DebugCommenterNodeVisitor.php

<?php

namespace App\Twig;

use Twig\Environment;
use Twig\Node\BlockNode;
use Twig\Node\BodyNode;
use Twig\Node\ModuleNode;
use Twig\Node\Node;
use Twig\Node\TextNode;
use Twig\NodeVisitor\AbstractNodeVisitor;

class DebugCommenterNodeVisitor extends AbstractNodeVisitor {

    protected function doEnterNode(Node $node, Environment $env)
    {
        if ($node instanceof ModuleNode) {
            $templateName = $node->getTemplateName();
            $extension = pathinfo($templateName, PATHINFO_EXTENSION);

            $node->setNode('body', new BodyNode([
                new TextNode($this->createComment('BEGIN MODULE TEMPLATE: ' . $templateName, $extension), 0),
                $node->getNode('body'),
                new TextNode($this->createComment('END MODULE TEMPLATE: ' . $templateName, $extension), 0),
            ]));
        }
        elseif ($node instanceof BlockNode) {
            // Bonus helper for form templates and such.
            $name = $node->getAttribute('name');
            $sourceContext = $node->getSourceContext();
            if ($sourceContext) {
                $sourceContextName = $sourceContext->getName();
                // Note that we are skipping anything related to attributes, as we cannot put comments inside the html tags.
                if (!str_contains($name, 'attributes')) {
                    $node->setNode('body', new BodyNode([
                        new TextNode($this->createComment("BEGIN BLOCK TEMPLATE: $name, SOURCE CONTEXT: $sourceContextName"), 0),
                        $node->getNode('body'),
                        new TextNode($this->createComment("END BLOCK TEMPLATE: $name, SOURCE CONTEXT: $sourceContextName"), 0),
                    ]));
                }
            }
        }

        return $node;
    }

    protected function doLeaveNode(Node $node, Environment $env)
    {
        return $node;
    }

    public function getPriority(): int
    {
        return 0;
    }

    private function createComment(string $comment, string $extension = 'html'): string
    {
        return match ($extension) {
            'css', 'js' => '/* ' . $comment . ' */',
            default => '<!-- ' . $comment . ' -->',
        };
    }
}

In the case of not using autowiring, DebugExtension needs to be a service tagged with the twig.extension tag.

Łukasz Zaroda
  • 869
  • 2
  • 19
  • 55
0

How to do this in Symfony 3.4 (I do not know about other versions), based on Twig - display template names if debug mode is enabled and @DarkBee helping hands!

Steps:

  • Create your template class. Example: src/YourCompany/Application/TWIG/Helper/DebugTemplate.php

     namespace YourCompany\Application\TWIG\Helper;
     use Twig_Template;
    
     abstract class DebugTemplate extends Twig_Template {
         public function display(array $context, array $blocks = array())
         {
             // workaround - only add the html comment when the partial is loaded with @
             if(substr($this->getTemplateName(),0,1) == '@') {
                 echo 'getTemplateName() . ' -->';
             }
    
             $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks));
    
             if(substr($this->getTemplateName(),0,1) == '@') {
                 echo 'getTemplateName() . ' -->';
             }
    
         }
     }
     
  • go to config.yml. In my project its path is app/config/config.yml. Add the base_template_class setting under the twig section using our new namespace\className as the value. Example:

     ...
    
     # Twig Configuration
     twig:
         debug: '%kernel.debug%'
         strict_variables: '%kernel.debug%'
         base_template_class: YourCompany\Application\TWIG\Helper\DebugTemplate
    
     
LanderTaker
  • 55
  • 1
  • 8