Bỏ qua tới nội dung
WordPress· ·10 phút đọc

Viết functions.php đúng cách trong WordPress (tránh biến nó thành ngăn kéo rác)

Vũ Đức Minh
Viết functions.php đúng cách trong WordPress (tránh biến nó thành ngăn kéo rác)
Cỡ chữ

Hầu như mọi theme WordPress đều có một file functions.php, và nó cũng là nơi dễ bị lạm dụng nhất. Bài này giải thích file này thực sự làm gì, những lỗi khiến website của bạn dễ vỡ, và cách tổ chức code gọn gàng theo chuẩn 2026.

functions.php thực chất là gì

Theo tài liệu chính thức của WordPress, functions.php “hoạt động giống như một plugin” — nó nạp tự động mỗi khi theme đang kích hoạt, cho phép bạn móc vào (hook — bắt vào điểm chạy có sẵn của WordPress) lõi hệ thống để thêm hoặc đổi hành vi. Khác biệt cốt lõi so với plugin nằm ở phạm vi:

  • functions.php: không cần header, chỉ chạy khi theme đó đang bật, tự nạp theo theme.
  • plugin: có header khai báo, chạy bất kể theme nào, bật/tắt độc lập.

Hệ quả quan trọng: nếu bạn đặt một chức năng trong functions.php rồi đổi theme, chức năng đó biến mất theo. Đây là nguyên nhân gốc của rất nhiều rắc rối phía sau.

Bốn lỗi hay gặp nhất với functions.php

1. Nhồi quá nhiều thứ vào một file

Cộng đồng WordPress gọi functions.php là “ngăn kéo rác” (junk drawer — chỗ vứt mọi thứ linh tinh). Một file dài vài nghìn dòng gồm custom post type, shortcode, đăng ký script, tinh chỉnh excerpt, vá lỗi tạm… rất khó đọc, khó tìm bug, và một dấu chấm phẩy thiếu ở dòng 1.800 có thể làm trắng cả website. File càng phình, rủi ro càng cao.

2. Không prefix tên hàm

WordPress nạp theme, plugin và lõi vào cùng một không gian tên toàn cục. Nếu bạn đặt hàm tên chung chung như get_related_posts(), sớm muộn cũng đụng tên với một plugin khác — và WordPress sẽ báo lỗi fatal “Cannot redeclare function”. Tài liệu chính thức yêu cầu đặt tiền tố là tên hoặc viết tắt của theme. Web22 dùng tiền tố web22_ cho mọi hàm tự viết trong theme custom.

3. Sửa trực tiếp file của theme cha

Nếu bạn dùng một theme mua sẵn và sửa thẳng functions.php của nó, lần cập nhật theme tiếp theo sẽ ghi đè toàn bộ — code của bạn mất sạch. Đây là lý do tồn tại của theme con (child theme).

4. Sửa lõi WordPress hoặc chép-dán template thay vì dùng hook

Đừng bao giờ chỉnh file trong wp-includes hay wp-admin; mọi thứ ở đó bị ghi đè mỗi lần nâng cấp WordPress. Thay vào đó, gần như mọi nhu cầu đều có sẵn một action hoặc filter để móc vào.

So sánh cách viết functions.php sai và đúng cho theme WordPress
Bốn lỗi quen tay khiến functions.php thành ngăn kéo rác, đặt cạnh cách làm gọn gàng.

Đặt code ở child theme, không phải theme cha

Quy tắc an toàn: nếu bạn dùng theme bên thứ ba, mọi tùy biến đi vào functions.php của child theme. WordPress nạp functions.php của theme con trước theme cha, và cả hai cùng chạy — nên bạn chỉ cần chép những hàm tự viết của mình, không cần chép lại hàm của theme cha. Nhờ vậy theme cha vẫn cập nhật bình thường mà code của bạn còn nguyên.

<?php
// functions.php trong child theme
add_action( 'wp_enqueue_scripts', 'web22_child_styles' );
function web22_child_styles() {
    // nạp style của theme cha trước
    wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
    // rồi nạp style của theme con đè lên
    wp_enqueue_style(
        'child-style',
        get_stylesheet_directory_uri() . '/style.css',
        array( 'parent-style' )
    );
}

Lưu ý cặp hàm hay nhầm: get_template_directory_uri() luôn trỏ về theme cha, còn get_stylesheet_directory_uri() trỏ về theme con (theme đang kích hoạt). Đặt sai một trong hai là style của bạn không nạp được. Chi tiết quy trình nạp tài nguyên đúng thứ tự nằm ở bài về cách enqueue script và style chuẩn.

Dùng hook thay vì sửa trực tiếp

Triết lý của WordPress là mở rộng qua hook. Thay vì sửa template, bạn móc một filter để đổi kết quả. Ví dụ đổi độ dài đoạn trích (excerpt):

<?php
add_filter( 'excerpt_length', 'web22_excerpt_length' );
function web22_excerpt_length( $length ) {
    return 30; // 30 từ thay vì mặc định 55
}

Hay khai báo theme hỗ trợ tính năng, đặt trong hàm setup móc vào after_setup_theme để chạy đúng thời điểm:

<?php
add_action( 'after_setup_theme', 'web22_setup' );
function web22_setup() {
    add_theme_support( 'post-thumbnails' );
    add_theme_support( 'title-tag' );
    add_theme_support( 'html5', array( 'search-form', 'gallery' ) );
}

Nếu bạn còn lạ với cơ chế này, bài phân biệt action và filter giải thích kỹ khi nào dùng cái nào.

Tách module: bí quyết giữ functions.php gọn

Cách Web22 tổ chức theme custom của mình: functions.php chỉ làm một việc — định nghĩa hằng số rồi nạp các module nhỏ qua require. Mỗi module lo một mảng việc rõ ràng:

<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit; // chặn truy cập trực tiếp
}

define( 'WEB22_DIR', get_template_directory() );

require WEB22_DIR . '/inc/setup.php';        // add_theme_support, menu
require WEB22_DIR . '/inc/enqueue.php';      // nạp CSS/JS
require WEB22_DIR . '/inc/menus.php';        // điều hướng
require WEB22_DIR . '/inc/template-tags.php';// hàm in HTML dùng lại

Nhờ vậy file gốc chỉ còn hơn chục dòng, dễ đọc như mục lục. Cần sửa phần nạp CSS thì mở đúng inc/enqueue.php, không phải cuộn qua một file khổng lồ. Dòng if ( ! defined( 'ABSPATH' ) ) exit; ở đầu mỗi file là thói quen bảo mật cơ bản — chặn người dùng gọi thẳng file PHP qua URL. Các thực hành tổ chức code sạch khác được gom trong bài tự tay dựng một theme từ đầu. Nếu bạn không tự tay làm phần này mà muốn nhờ Web22 dựng website, chúng mình bàn giao theme đã tách module gọn sẵn từ đầu.

Bảng phân biệt khi nào để code ở functions.php và khi nào tách ra plugin
Chọn chỗ đặt code theo việc nó gắn với giao diện hay gắn với tính năng site.

Khi nào nên chuyển từ functions.php sang plugin

Ranh giới đơn giản: chức năng thuộc về giao diện thì ở theme; chức năng thuộc về nội dung/dữ liệu thì nên là plugin. Vì nếu nó nằm trong theme mà bạn đổi theme, dữ liệu coi như mất kết nối.

Nên đặt ở functions.php (theme con)Nên tách thành plugin
Nạp style/script của themeCustom post type, taxonomy
Đăng ký menu, sidebar, kích thước ảnhShortcode dùng nhiều nơi
add_theme_support, tinh chỉnh excerptTích hợp API, logic SEO/schema

Web22 đẩy toàn bộ custom post type (dịch vụ, dự án) và phần SEO/schema sang một plugin riêng (web22-core), để theme chỉ lo giao diện. Nhờ vậy đổi giao diện không làm sập dữ liệu. Đây chính là tinh thần của một khung plugin gọn theo chuẩn 2026. Với chức năng “phải có dù theme nào” như cấu hình môi trường hay redirect, WordPress còn có thư mục mu-plugins (must-use — plugin bắt buộc, không tắt được).

Câu hỏi thường gặp

Có thể sửa functions.php trong wp-admin không?

Có nút Theme Editor, nhưng đừng dùng. Một lỗi cú pháp khi lưu là website trắng xóa và bạn mất luôn cả trang admin. Sửa qua FTP hoặc trình soạn thảo cục bộ để còn đường lùi.

functions.php nằm ở đâu trong theme con?

Bạn tự tạo file functions.php trong thư mục theme con; nó không tự sinh ra. WordPress sẽ nạp nó cùng với file của theme cha, không ghi đè lên nhau.

Bao nhiêu code thì nên chuyển sang plugin?

Không có con số cứng. Phép thử là câu hỏi: “Nếu mai mình đổi theme, đoạn này có cần giữ không?” Nếu có, nó thuộc về plugin.

Nếu bạn muốn một theme được tổ chức bài bản từ đầu thay vì chữa cháy một functions.php phình to, tham khảo cách Web22 nhận làm website WordPress với code sạch, tách module rõ ràng.

Đọc tiếp

Bài viết
cùng chủ đề.

Tất cả bài viết