joomla-template-overrides
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseJoomla Template Overrides - Complete System
Joomla 模板重写系统完全指南
Introduction
简介
Template overrides allow you to customize the output of components, modules, and plugins without modifying core files. They are stored in and are automatically loaded in place of the original files.
/templates/[name]/html/Covers: Joomla 5.x, 6.x | Requirements: Basic knowledge of PHP, Joomla folder structure
模板重写允许你在不修改核心文件的前提下,自定义组件、模块和插件的输出内容。它们存储在目录中,会自动加载以替代原始文件。
/templates/[name]/html/适用版本:Joomla 5.x、6.x | 前置要求:具备PHP基础和Joomla目录结构相关知识
Fundamental Concepts
核心概念
Why Use Overrides?
为什么使用模板重写?
- Customize presentation without modifying core
- Maintain functionality when updating Joomla
- Reuse code across views
- Separate presentation logic
- 无需修改核心文件即可自定义展示效果
- Joomla更新时仍能保留原有功能
- 在多个视图间复用代码
- 分离展示逻辑
Loading Hierarchy
加载优先级
Joomla looks for files in this order:
- → Custom override
/templates/[active]/html/[path] - → Original file
/[component]/views/[view]/tmpl/
Joomla会按照以下顺序查找文件:
- → 自定义重写文件
/templates/[active]/html/[path] - → 原始文件
/[component]/views/[view]/tmpl/
/html/ Folder Structure
/html/ 目录结构
/templates/cassiopeia/html/
├── com_content/ # Components (com_)
│ ├── article/
│ │ └── default.php
│ └── category/
│ ├── blog.php
│ ├── blog_item.php
│ └── default.php
├── mod_login/ # Modules (mod_)
│ ├── default.php
│ └── slim.php
├── plg_content_pagenavigation/ # Plugins (plg_)
│ └── default.php
└── layouts/ # Reusable JLayouts
└── joomla/
└── content/
├── intro_image.php
└── info_block.phpNaming Convention:
- → components
com_[component] - → modules
mod_[module] - → plugins
plg_[group]_[plugin]
/templates/cassiopeia/html/
├── com_content/ # Components (com_)
│ ├── article/
│ │ └── default.php
│ └── category/
│ ├── blog.php
│ ├── blog_item.php
│ └── default.php
├── mod_login/ # Modules (mod_)
│ ├── default.php
│ └── slim.php
├── plg_content_pagenavigation/ # Plugins (plg_)
│ └── default.php
└── layouts/ # Reusable JLayouts
└── joomla/
└── content/
├── intro_image.php
└── info_block.php命名规则:
- → 组件
com_[component] - → 模块
mod_[module] - → 插件
plg_[group]_[plugin]
Component Overrides - com_content
组件重写 - com_content
Single Article (article/default.php)
单篇文章 - article/default.php
Original Location:
Override:
/components/com_content/views/article/tmpl/default.php/templates/cassiopeia/html/com_content/article/default.phpAvailable variables:
- → article object
$this->item - → parameters
$this->params - → custom fields
$this->item->jcfields
php
<?php defined('_JEXEC') or die; ?>
<article class="article-container">
<header class="article-header">
<h1><?php echo htmlspecialchars($this->item->title); ?></h1>
</header>
<section class="article-body">
<?php if (!empty($this->item->images)): ?>
<?php echo JLayoutHelper::render('joomla.content.intro_image',
['item' => $this->item]); ?>
<?php endif; ?>
<?php echo $this->item->text; ?>
</section>
<?php if (!empty($this->item->jcfields)): ?>
<section class="article-custom-fields">
<?php foreach ($this->item->jcfields as $field): ?>
<div class="field-<?php echo htmlspecialchars($field->type); ?>">
<strong><?php echo htmlspecialchars($field->label); ?></strong>
<?php echo $field->rawvalue; ?>
</div>
<?php endforeach; ?>
</section>
<?php endif; ?>
</article>原始路径:
重写路径:
/components/com_content/views/article/tmpl/default.php/templates/cassiopeia/html/com_content/article/default.php可用变量:
- → 文章对象
$this->item - → 参数配置
$this->params - → 自定义字段
$this->item->jcfields
php
<?php defined('_JEXEC') or die; ?>
<article class="article-container">
<header class="article-header">
<h1><?php echo htmlspecialchars($this->item->title); ?></h1>
</header>
<section class="article-body">
<?php if (!empty($this->item->images)): ?>
<?php echo JLayoutHelper::render('joomla.content.intro_image',
['item' => $this->item]); ?>
<?php endif; ?>
<?php echo $this->item->text; ?>
</section>
<?php if (!empty($this->item->jcfields)): ?>
<section class="article-custom-fields">
<?php foreach ($this->item->jcfields as $field): ?>
<div class="field-<?php echo htmlspecialchars($field->type); ?>">
<strong><?php echo htmlspecialchars($field->label); ?></strong>
<?php echo $field->rawvalue; ?>
</div>
<?php endforeach; ?>
</section>
<?php endif; ?>
</article>Category Blog Mode - blog_item.php
分类博客模式 - blog_item.php
Location:
/templates/cassiopeia/html/com_content/category/blog_item.phpRenders each article in the blog:
php
<?php defined('_JEXEC') or die;
$item = $this->item; ?>
<article class="blog-item">
<h2 class="item-title">
<?php echo JHtml::_('link', JRoute::_($item->link),
htmlspecialchars($item->title)); ?>
</h2>
<?php if (!empty($item->images)): ?>
<?php echo JLayoutHelper::render('joomla.content.intro_image',
['item' => $item]); ?>
<?php endif; ?>
<div class="item-content">
<?php echo $item->introtext; ?>
</div>
<a href="<?php echo JRoute::_($item->link); ?>" class="read-more">
Read more
</a>
</article>路径:
/templates/cassiopeia/html/com_content/category/blog_item.php用于渲染博客中的每一篇文章:
php
<?php defined('_JEXEC') or die;
$item = $this->item; ?>
<article class="blog-item">
<h2 class="item-title">
<?php echo JHtml::_('link', JRoute::_($item->link),
htmlspecialchars($item->title)); ?>
</h2>
<?php if (!empty($item->images)): ?>
<?php echo JLayoutHelper::render('joomla.content.intro_image',
['item' => $item]); ?>
<?php endif; ?>
<div class="item-content">
<?php echo $item->introtext; ?>
</div>
<a href="<?php echo JRoute::_($item->link); ?>" class="read-more">
Read more
</a>
</article>Category List Mode - default.php
分类列表模式 - default.php
Location:
/templates/cassiopeia/html/com_content/category/default.phpMain container with article table.
路径:
/templates/cassiopeia/html/com_content/category/default.php包含文章列表的主容器。
Module Overrides
模块重写
Structure
结构
Location:
/templates/[template]/html/mod_[module]/[layout].phpCommon modules:
- → login form
mod_login - → menus
mod_menu - → custom content
mod_custom - → latest articles
mod_articles_latest - → breadcrumbs
mod_breadcrumbs
路径:
/templates/[template]/html/mod_[module]/[layout].php常见模块:
- → 登录表单
mod_login - → 导航菜单
mod_menu - → 自定义内容
mod_custom - → 最新文章
mod_articles_latest - → 面包屑导航
mod_breadcrumbs
Example: mod_login Override
示例:mod_login 重写
Location:
/templates/cassiopeia/html/mod_login/default.phpphp
<?php defined('_JEXEC') or die;
$params = $this->params; ?>
<form action="<?php echo JRoute::_('index.php'); ?>" method="post" class="login-form">
<div class="form-group">
<label for="login-username">Username</label>
<input type="text" name="username" id="login-username"
class="form-control" required>
</div>
<div class="form-group">
<label for="login-password">Password</label>
<input type="password" name="password" id="login-password"
class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">Log In</button>
<input type="hidden" name="option" value="com_users">
<input type="hidden" name="task" value="user.login">
<input type="hidden" name="return" value="<?php echo base64_encode(JUri::current()); ?>">
<?php echo JHtml::_('form.token'); ?>
</form>路径:
/templates/cassiopeia/html/mod_login/default.phpphp
<?php defined('_JEXEC') or die;
$params = $this->params; ?>
<form action="<?php echo JRoute::_('index.php'); ?>" method="post" class="login-form">
<div class="form-group">
<label for="login-username">Username</label>
<input type="text" name="username" id="login-username"
class="form-control" required>
</div>
<div class="form-group">
<label for="login-password">Password</label>
<input type="password" name="password" id="login-password"
class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">Log In</button>
<input type="hidden" name="option" value="com_users">
<input type="hidden" name="task" value="user.login">
<input type="hidden" name="return" value="<?php echo base64_encode(JUri::current()); ?>">
<?php echo JHtml::_('form.token'); ?>
</form>Alternative Layouts
替代布局
Selectable variations without fully replacing the view.
可选择的视图变体,无需完全替换原有视图。
Difference vs Template Override
与模板重写的区别
| Aspect | Override | Alternative Layout |
|---|---|---|
| Application | Automatic site-wide | Selectable per module |
| File | default.php (replaces) | Unique name (e.g.: grid.php) |
| Usage | Replaces original view | Option alongside original |
| 维度 | 模板重写 | 替代布局 |
|---|---|---|
| 应用范围 | 全站自动生效 | 可按模块单独选择 |
| 文件名称 | default.php(替换原有) | 唯一名称(如:grid.php) |
| 使用方式 | 替换原始视图 | 与原始视图作为选项共存 |
Creating an Alternative Layout
创建替代布局
For modules: Multiple files in
/html/mod_[module]/php
// /templates/cassiopeia/html/mod_login/grid.php
// Alternative grid layout for mod_login
<?php defined('_JEXEC') or die; ?>
<div class="login-grid">
<!-- grid structure -->
</div>For components: In menu select "Alternative Layout"
Naming rules:
- Do not use underscores
- Descriptive names: ,
grid.php,minimal.phpcard.php - = original layout
default.php
针对模块:在目录下创建多个文件
/html/mod_[module]/php
// /templates/cassiopeia/html/mod_login/grid.php
// mod_login的网格型替代布局
<?php defined('_JEXEC') or die; ?>
<div class="login-grid">
<!-- grid structure -->
</div>针对组件:在菜单设置中选择「替代布局」
命名规则:
- 不要使用下划线
- 使用描述性名称:、
grid.php、minimal.phpcard.php - = 原始布局
default.php
JLayout - Reusable Components
JLayout - 可复用组件
System for creating reusable fragments.
Joomla layouts location:
/layouts/joomla/[group]/[layout].phpOverride:
/templates/cassiopeia/html/layouts/joomla/[group]/[layout].php用于创建可复用代码片段的系统。
Joomla布局原始路径:
/layouts/joomla/[group]/[layout].php重写路径:
/templates/cassiopeia/html/layouts/joomla/[group]/[layout].phpCreating a Custom Layout
创建自定义布局
php
// /templates/cassiopeia/html/layouts/joomla/custom/article-card.php
<?php defined('_JEXEC') or die;
$title = $displayData['title'] ?? '';
$content = $displayData['content'] ?? '';
$image = $displayData['image'] ?? '';
$link = $displayData['link'] ?? '#';
?>
<article class="card">
<?php if ($image): ?>
<figure class="card-image">
<img src="<?php echo htmlspecialchars($image); ?>"
alt="<?php echo htmlspecialchars($title); ?>">
</figure>
<?php endif; ?>
<div class="card-body">
<h3><?php echo htmlspecialchars($title); ?></h3>
<div class="card-content">
<?php echo $content; ?>
</div>
<a href="<?php echo htmlspecialchars($link); ?>" class="card-link">
View more
</a>
</div>
</article>php
// /templates/cassiopeia/html/layouts/joomla/custom/article-card.php
<?php defined('_JEXEC') or die;
$title = $displayData['title'] ?? '';
$content = $displayData['content'] ?? '';
$image = $displayData['image'] ?? '';
$link = $displayData['link'] ?? '#';
?>
<article class="card">
<?php if ($image): ?>
<figure class="card-image">
<img src="<?php echo htmlspecialchars($image); ?>"
alt="<?php echo htmlspecialchars($title); ?>">
</figure>
<?php endif; ?>
<div class="card-body">
<h3><?php echo htmlspecialchars($title); ?></h3>
<div class="card-content">
<?php echo $content; ?>
</div>
<a href="<?php echo htmlspecialchars($link); ?>" class="card-link">
View more
</a>
</div>
</article>Usage in blog_item.php
在blog_item.php中使用
php
<?php echo JLayoutHelper::render('joomla.custom.article-card', [
'title' => $this->item->title,
'content' => $this->item->introtext,
'image' => json_decode($this->item->images)->image_intro ?? '',
'link' => JRoute::_($this->item->link),
]); ?>php
<?php echo JLayoutHelper::render('joomla.custom.article-card', [
'title' => $this->item->title,
'content' => $this->item->introtext,
'image' => json_decode($this->item->images)->image_intro ?? '',
'link' => JRoute::_($this->item->link),
]); ?>Child Templates
子模板
A template that inherits from a parent, only storing changes.
从父模板继承的模板,仅存储修改的内容。
Creating a Child Template
创建子模板
Structure:
/templates/cassiopeia-child/
├── html/
│ └── com_content/article/default.php (custom override)
├── css/
│ └── custom.css
└── templateDetails.xmltemplateDetails.xml:
xml
<?xml version="1.0" encoding="utf-8"?>
<extension type="template" client="site">
<name>Cassiopeia Child</name>
<version>1.0.0</version>
<description>Child template based on Cassiopeia</description>
<parent>cassiopeia</parent>
<files>
<folder>html</folder>
<folder>css</folder>
<filename>templateDetails.xml</filename>
</files>
<positions>
<position>header</position>
<position>sidebar</position>
<position>footer</position>
</positions>
</extension>Advantages:
- Automatically inherits non-customized files
- Only stores modified files
- Simplifies maintenance and updates
- Allows multiple variations of the same parent
目录结构:
/templates/cassiopeia-child/
├── html/
│ └── com_content/article/default.php (custom override)
├── css/
│ └── custom.css
└── templateDetails.xmltemplateDetails.xml:
xml
<?xml version="1.0" encoding="utf-8"?>
<extension type="template" client="site">
<name>Cassiopeia Child</name>
<version>1.0.0</version>
<description>Child template based on Cassiopeia</description>
<parent>cassiopeia</parent>
<files>
<folder>html</folder>
<folder>css</folder>
<filename>templateDetails.xml</filename>
</files>
<positions>
<position>header</position>
<position>sidebar</position>
<position>footer</position>
</positions>
</extension>优势:
- 自动继承未自定义的文件
- 仅存储修改过的文件
- 简化维护和更新流程
- 允许基于同一父模板创建多个变体
Field Overrides - Custom Fields
字段重写 - 自定义字段
Override how custom fields are displayed.
Location:
/templates/[template]/html/layouts/com_fields/field/[layout].phpphp
// /templates/cassiopeia/html/layouts/com_fields/field/render.php
<?php defined('_JEXEC') or die;
$field = $displayData['field'] ?? null;
$value = $displayData['value'] ?? null;
if (!$field || !$value) return;
?>
<div class="field-container" data-field-id="<?php echo (int)$field->id; ?>">
<label class="field-label">
<?php echo htmlspecialchars($field->label); ?>
</label>
<div class="field-value">
<?php echo $value; ?>
</div>
</div>Select in backend: Field Edit > Render Options > Layout
重写自定义字段的展示方式。
路径:
/templates/[template]/html/layouts/com_fields/field/[layout].phpphp
// /templates/cassiopeia/html/layouts/com_fields/field/render.php
<?php defined('_JEXEC') or die;
$field = $displayData['field'] ?? null;
$value = $displayData['value'] ?? null;
if (!$field || !$value) return;
?>
<div class="field-container" data-field-id="<?php echo (int)$field->id; ?>">
<label class="field-label">
<?php echo htmlspecialchars($field->label); ?>
</label>
<div class="field-value">
<?php echo $value; ?>
</div>
</div>在后台选择:字段编辑 > 渲染选项 > 布局
Template Manager - Creating Overrides
模板管理器 - 创建重写
Backend: Extensions > Templates > [Template] > Create Overrides
Advantages:
- Intuitive visual interface
- Automatically copies files
- No manual searching required
- Ensures correct structure
后台路径:扩展 > 模板 > [对应模板] > 创建重写
优势:
- 直观的可视化界面
- 自动复制文件
- 无需手动查找路径
- 确保目录结构正确
Best Practices
最佳实践
Code Documentation
代码文档
php
<?php
/**
* Override: Custom article
*
* Component: com_content
* Original view: article/tmpl/default.php
*
* CHANGES:
* - Improved semantic structure
* - Added custom fields
* - Reordered metadata
*
* DEPENDENCIES: Custom field 'author-bio'
* JOOMLA: 5.0+
* DATE: 2024-03-06
*/
defined('_JEXEC') or die;php
<?php
/**
* 重写:自定义文章视图
*
* 组件:com_content
* 原始视图:article/tmpl/default.php
*
* 修改内容:
* - 优化语义化结构
* - 添加自定义字段展示
* - 调整元数据顺序
*
* 依赖项:自定义字段'author-bio'
* 适配Joomla版本:5.0+
* 日期:2024-03-06
*/
defined('_JEXEC') or die;Security - Escaping
安全 - 输出转义
php
// GOOD: Escape outputs
<?php echo htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8'); ?>
<?php echo JHtml::_('string.truncate', $item->text, 100); ?>
// GOOD: URLs with JRoute
<?php echo JRoute::_('index.php?option=com_content&view=article&id=' . $item->id); ?>
// BAD: Unescaped output
<?php echo $item->title; ?>php
// 推荐:对输出内容进行转义
<?php echo htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8'); ?>
<?php echo JHtml::_('string.truncate', $item->text, 100); ?>
// 推荐:使用JRoute生成URL
<?php echo JRoute::_('index.php?option=com_content&view=article&id=' . $item->id); ?>
// 不推荐:未转义的输出
<?php echo $item->title; ?>Post-Update Testing
更新后测试
bash
undefinedbash
undefinedCompare overrides with core files
对比重写文件与核心文件的差异
diff -u /components/com_content/views/article/tmpl/default.php
/templates/cassiopeia/html/com_content/article/default.php
/templates/cassiopeia/html/com_content/article/default.php
diff -u /components/com_content/views/article/tmpl/default.php
/templates/cassiopeia/html/com_content/article/default.php
/templates/cassiopeia/html/com_content/article/default.php
Backup overrides before updating
更新前备份重写文件
cp -r templates/cassiopeia/html templates/cassiopeia/html.backup
undefinedcp -r templates/cassiopeia/html templates/cassiopeia/html.backup
undefinedAvoid Unnecessary Overrides
避免不必要的重写
- Only override if you modify the view
- Use alternative layouts for variations
- Use JLayout for reusable components
- Maintain change tracking (git, documentation)
- 仅在需要修改视图时才创建重写
- 使用替代布局实现视图变体
- 使用JLayout创建可复用组件
- 维护修改记录(Git、文档)
Troubleshooting
故障排查
Override Not Working
重写未生效
- Verify correct path in
/templates/[active]/html/ - Clear cache (System > Clear Cache)
- Verify file permissions (755 folders, 644 files)
- Verify PHP syntax (php -l file.php)
- Check error logs in
/logs/
- 验证目录下的路径是否正确
/templates/[active]/html/ - 清除缓存(系统 > 清除缓存)
- 验证文件权限(文件夹755,文件644)
- 验证PHP语法(执行php -l file.php)
- 查看目录下的错误日志
/logs/
File Permissions
文件权限设置
bash
undefinedbash
undefinedFolders: read+execute
文件夹:可读+可执行
chmod 755 /templates/cassiopeia/html/
chmod 755 /templates/cassiopeia/html/
Files: read
文件:可读
chmod 644 /templates/cassiopeia/html/com_content/article/default.php
undefinedchmod 644 /templates/cassiopeia/html/com_content/article/default.php
undefinedCaching Issues
缓存问题
- Clear cache in backend: System > Clear Cache
- Template option: Style Edit > Caching
- Verify router cache in configuration.php
- 后台清除缓存:系统 > 清除缓存
- 模板设置:样式编辑 > 缓存
- 验证configuration.php中的路由缓存配置
Practical Case: Featured Articles
实战案例:特色文章展示
Objective: Display featured articles in card format
Steps:
- Create override:
com_content/article/featured.php - Create JLayout:
layouts/joomla/custom/featured-card.php - Use in override with JLayoutHelper::render()
- Assign custom CSS
See complete examples in
/referencias/目标:以卡片形式展示特色文章
步骤:
- 创建重写文件:
com_content/article/featured.php - 创建JLayout:
layouts/joomla/custom/featured-card.php - 在重写文件中使用JLayoutHelper::render()调用
- 添加自定义CSS样式
完整示例请查看目录
/referencias/Quick Reference
快速参考
Common Paths
常见路径
| Element | Original | Override |
|---|---|---|
| Article | | |
| Blog item | | |
| Category list | | |
| Login module | | |
| JLayout image | | |
| Nav plugin | | |
| 元素 | 原始路径 | 重写路径 |
|---|---|---|
| 文章 | | |
| 博客文章项 | | |
| 分类列表 | | |
| 登录模块 | | |
| JLayout图片 | | |
| 导航插件 | | |
Checklist - Creating an Override
创建重写的检查清单
- Locate original file in core
- Create structure in template
/html/ - Copy file to override location
- Make modifications
- Escape outputs correctly
- Document changes in header
- Test in browser
- Clear cache
- Verify at different resolutions
- Use Template Manager to verify structure
- 定位核心文件的原始路径
- 在模板中创建目录结构
/html/ - 将核心文件复制到重写路径
- 进行修改
- 正确转义输出内容
- 在文件头部添加修改文档
- 在浏览器中测试
- 清除缓存
- 在不同分辨率下验证效果
- 使用模板管理器验证目录结构
Useful Variables
常用变量
php
// Articles
$this->item->id
$this->item->title
$this->item->introtext
$this->item->text
$this->item->images (JSON)
$this->item->jcfields (custom fields)
// Parameters
$this->params->get('show_author')
$this->params->get('show_category')
// Modules
$this->module->id
$this->module->title
$this->params
// JLayout
$displayData (array of passed data)php
// 文章相关
$this->item->id
$this->item->title
$this->item->introtext
$this->item->text
$this->item->images (JSON格式)
$this->item->jcfields (自定义字段)
// 参数相关
$this->params->get('show_author')
$this->params->get('show_category')
// 模块相关
$this->module->id
$this->module->title
$this->params
// JLayout相关
$displayData(传入的参数数组)Additional Resources
额外资源
- Joomla Documentation - Template Overrides
- [Template Manager in Backend](Extensions > Templates)
- Joomla Magazine - Child Templates
- Debugging - developer.joomla.org
- Joomla官方文档 - 模板重写
- 后台模板管理器(扩展 > 模板)
- Joomla杂志 - 子模板
- 调试指南 - developer.joomla.org