0

Joomla Bài học 26: Kỹ thuật Template Overrides: Ghi đè giao diện của Component và Module theo thiết kế riêng

Trong các bài học trước, chúng ta đã học cách cấu hình bố cục tổng thể qua index.php và quản lý tài nguyên tĩnh qua joomla.asset.json. Tuy nhiên, khi bạn cần thay đổi cách hiển thị chi tiết bên trong một Component (ví dụ: đổi thứ tự hiển thị tiêu đề, ngày tháng, ảnh đại diện của trang chi tiết bài viết com_content) hoặc một Module (ví dụ: biến danh sách bài viết mới thành một Slider trượt ngang), việc sửa trực tiếp vào mã nguồn gốc của Joomla là điều cấm kỵ.

Trong Joomla Bài học 26, chúng ta sẽ làm chủ vũ khí lợi hại nhất của lập trình viên giao diện Joomla: Template Overrides (Kỹ thuật ghi đè giao diện). Kỹ thuật này cho phép bạn tùy biến cấu trúc HTML của bất kỳ thành phần nào theo ý muốn mà vẫn giữ nguyên vẹn tính an toàn khi nâng cấp hệ thống Core.

1. Bản chất kỹ thuật của Template Overrides

Khi Joomla xử lý một yêu cầu hiển thị (ví dụ: hiển thị chi tiết bài viết thuộc com_content), bộ định tuyến MVC sẽ đi tìm file giao diện theo thứ tự ưu tiên (Fallback Mechanism):

  1. Kiểm tra đầu tiên tại Template đang hoạt động: Joomla quét thư mục /templates/<ten_template>/html/<component_name>/<view_name>/ (Ví dụ: /templates/joomlalab/html/com_content/article/default.php). Nếu tìm thấy file này, nó sẽ ngay lập tức sử dụng file của bạn và bỏ qua bản gốc.

  2. Kiểm tra tại thư mục gốc của Component (Fallback): Nếu không tìm thấy file ghi đè trong thư mục Template, Joomla mới lùi về lấy file mặc định nằm trong thư mục cốt lõi /components/<component_name>/tmpl/article/default.php.

Nhờ cơ chế này, bạn có thể copy file giao diện gốc ra thư mục html/ của template và thoải mái mổ xẻ, viết thêm code PHP/HTML mà không lo bị mất code khi cập nhật Joomla Core!

2. Quy trình tạo Template Overrides trực quan trên Administrator

Joomla 5 cung cấp công cụ tự động copy file cực kỳ tiện lợi:

  1. Truy cập System →\rightarrow Site Templates →\rightarrow Click chọn joomlalab Details and Files.

  2. Chuyển sang tab Create Overrides.

  3. Giao diện sẽ hiển thị danh sách toàn bộ các thành phần có thể ghi đè được chia theo nhóm:

    • com_content (Component bài viết): Ghi đè trang chi tiết (article), danh sách chuyên mục (category), trang blog (category_blog).

    • mod_articles_latest (Module bài viết mới nhất).

    • com_users, com_contact, com_finder, v.v.

  4. Bấm vào mục bạn muốn ghi đè (Ví dụ: click vào com_content →\rightarrow chọn article).

  5. Hệ thống sẽ báo thông báo thành công: Override created successfully. Ngay lập tức, file giao diện đã được tự động sao chép vào thư mục /templates/joomlalab/html/com_content/article/default.php.

3. Cấu trúc thư mục Overrides thực tế trong dự án

Nếu mở thư mục mã nguồn src/ trên IDE của bạn, cấu trúc file ghi đè sẽ có dạng:

Plaintext

src/templates/joomlalab/html/
├── com_content/
│   ├── article/
│   │   └── default.php             <-- Ghi đè trang chi tiết bài viết
│   └── category/
│       └── blog.php                <-- Ghi đè trang danh sách blog
└── mod_articles_latest/
    └── default.php                 <-- Ghi đè module bài viết mới nhất

4. Thực hành: Tùy biến file Override com_content/article/default.php

Hãy mở file vừa được tạo tại src/templates/joomlalab/html/com_content/article/default.php. Đây là file PHP chứa HTML kết hợp với các biến dữ liệu được truyền từ Model/View của component.

Chúng ta sẽ tùy biến lại cấu trúc: Đưa ảnh đại diện (fullImage) lên trên cùng làm tiêu đề tràn viền, đẩy tên tác giả và ngày tháng xuống dưới, đồng thời bọc các Custom Fields thành một bảng thông số đẹp mắt:

PHP

<?php
\defined('_JEXEC') or die;

use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;

/** @var \Joomla\Component\Content\Site\View\Article\HtmlView $this */

$item = $this->item;
$params = $item->params;
$images = json_decode($item->images);
?>

<article class="item-page custom-article-override">
    <!-- 1. TIÊU ĐỀ BÀI VIẾT -->
    <?php if ($params->get('show_title')) : ?>
        <header class="article-header mb-4">
            <h1 class="fw-bold display-5 text-dark"><?php echo $this->escape($item->title); ?></h1>
            
            <!-- THÔNG TIN TÁC GIẢ VÀ NGÀY THÁNG -->
            <div class="text-muted small mt-2">
                <span class="me-3"><i class="fas fa-calendar-alt"></i> <?php echo HTMLHelper::_('date', $item->publish_up, Text::_('DATE_FORMAT_LC3')); ?></span>
                <?php if ($params->get('show_author') && !empty($item->author)) : ?>
                    <span><i class="fas fa-user"></i> <?php echo $this->escape($item->author); ?></span>
                <?php endif; ?>
            </div>
        </header>
    <?php endif; ?>

    <!-- 2. ẢNH ĐẠI DIỆN LỚN (FULL IMAGE) -->
    <?php if (!empty($images->image_fulltext)) : ?>
        <div class="article-image mb-4 overflow-hidden rounded-4 shadow-sm">
            <img src="<?php echo htmlspecialchars($images->image_fulltext, ENT_QUOTES, 'UTF-8'); ?>" 
                 alt="<?php echo htmlspecialchars($images->image_fulltext_alt, ENT_QUOTES, 'UTF-8'); ?>" 
                 class="img-fluid w-100 object-fit-cover" style="max-height: 450px;">
            <?php if (!empty($images->image_fulltext_caption)) : ?>
                <figcaption class="text-center text-muted small mt-2 fst-italic">
                    <?php echo htmlspecialchars($images->image_fulltext_caption, ENT_QUOTES, 'UTF-8'); ?>
                </figcaption>
            <?php endif; ?>
        </div>
    <?php endif; ?>

    <!-- 3. NỘI DUNG CHÍNH CỦA BÀI VIẾT -->
    <section class="article-content fs-5 text-secondary lh-lg mb-5">
        <?php echo $item->text; ?>
    </section>

    <!-- 4. HIỂN THỊ CUSTOM FIELDS (NẾU CÓ) -->
    <?php if (!empty($item->jcfields)) : ?>
        <div class="card border-0 bg-light rounded-4 p-4 mb-4">
            <h4 class="fw-bold mb-3 fs-5 text-dark"><i class="fas fa-info-circle me-2"></i> Thông số kỹ thuật</h4>
            <table class="table table-borderless mb-0">
                <tbody>
                    <?php foreach ($item->jcfields as $field) : ?>
                        <?php if (!empty($field->value)) : ?>
                            <tr>
                                <td class="fw-semibold text-dark w-25"><?php echo htmlspecialchars($field->label, ENT_COMPAT, 'UTF-8'); ?>:</td>
                                <td class="text-secondary"><?php echo $field->value; ?></td>
                            </tr>
                        <?php endif; ?>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>
    <?php endif; ?>
</article>

5. Kỹ thuật tạo Alternative Layouts (Layout thay thế tùy chọn)

Đôi khi bạn không muốn ghi đè toàn bộ trang chi tiết bài viết mặc định (default.php), mà muốn tạo ra một Layout riêng biệt chỉ áp dụng cho một số bài viết đặc biệt (Ví dụ: một bài viết có giao diện dạng Báo cáo toàn màn hình, bài khác dạng Tin tức ngắn).

Cách thực hiện cực kỳ đơn giản:

  1. Copy file /templates/joomlalab/html/com_content/article/default.php ra thành một file mới ngay trong cùng thư mục và đặt tên tùy ý, ví dụ landing.php.

  2. Mở file landing.php lên và tùy biến cấu trúc HTML theo ý muốn (ví dụ: ẩn sidebar, dùng màu nền tối).

  3. Khi bạn quay lại trang quản trị Joomla, vào một bài viết bất kỳ →\rightarrow chuyển sang tab Page Display (hoặc Options tùy phiên bản), tại mục Alternative Layout, bạn sẽ thấy xuất hiện lựa chọn landing trong danh sách dropdown!

  4. Khi chọn landing, Joomla sẽ tự động dùng file landing.php của template để render riêng cho bài viết đó mà không làm ảnh hưởng đến các bài viết khác dùng default.php.

6. Tổng kết bài học

  • Hiểu rõ cơ chế tìm kiếm và ghi đè MVC qua thư mục /templates/<template>/html/.

  • Thành thạo quy trình tạo bản ghi đè cho Component (com_content) và Module ngay trên giao diện Administrator.

  • Biết cách tối ưu hóa file Override bằng cách sử dụng các biến $this->item, $item->jcfields và tạo Alternative Layouts để linh hoạt thay đổi giao diện theo từng bài viết cụ thể.

Trong Bài học 27, chúng ta sẽ tiếp tục khám phá kỹ thuật tái sử dụng thành phần giao diện dùng chung trong hệ thống: Kỹ thuật Layout Overrides (JLayout): Tái sử dụng các thành phần giao diện dùng chung.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí