{
    "mode": "perldoc",
    "parameter": "Template::Manual::Internals",
    "section": "",
    "url": "https://www.chedong.com/phpMan.php/perldoc/Template%3A%3AManual%3A%3AInternals/json",
    "generated": "2026-06-09T14:42:11Z",
    "sections": {
        "NAME": {
            "content": "Template::Manual::Internals - Template Toolkit internals\n",
            "subsections": []
        },
        "Introduction": {
            "content": "This section of the documentation is aimed at developers wishing to know more about how the\nTemplate Toolkit works on the inside in order to extend or adapt it to their own needs.\n\nIf that doesn't sound like you then you probably don't need to read this. There is no test\nafterwards.\n",
            "subsections": []
        },
        "Outside Looking In": {
            "content": "The Template module is simply a front end module which creates and uses a Template::Service and\npipes the output wherever you want it to go (\"STDOUT\" by default, or maybe a file, scalar, etc).\nThe \"Apache::Template\" module (available separately from CPAN) is another front end. That\ncreates a \"Template::Service::Apache\" object, calls on it as required and sends the output back\nto the relevant \"Apache::Request\" object.\n\nThese front-end modules are really only there to handle any specifics of the environment in\nwhich they're being used. The \"Apache::Template\" front end, for example, handles\n\"Apache::Request\" specifics and configuration via the httpd.conf. The regular Template front-end\ndeals with \"STDOUT\", variable refs, etc. Otherwise it is Template::Service (or subclass) which\ndoes all the work.\n\nThe Template::Service module provides a high-quality template delivery service, with bells,\nwhistles, signed up service level agreement and a 30-day no quibble money back guarantee. \"Have\na good time, all the time\", that's our motto.\n\nWithin the lower levels of the Template Toolkit, there are lots of messy details that we\ngenerally don't want to have to worry about most of the time. Things like templates not being\nfound, or failing to parse correctly, uncaught exceptions being thrown, missing plugin modules\nor dependencies, and so on. Template::Service hides that all away and makes everything look\nsimple to the outsider. It provides extra features, like \"PREPROCESS\", \"PROCESS\" and\n\"POSTPROCESS\", and also provides the error recovery mechanism via \"ERROR\". You ask it to\nprocess a template and it takes care of everything for you. The \"Template::Service::Apache\"\nmodule goes a little bit further, adding some extra headers to the Apache::Request, setting a\nfew extra template variables, and so on.\n\nFor the most part, the job of a service is really just one of scheduling and dispatching. It\nreceives a request in the form of a call to its process() method and schedules the named\ntemplate specified as an argument, and possibly several other templates (\"PREPROCESS\", etc) to\nbe processed in order. It doesn't actually process the templates itself, but instead makes a",
            "subsections": [
                {
                    "name": "process",
                    "content": "Template::Context is the runtime engine for the Template Toolkit - the module that hangs\neverything together in the lower levels of the Template Toolkit and that one that does most of\nthe real work, albeit by crafty delegation to various other friendly helper modules.\n\nGiven a template name (or perhaps a reference to a scalar or file handle) the context process()\nmethod must load and compile, or fetch a cached copy of a previously compiled template,\ncorresponding to that name. It does this by calling on a list of one or more Template::Provider\nobjects (the \"LOADTEMPLATES\" posse) who themselves might get involved with a Template::Parser\nto help turn source templates into executable Perl code (but more on that later).\n\nThankfully, all of this complexity is hidden away behind a simple template() method. You call it\npassing a template name as an argument, and it returns a compiled template in the form of a\nTemplate::Document object, or otherwise raises an exception.\n\nA Template::Document is a thin object wrapper around a compiled template subroutine. The object\nimplements a process() method which performs a little bit of housekeeping and then calls the\ntemplate subroutine. The object also defines template metadata (defined in \"[% META ... %]\"\ndirectives) and has a block() method which returns a hash of any additional \"[% BLOCK xxxx %]\"\ndefinitions found in the template source.\n\nSo the context fetches a compiled document via its own template() method and then gets ready to\nprocess it. It first updates the stash (the place where template variables get defined - more on\nthat shortly) to set any template variable definitions specified as the second argument by\nreference to hash array. Then, it calls the document process() method, passing a reference to\nitself, the context object, as an argument. In doing this, it provides itself as an object\nagainst which template code can make callbacks to access runtime resources and Template Toolkit\nfunctionality.\n\nWhat we're trying to say here is this: not only does the Template::Context object receive calls\nfrom the *outside*, i.e. those originating in user code calling the process() method on a\nTemplate object, but it also receives calls from the *inside*, i.e. those originating in\ntemplate directives of the form \"[% PROCESS template %]\".\n\nBefore we move on to that, here's a simple structure diagram showing the outer layers of the\nTemplate Toolkit heading inwards, with pseudo code annotations showing a typical invocation\nsequence.\n\n,--------.\n| Caller |     use Template;\n`--------'     my $tt = Template->new( ... );\n|         $tt->process($template, \\%vars);\n|                                                     Outside\n- - - | - - - - - - - - - - - - - - - - - - - - - - - - - - - - T T\n|         package Template;                            Inside\nV\n+----------+    sub process($template, \\%vars) {\n| Template |        $out = $self->SERVICE->process($template, $vars);\n+----------+        print $out or send it to $self->OUTPUT;\n|         }\n|\n|         package Template::Service;\n|\n|         sub process($template, \\%vars) {\n|             try {\n+----------+            foreach $p in @self->PREPROCESS\n| Service  |                $self->CONTEXT->process($p, $vars);\n+----------+\n|                 $self->CONTEXT->process($template, $vars);\n|\n|                 foreach $p @self->POSTPROCESS\n|                     $self->CONTEXT->process($p, $vars);\n|             }\n|             catch {\n|                 $self->CONTEXT->process($self->ERROR);\n|             }\n|         }\n|\nV         package Template::Context;\n+----------+\n| Context  |    sub process($template, \\%vars) {\n+----------+        # fetch compiled template\n|             $template = $self->template($template)\n|             # update stash\n|             $self->STASH->update($vars);\n|             # process template\n|             $template->process($self)\n|         }\nV\n+----------+    package Template::Document;\n| Document |\n+----------+    sub process($context) {\n$output = &{ $self->BLOCK }($context);\n}\n"
                }
            ]
        },
        "Inside Looking Out": {
            "content": "To understand more about what's going on in these lower levels, we need to look at what a\ncompiled template looks like. In fact, a compiled template is just a regular Perl sub-routine.\nHere's a very simple one.\n\nsub mycompiledtemplate {\nreturn \"This is a compiled template.\\n\";\n}\n\nYou're unlikely to see a compiled template this simple unless you wrote it yourself but it is\nentirely valid. All a template subroutine is obliged to do is return some output (which may be\nan empty of course). If it can't for some reason, then it should raise an error via \"die()\".\n\nsub mytodotemplate {\ndie \"This template not yet implemented\\n\";\n}\n\nIf it wants to get fancy, it can raise an error as a Template::Exception object. An exception\nobject is really just a convenient wrapper for the '\"type\"' and '\"info\"' fields.\n\nsub mysoliliquetemplate {\ndie (Template::Exception->new('yorrick', 'Fellow of infinite jest'));\n}\n\nTemplates generally need to do a lot more than just generate static output or raise errors. They\nmay want to inspect variable values, process another template, load a plugin, run a filter, and\nso on. Whenever a template subroutine is called, it gets passed a reference to a\nTemplate::Context object. It is through this context object that template code can access the\nfeatures of the Template Toolkit.\n\nWe described earlier how the Template::Service object calls on Template::Context to handle a",
            "subsections": [
                {
                    "name": "process",
                    "content": "template, but from within the code of another template. This is a call from the *inside*.\n\nsub myprocesstemplate {\nmy $context = shift;\nmy $output = $context->process('header', { title => 'Hello World' })\n. \"\\nsome content\\n\"\n. $context->process('footer');\n}\n\nThis is then roughly equivalent to a source template something like this:\n\n[% PROCESS header\ntitle = 'Hello World'\n%]\nsome content\n[% PROCESS footer %]\n\nTemplate variables are stored in, and managed by a Template::Stash object. This is a blessed\nhash array in which template variables are defined. The object wrapper provides get() and set()\nmethod which implement all the *magical.variable.features* of the Template Toolkit.\n\nEach context object has its own stash, a reference to which can be returned by the appropriately\nnamed stash() method. So to print the value of some template variable, or for example, to\nrepresent the following source template:\n\n<title>[% title %]</title>\n\nwe might have a subroutine definition something like this:\n\nsub {\nmy $context = shift;\nmy $stash = $context->stash();\nreturn '<title>' . $stash->get('title') . '</title>';\n}\n\nThe stash get() method hides the details of the underlying variable types, automatically calling\ncode references, checking return values, and performing other such tricks. If '\"title\"' happens\nto be bound to a subroutine then we can specify additional parameters as a list reference passed\nas the second argument to get().\n\n[% title('The Cat Sat on the Mat') %]\n\nThis translates to the stash call:\n\n$stash->get([ 'title', ['The Cat Sat on the Mat'] ]);\n\nDotted compound variables can be requested by passing a single list reference to the \"get()\"\nmethod in place of the variable name. Each pair of elements in the list should correspond to the\nvariable name and reference to a list of arguments for each dot-delimited element of the\nvariable.\n\n[% foo(1, 2).bar(3, 4).baz(5) %]\n\nis thus equivalent to\n\n$stash->get([ foo => [1,2], bar => [3,4], baz => [5] ]);\n\nIf there aren't any arguments for an element, you can specify an empty, zero or null argument\nlist.\n\n[% foo.bar %]\n$stash->get([ 'foo', 0, 'bar', 0 ]);\n\nThe set() method works in a similar way. It takes a variable name and a variable value which\nshould be assigned to it.\n\n[% x = 10 %]\n$stash->set('x', 10);\n\n[% x.y = 10 %]\n$stash->set([ 'x', 0, 'y', 0 ], 10);\n\nSo the stash gives us access to template variables and the context provides the higher level\nfunctionality.\n\nAlongside the process() method lies the include() method. Just as with the \"PROCESS\" / \"INCLUDE\"\ndirectives, the key difference is in variable localisation. Before processing a template, the\n\"process()\" method simply updates the stash to set any new variable definitions, overwriting any\nexisting values. In contrast, the \"include()\" method creates a copy of the existing stash, in a\nprocess known as *cloning* the stash, and then uses that as a temporary variable store. Any\npreviously existing variables are still defined, but any changes made to variables, including\nsetting the new variable values passed aas arguments will affect only the local copy of the\nstash (although note that it's only a shallow copy, so it's not foolproof). When the template\nhas been processed, the \"include()\" method restores the previous variable state by *decloning*\nthe stash.\n\nThe context also provides an insert() method to implement the \"INSERT\" directive, but no\n\"wrapper()\" method. This functionality can be implemented by rewriting the Perl code and calling\n\"include()\".\n\n[% WRAPPER foo -%]\nblah blah [% x %]\n[%- END %]\n\n$context->include('foo', {\ncontent => 'blah blah ' . $stash->get('x'),\n});\n\nOther than the template processing methods \"process()\", \"include()\" and \"insert()\", the context\ndefines methods for fetching plugin objects, plugin(), and filters, filter().\n\n# TT USE directive\n[% USE foo = Bar(10) %]\n\n# equivalent Perl\n$stash->set('foo', $context->plugin('Bar', [10]));\n\n# TT FILTER block\n[% FILTER bar(20) %]\nblah blah blah\n[% END %]\n\n# equivalent Perl\nmy $filter = $context->filter('bar', [20]);\n&$filter('blah blah blah');\n\nPretty much everything else you might want to do in a template can be done in Perl code. Things\nlike \"IF\", \"UNLESS\", \"FOREACH\" and so on all have direct counterparts in Perl.\n\n# TT IF directive\n[% IF msg %]\nMessage: [% msg %]\n[% END %];\n\n# equivalent Perl\nif ($stash->get('msg')) {\n$output .=  'Message: ';\n$output .= $stash->get('msg');\n}\n\nThe best way to get a better understanding of what's going on underneath the hood is to set the\n$Template::Parser::DEBUG flag to a true value and start processing templates. This will cause\nthe parser to print the generated Perl code for each template it compiles to \"STDERR\". You'll\nprobably also want to set the $Template::Directive::PRETTY option to have the Perl\npretty-printed for human consumption.\n\nuse Template;\nuse Template::Parser;\nuse Template::Directive;\n\n$Template::Parser::DEBUG = 1;\n$Template::Directive::PRETTY = 1;\n\nmy $template = Template->new();\n$template->process(\\*DATA, { cat => 'dog', mat => 'log' });\n\nDATA\nThe [% cat %] sat on the [% mat %]\n\nThe output sent to \"STDOUT\" remains as you would expect:\n\nThe dog sat on the log\n\nThe output sent to \"STDERR\" would look something like this:\n\ncompiled main template document block:\nsub {\nmy $context = shift || die \"template sub called without context\\n\";\nmy $stash   = $context->stash;\nmy $output  = '';\nmy $error;\n\neval { BLOCK: {\n$output .=  \"The \";\n$output .=  $stash->get('cat');\n$output .=  \" sat on the \";\n$output .=  $stash->get('mat');\n$output .=  \"\\n\";\n} };\nif ($@) {\n$error = $context->catch($@, \\$output);\ndie $error unless $error->type eq 'return';\n}\n\nreturn $output;\n}\n"
                }
            ]
        },
        "Hacking on the Template Toolkit": {
            "content": "Please feel free to hack on the Template Toolkit. If you find a bug that needs fixing, if you\nhave an idea for something that's missing, or you feel inclined to tackle something on the TODO\nlist, then by all means go ahead and do it!\n\nIf you're contemplating something non-trivial then you'll probably want to bring it up on the\nmailing list first to get an idea about the current state of play, find out if anyone's already\nworking on it, and so on.\n\nThe source code repository for the Template Toolkit is hosted at Github.\n\nhttps://github.com/abw/Template2\n\nClone the repository, make your changes, commit them, then send a pull request.\n\nOnce you've made your changes, please remember to update the test suite by adding extra tests to\none of the existing test scripts in the \"t\" sub-directory, or by adding a new test script of\nyour own. And of course, run \"make test\" to ensure that all the tests pass with your new code.\n\nDon't forget that any files you do add will need to be added to the MANIFEST. Running \"make\nmanifest\" will do this for you, but you need to make sure you haven't got any other temporary\nfiles lying around that might also get added to it.\n\nDocumentation is often something that gets overlooked but it's just as important as the code. If\nyou're adding a new module, a plugin module, for example, then it's OK to include the POD\ndocumentation in with the module, but *please* write it all in one piece at the end of the file,\n*after* the code (just look at any other \"Template::*\" module for an example). It's a religious\nissue, I know, but I have a strong distaste for POD documentation interspersed throughout the\ncode. In my not-so-humble opinion, it makes both the code and the documentation harder to read\n(same kinda problem as embedding Perl in HTML).\n\nThen add a line to the Changes file giving a very brief description of what you've done. There's\nno need to go into detail here (save that for the commit message, comments in code or\ndocuemtation where appropriate).\n\nPlease also make sure you add your name to the lib/Template/Manual/Credits.pod file (if it isn't\nalready there).\n\nThen commit your changes and send a pull request.\n",
            "subsections": []
        }
    },
    "summary": "Template::Manual::Internals - Template Toolkit internals",
    "flags": [],
    "examples": [],
    "see_also": []
}