OpenCart 3主题开发:将Twig模板内嵌JS移至页脚的实现方案
Great question! Coming from Laravel's Blade, you’ll be glad to know Twig can replicate that @stack/@push functionality—you just need to extend OpenCart’s Twig environment a bit, since it doesn’t come with this out of the box. Here’s a step-by-step solution tailored to OpenCart 3’s constraints:
1. Extend Twig to Add Stack/Push Functionality
OpenCart initializes its Twig environment in system/library/twig.php. We’ll add a global array to store scripts, plus two custom Twig functions: push_script (to add scripts to the stack) and render_scripts (to output the stack in the footer).
Edit system/library/twig.php (tip: use OCmod/vQmod for this instead of editing core files directly if you want to keep updates clean):
// After initializing $twig = new Twig_Environment($loader, $config); // Create a global array to hold our script stack $twig->addGlobal('scripts_stack', []); // Add the push_script function to add scripts to the stack $twig->addFunction(new Twig_Function('push_script', function($script_content) use (&$twig) { $current_stack = $twig->getGlobals()['scripts_stack']; $current_stack[] = $script_content; $twig->addGlobal('scripts_stack', $current_stack); })); // Add the render_scripts function to output all stacked scripts $twig->addFunction(new Twig_Function('render_scripts', function() use ($twig) { $output = ''; foreach ($twig->getGlobals()['scripts_stack'] as $script) { // Wrap inline scripts in <script> tags (adjust if pushing external script tags directly) if (!str_starts_with(trim($script), '<script')) { $output .= '<script>' . $script . '</script>' . PHP_EOL; } else { $output .= $script . PHP_EOL; } } // Render raw HTML without escaping return new Twig_Markup($output, 'UTF-8'); }));
2. Update Your Module Templates (e.g., slideshow.twig)
Replace inline JavaScript in your module templates with the push_script function. For example, in catalog/view/theme/your_theme/template/module/slideshow.twig:
Before:
<div class="slideshow">...</div> <script> $(document).ready(function() { $('.slideshow').slick({ autoplay: true, dots: true, infinite: true }); }); </script>
After:
<div class="slideshow">...</div> {% verbatim %} {{ push_script("$(document).ready(function() { $('.slideshow').slick({ autoplay: true, dots: true, infinite: true }); });") }} {% endverbatim %}
- Use
{% verbatim %}to avoid Twig parsing issues with curly braces in your JS code. - If you’re pushing an external script file, you can pass the full tag directly:
{{ push_script('<script src="catalog/view/javascript/slick.min.js"></script>') }}
3. Render the Script Stack in Your Footer
Open your footer template (catalog/view/theme/your_theme/template/common/footer.twig) and add the render_scripts function right before the closing </body> tag:
<!-- Other footer content --> {{ render_scripts() }} </body> </html>
Bonus: Optimizations
- Deduplicate Scripts: Modify the
push_scriptfunction to check if the script is already in the stack before adding it (useful for external libraries loaded by multiple modules). - Separate Stacks: Create multiple stacks (e.g.,
head_scripts,footer_scripts) if you need some scripts in the head and others in the footer.
This approach mimics Blade’s stack/push workflow perfectly, works within OpenCart’s template constraints, and keeps your Twig templates clean by moving all JS to the footer.
内容的提问来源于stack exchange,提问作者secondman

