Includes
BoxLang's include system allows you to merge templates together for code reuse, with full scope absorption and dynamic template execution.
Template includes are BoxLang's server-side inclusion mechanism that embeds one template into another at runtime. When you include a template, it becomes part of the current execution context with complete access to all scopes in the including template.
📋 Table of Contents
🎯 What Are Includes?
An include is a file that is embedded (or included) within another file, making it part of the current execution. The included template has complete access to the including template's scopes.
Key Characteristics
✅ Runtime Merging - Templates are merged at execution time
✅ Scope Absorption - Included templates inherit all parent scopes
✅ Bidirectional Access - Both templates can read/write shared variables
✅ Dynamic Execution - Template paths can be computed at runtime
✅ Multiple Formats - Script and template syntax supported
Common Use Cases
Header/Footer Templates - Shared site layouts
Utility Functions - Reusable function libraries
Configuration Files - Shared settings and constants
Mixins - Injecting helper methods into contexts
Partial Views - Reusable UI components
📝 Include Syntax
BoxLang provides multiple syntax options for including templates:
Script Syntax
Template Syntax
Include Attributes
template
string
✅ Yes
-
Path to template file (relative, absolute, or mapping)
externalOnly
boolean
❌ No
false
If true, prevents including templates from within classes
Syntax Examples
🔄 Scope Absorption
The most important characteristic of includes is complete scope absorption. When a template is included, it has full access to all scopes in the including template.
How Scope Absorption Works
Bidirectional Access
Both the including and included templates can read and write shared variables:
main.bxm:
helper.bxm:
Scope Access Example
process-helper.bxm:
Scope Visibility Comparison
Variables
✅ Full
✅ Yes
Local
✅ Full
✅ Yes
Arguments
✅ Full
✅ Yes
This
✅ Full
✅ Yes
Application
✅ Full
✅ Yes
Session
✅ Full
✅ Yes
Request
✅ Full
✅ Yes
Server
✅ Full
✅ Yes
CGI
✅ Full
❌ Read-only
Form
✅ Full
✅ Yes
URL
✅ Full
✅ Yes
Critical: Included templates have complete access to ALL scopes. This means they can read, modify, or delete ANY variable in the including template. Be careful with what you include!
Practical Scope Examples
Example 1: Shared Utility Functions
main.bxm:
utils/string-helpers.bxm:
Example 2: Configuration Mixin
app.bxm:
config/settings.bxm:
Example 3: Function Scope Access
order-processor.bxm:
🗺️ Template Path Resolution
BoxLang resolves template paths using multiple strategies:
Path Types
Relative
"includes/header.bxm"
Relative to current template directory
Absolute
"/var/www/app/shared.bxm"
Absolute filesystem path
Mapping
"/app/includes/util.bxm"
BoxLang mapping (starts with /mapping/)
Dot-Notation
"../shared/functions.bxm"
Parent directory traversal
Path Resolution Examples
Dynamic Path Resolution
Path Resolution Algorithm
⚙️ Configuration
You can configure which file extensions BoxLang will process as valid templates using the validTemplateExtensions setting in boxlang.json.
Default Template Extensions
BoxLang includes these core template extensions by default:
.bxs- BoxLang script.bxm- BoxLang markup (template).bxml- BoxLang XML.cfm- ColdFusion markup.cfml- ColdFusion markup language.cfs- ColdFusion script
Adding Custom Extensions
boxlang.json:
Allow All Extensions
Use the wildcard * to allow any extension to be processed as a template:
boxlang.json:
Security Warning: Using * allows ALL file extensions to be executed as templates. This can be a security risk if you have user-uploaded files or other non-template files in accessible directories!
Configuration Examples
Example 1: Add Custom Extensions
Example 2: Development vs Production
Extension Validation Process
From Configuration.java:
Template Extension Best Practices
✅ Use Standard Extensions - Stick to .bxm, .cfm, .cfs when possible ✅ Descriptive Custom Extensions - Use .inc for includes, .part for partials ✅ Avoid Wildcards - Don't use * in production environments ✅ Document Custom Extensions - Make custom extensions clear to your team ❌ Don't Override Security - Don't allow dangerous extensions like .exe, .dll
📚 Use Cases
Use Case 1: Header/Footer Templates
layout.bxm:
includes/header.bxm:
Use Case 2: Function Libraries
main.bxm:
Use Case 3: Configuration Mixins
Application.bx:
Use Case 4: ColdBox Framework Mixins
ColdBox allows mixin injection at runtime:
Use Case 5: Dynamic Partial Loading
💡 Best Practices
1. Use Descriptive Naming
2. Organize Includes in Directories
3. Document Scope Dependencies
4. Avoid Circular Includes
5. Use Include Guards for One-Time Execution
6. Prefer Composition Over Includes
7. Secure Include Paths
⚠️ A Stern Warning
Warning: Includes are one of the most abused features in ANY language! They can lead to:
Spaghetti Code - Hard to trace execution flow
Namespace Pollution - Variables from includes can conflict
Tight Coupling - Changes in one file affect many others
Testing Challenges - Difficult to unit test included code
Maintenance Nightmares - Unclear dependencies
Easy ≠ Maintainable
Just because includes are easy doesn't mean they're the right solution. Modern design patterns often provide better alternatives:
Better Alternatives
Components
Function includes
Encapsulation, testability, reusability
Dependency Injection
Config includes
Loose coupling, flexibility
Composition
Mixin includes
Clear dependencies, maintainability
Modules
Library includes
Namespacing, versioning, isolation
Services
Utility includes
Stateful operations, lifecycle management
Rule of Thumb: Think twice before using includes, think thrice before using them heavily. Ask yourself: "Could this be a component, service, or module instead?"
🔀 Includes vs Other Patterns
Includes vs Components
Advantages of Components:
Clear dependencies
Easier to test
No scope pollution
Better encapsulation
Includes vs Dependency Injection
Includes vs Modules
📋 Summary
BoxLang includes provide powerful template merging:
✅ Full Scope Absorption - Included templates access all parent scopes
✅ Flexible Syntax - Script, template, and CFML compatibility
✅ Dynamic Paths - Relative, absolute, and mapping-based resolution
✅ Configurable Extensions - Control which files are valid templates
✅ Bidirectional Access - Both templates can read/write shared data
⚠️ Use Sparingly - Consider components, DI, and composition first
🔗 Related Documentation
Variable Scopes - Understanding BoxLang scopes
Components - Object-oriented alternatives
Modularity - Module system
Application.bx - Application configuration
ColdBox Mixins - Framework-level mixins
Last updated
Was this helpful?
