Hướng dẫn tạo mục lục tự động cho bài viết bằng PHP
Bài viết hướng dẫn bạn cách tạo mục lục tự động cho nội dung bài viết bằng PHP, sử dụng lớp `DOMDocument` để phân tích cú pháp HTML và tạo cấu trúc mục lục với các tiêu đề.
Trong bài viết này, chúng ta sẽ tìm hiểu cách tạo mục lục tự động cho bài viết bằng PHP. Bằng cách sử dụng hàm generateTOC
, chúng ta sẽ phân tích nội dung HTML và tự động thêm các ID cho các tiêu đề, sau đó tạo ra một danh sách các liên kết đến các tiêu đề đó.
Mã PHP:
<?php
function generateTOC($content) {
// Load HTML content
$dom = new DOMDocument();
$contentType = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
@$dom->loadHTML($contentType . $content);
// Find all headers and add IDs
$headers = $dom->getElementsByTagName('*');
$toc = [];
foreach ($headers as $header) {
if (in_array($header->nodeName, ['h1', 'h2', 'h3', 'h4'])) {
$id = str_slug($header->textContent);
$header->setAttribute('id', $id);
$toc[] = [
'tag' => $header->nodeName,
'text' => $header->textContent,
'id' => $id
];
}
}
// Generate TOC HTML with nested structure
$tocHtml = buildNestedTOC($toc);
if($tocHtml) {
$tocHtml = '<div id="toc"><div id="toc-title"><strong>Table Of Contents</strong></div>' . $tocHtml . '</div>';
}
return $tocHtml . $dom->saveHTML();
}
function buildNestedTOC($toc) {
$html = '';
$prevLevel = 0;
foreach ($toc as $item) {
$currentLevel = (int) substr($item['tag'], 1);
if ($prevLevel == 0) {
$html .= '<ul>';
} elseif ($currentLevel > $prevLevel) {
$html .= '<ul>';
} elseif ($currentLevel < $prevLevel) {
$html .= str_repeat('</ul>', $prevLevel - $currentLevel);
}
$html .= '<li><a href="#' . htmlspecialchars($item['id']) . '">' . htmlspecialchars($item['text']) . '</a></li>';
$prevLevel = $currentLevel;
}
$html .= str_repeat('</ul>', $prevLevel);
return $html;
}
function str_slug($string) {
// Chuyển đổi chuỗi thành slug (chuỗi không dấu)
$slug = preg_replace('/[^A-Za-z0-9-]+/', '-', $string);
return strtolower(trim($slug, '-'));
}
// Ví dụ sử dụng
$content = '<h1>Tiêu đề chính</h1><h2>Tiêu đề phụ 1</h2><h3>Tiêu đề con 1.1</h3><h2>Tiêu đề phụ 2</h2>';
echo generateTOC($content);
?>
Giải thích chi tiết từng dòng code:
function generateTOC($content)
: Định nghĩa hàmgenerateTOC
nhận vào nội dung HTML.$dom = new DOMDocument();
: Khởi tạo một đối tượngDOMDocument
để xử lý HTML.$contentType = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
: Thiết lập thông tin loại nội dung.@$dom->loadHTML($contentType . $content);
: Tải nội dung HTML vào đối tượngDOMDocument
. Dấu@
giúp ẩn thông báo lỗi nếu có.$headers = $dom->getElementsByTagName('*');
: Lấy tất cả các phần tử trong tài liệu.foreach ($headers as $header) {...}
: Duyệt qua từng phần tử và tìm các tiêu đề (h1
,h2
,h3
,h4
).if (in_array($header->nodeName, ['h1', 'h2', 'h3', 'h4'])) {...}
: Kiểm tra xem phần tử có phải là tiêu đề không.$id = str_slug($header->textContent);
: Tạo ID từ nội dung tiêu đề bằng hàmstr_slug
.$header->setAttribute('id', $id);
: Thêm thuộc tính ID vào tiêu đề.$toc[] = [...];
: Thêm thông tin tiêu đề vào mảng$toc
để tạo mục lục.$tocHtml = buildNestedTOC($toc);
: Gọi hàmbuildNestedTOC
để tạo mã HTML cho mục lục.if($tocHtml) {...}
: Nếu có mục lục, tạo phần HTML cho mục lục.return $tocHtml . $dom->saveHTML();
: Trả về mục lục và nội dung HTML gốc.
Yêu cầu hệ thống:
- PHP >= 7.0
- Không cần cài đặt thêm thư viện nào.
Lời khuyên:
- Hàm
str_slug
có thể được điều chỉnh để xử lý các ký tự đặc biệt theo yêu cầu của bạn. - Tạo mục lục giúp người đọc dễ dàng điều hướng và tìm kiếm thông tin trong bài viết dài.