Hiện nay có rất nhiều bạn đang nghĩ rằng tự tùy chỉnh WordPress Meta Box là không cần thiết, lỗi thời bởi có rất nhiều plugin hoặc builder đang hỗ trợ tự động chỉnh sửa tất cả. Nhưng mà điều đó là chưa đúng đâu các fen.
Cho dù các plugin này có hỗ trợ bạn rất tốt nhưng biết cách code để tạo metabox 1 cách thủ công vẫn là rất hữu ích. Ví dụ như Woocommerce chẳng hạn, bạn có thể tùy chỉnh thêm meta box mà không cần cài thêm các plugin phức tạp có sẵn các tính năng không cần thiết với nhu cầu của bạn.
Meta box là gì?
Meta box là các khối giao diện người dùng, cho phép bạn quản lý các metadata của bài đăng.
Vậy metadata là gì?
Mọi loại nội dung trong WordPress như post, term, user và comment đều có bảng riêng trong cơ sở dữ liệu như wp_posts, wp_terms và wp_comments tương ứng. Các bảng đó sẽ lưu trữ một số dữ liệu mặc định, ví dụ như tiêu đề bài đăng, ngày xuất bản của chúng.
Nhưng nếu bạn cần lưu trữ một dữ liệu của riêng bạn thì sao? Ví dụ như tiêu đề cho SEO, độ tuổi của người đọc hoặc giá của sản phẩm? Câu trả lời là metadata. WordPress cũng có các bảng cơ sở dữ liệu cho những dữ liệu đó, tùy nhu cầu của bạn. Ví dụ 1 bảng dữ liệu của sản phẩm có các thông tin như:
Các Meta Box sẽ cho phép bạn quản lý các dữ liệu này, ví dụ như Woocommerce. Bạn có thể thấy giá trị _sale_price trong bảng này tương ứng với Sale price field dưới đây:
Làm thế nào để xóa các Meta Box mặc định?
Trên mỗi trang chỉnh sửa bài đăng, WordPress đã có sẵn các Meta Box được xác định trước. Nếu bạn mở bất kỳ trang chỉnh sửa bài đăng nào bằng “Classic Editor” thì bạn sẽ thấy chúng.
Có 2 cách để xóa Meta Box mặc định:
- Dùng hàm remove_meta_box().
- Dùng hàm remove_post_type_support().
Hàm remove_meta_box()
Ví dụ luôn, chúng ta sẽ xóa 2 meta box “Page Attributes” và “Custom Fields” cho post. Code ví dụ:
add_action( 'admin_menu', 'monkeywp_remove_meta_box' );
function monkeywp_remove_meta_box(){
// Custom Fields
remove_meta_box( 'postcustom', 'post', 'normal' );
// Page Attributes
remove_meta_box( 'pageparentdiv', 'page', 'normal' );
}
Tham số đầu tiên của hàm là Meta Box ID. Đây là danh sách các ID của Meta Box mặc định:
- commentstatusdiv – Discusion.
- slugdiv – Slug.
- commentsdiv – Bình luận.
- postexcept – Excerpt.
- authordiv – Tác giả.
- revisionsdiv – Revisions.
- postcustom – Custom Fields.
- trackbacksdiv – Gửi Trackbacks.
- categorydiv – Danh mục.
- tagsdiv-post_tag – Tags.
- {Taxonomy name}div – Bất cứ taxonomy nào.
- postimagediv – Riêng cái này thì bạn không thể dùng remove_meta_box(), mà phải dùng hàm remove_post_type_support().
- pageparentdiv – Page Attributes (thuộc tính trang).
- submitdiv – Publish.
Tham số thứ hai của hàm remove_meta_box() là post type mà bạn muốn xóa nó.
Hàm remove_post_type_support()
Về mặt kỹ thuật, hàm remove_post_type_support() không xóa Meta Box, nó chỉ vô hiệu hóa chức năng mà mình chỉ định.
Điều hay ho là hàm remove_post_type_support() có thể hoạt động cho cả Gutenberg và Classic Editor.
add_action( 'init', 'monkeywp_remove_meta_box_2' );
function monkeywp_remove_meta_box_2() {
// Featured image
remove_post_type_support( 'page', 'thumbnail' );
// Page attributes
remove_post_type_support( 'page', 'page-attributes' );
}
Bạn có thể thấy 2 đoạn code tương đồng với nhau.
Mình nghĩ cách tốt nhất để xóa Meta Box mặc định của WordPress là dùng hàm remove_post_type_support(). Vì nó sẽ tắt tính năng đó luôn, còn remove_meta_box() chỉ xóa Meta Box.
Tính năng / Meta Box có thể tắt:
- thumbnail — Meta Box ảnh feature
- author — Meta Box tác giả
- excerpt — Meta Box excerpt
- trackbacks — Gửi trackbacks Meta Box
- custom-fields — Custom Fields metabox
- comments — Bình luận metabox
- revisions — Revisions metabox
- page-attributes — Page Attributes metabox (chỉ Gutenberg)
Bạn cũng có thể xóa title hoặc content edior:
- title
- editor
Hàm unregister_taxonomy_for_object_type()
Có thể bạn thấy rằng ở các bước trên mình không đề cập đến việc xóa taxonomy Meta Box. Đó là bởi vì hàm remove_post_type_support() không thể xóa các taxonomy dù nó là tùy chỉnh hoặc mặc định.
Nhưng mà có cách khác:
add_action( 'init', 'monkeywp_remove_taxonomy_meta_boxes' );
function monkeywp_remove_taxonomy_meta_boxes() {
// for Post tags
unregister_taxonomy_for_object_type( 'post_tag', 'post' );
// for Categories
unregister_taxonomy_for_object_type( 'category', 'post' );
}
Thêm Meta Box tùy chỉnh
Và đến phần quan trọng nhất của buổi trình diễn hôm nay. Mình sẽ hướng dẫn bạn cách tạo Meta Box tùy chỉnh trong WordPress. Dưới đây là kết quả mà chúng ta sẽ thực hiện:
Bước 1. add_meta_box()
Hàm add_meta_box() nên được gọi bên trong 1 action hook, có 3 tùy chọn:
- admin_menu
- add_meta_boxes
- add_meta_boxes_{post_type} – bạn có thể liệt kê tên post type cụ thể mà mình muốn. Ví dụ như add_meta_boxes_page.
add_action( 'admin_menu', 'monkeywp_add_metabox' );
// hoặc add_action( 'add_meta_boxes', 'monkeywp_add_metabox' );
// hoặc add_action( 'add_meta_boxes_{post_type}', 'monkeywp_add_metabox' );
function monkeywp_add_metabox() {
add_meta_box(
'monkeywp_metabox', // metabox ID
'Meta Box', // tiêu đề
'monkeywp_metabox_callback', // hàm callback
'page', // thêm meta box vào custom post type
'normal', // vị trí (normal, side, advanced)
'default' // ưu tiên (default, low, high, core)
);
}
// đây là hàm callback, hiển thị và xử lý các giá trị trong Meta Box
function monkeywp_metabox_callback( $post ) {
echo 'hey';
}
Khi bạn chèn code vào functions.php của child theme hay trong 1 custom plugin, Meta Box sẽ hiển thị như sau:
Như bạn có thể thấy, chữ “hey” trong hàm callback sẽ hiển thị bên trong Meta Box.
Bây giờ mình sẽ làm 1 ví dụ khác phức tạp hơn.
Bước 2. Hàm callback với Meta Box HTML
Trong đoạn code dưới đây mình sẽ ví dụ 1 cái custom Meta Box với nhiều field khác nhau.
function monkeywp_metabox_callback( $post ) {
$seo_title = get_post_meta( $post->ID, 'seo_title', true );
$seo_robots = get_post_meta( $post->ID, 'seo_robots', true );
// nonce, thật sự thì cũng không cần thiết lắm
wp_nonce_field( 'somerandomstr', '_monkeywpnonce' );
echo '
';
}
Trong đoạn code trên:
- Mình dùng hàm get_post_meta() để lấy các giá trị meta field có sẵn và hiển thị chúng.
- Hàm wp_nonce_field() dùng để tăng cường bảo mật. Khi chúng ta lưu dữ liệu Meta Box, chúng ta có thể check giá trị nonce để đảm bảo request đến từ đúng nơi.
- Hàm selected() được tích hợp sẵn trong WordPress giúp đơn giản hóa các điều kiện và hiển thị selected=”selected” trong field <select>.
Và đây là kết quả:
Bước 3. Lưu dữ liệu Meta Box
Nếu bạn sử dụng Meta Box này trên màn hình chỉnh sửa trang hoặc custom post type, đừng quên xác định post type ở dòng thứ 23, nếu không dữ liệu Meta Box sẽ không được lưu.
Hàm update_post_meta() và delete_post_meta() (dòng 27-36) được gọi cho từng input field của Meta Box.
add_action( 'save_post', 'monkeywp_save_meta', 10, 2 );
// hoặc add_action( 'save_post_{post_type}', 'monkeywp_save_meta', 10, 2 );
function monkeywp_save_meta( $post_id, $post ) {
// nonce check
if ( ! isset( $_POST[ '_monkeywpnonce' ] ) || ! wp_verify_nonce( $_POST[ '_monkeywpnonce' ], 'somerandomstr' ) ) {
return $post_id;
}
// kiểm tra quyền của user
$post_type = get_post_type_object( $post->post_type );
if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) {
return $post_id;
}
// Không lưu dữ liệu bằng autosave
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
return $post_id;
}
// xác định post type ở đây
if( 'page' !== $post->post_type ) {
return $post_id;
}
if( isset( $_POST[ 'seo_title' ] ) ) {
update_post_meta( $post_id, 'seo_title', sanitize_text_field( $_POST[ 'seo_title' ] ) );
} else {
delete_post_meta( $post_id, 'seo_title' );
}
if( isset( $_POST[ 'seo_robots' ] ) ) {
update_post_meta( $post_id, 'seo_robots', sanitize_text_field( $_POST[ 'seo_robots' ] ) );
} else {
delete_post_meta( $post_id, 'seo_robots' );
}
return $post_id;
}
Chú ý rằng các field của bạn bắt buộc phải sanitization. Trong ví dụ ở trên mình sử dụng hàm sanitize_text_field(), nhưng cũng có thể dùng 1 số hàm khác như sanitize_textarea() cho textarea field, sanitize_emai(), v.v…
Ngoài ra, cũng không cần thiết sử dụng hàm delete_post_meta() cho 1 số trường hợp, ví dụ như text field thông thường. Nhưng hàm isset() và empty() vẫn nên sử dụng để tránh trường hợp php báo lỗi nếu field trống.
Nếu có thắc mắc gì thì bạn có thể nhắn tin Facebook Monkey WordPress hoặc email tới lienhe@monkeywp.dev nha :D.