Bài 07: Custom Meta Boxes trong WordPress
Trong bài này chúng ta sẽ tìm hiểu cách custom Meta Box trong WordPress, đây là cách bổ sung một field nào đó vào trong các loại post / page của WordPress.
WordPress là một CMS nên hệ thống dữ liệu của nó chỉ dừng lại ở một mức độ nào đó, nghĩa là bạn không thể thêm bớt các field một cách tự tiện được vì điều này sẽ làm cho hệ thống cấu trúc của nó bị phá vỡ.
Tuy nhiên vấn đề này đã được khắc phục bởi WordPress sử dụng mô hình EAV (Entity-Attribute-Value), đây là mô hình cho phép bạn thêm một field bất kì bởi mối quan hệ (1 - n) giữa các table.
Trước tiên chúng ta tìm hiểu mô hình này đã nhé :)
Bài viết này được đăng tại [free tuts .net]
1. Mô hình EAV trong WordPress
EAV là chữ viết tắt của Entity-Attribute-Value, đây là mô hình cho phép mỗi table có thể tạo ra nhiều trường lưu trữ khác nhau. Mô hình này thường áp dụng với những CMS hoặc lưu trữ cho những hệ thống đa ngôn ngữ.
Trong WordPress có nhiều table áp dụng mô hình này, tuy nhiên mình chỉ đưa ra 2 table posts và postmeta thôi bởi vì đa số chúng ta sử dụng nó thường xuyên.
Với cấu trúc này thì table postmeta
đóng vai trò lưu trữ các thuộc tính cho table posts
, vì vậy nó có một khóa ngoại là post_id
. Nói là khóa ngoại nhưng thực chất khi bạn cài đặt WordPress thì nó sẽ không thiết lập các tham chiếu, vì vậy ta có thể coi đây là 2 bảng tách biệt không có mối quan hệ khóa ngoại (vẫn join được nhé các bạn).
Với mỗi bài viết bạn có thể thêm rất nhiều key cho nó và được lưu trữ trong bảng postmeta
, field meta_key
sẽ là tên của key và meta_value
sẽ là giá trị của key. Ví dụ bạn cần luu trữ link_download
và link_demo
cho bài viết có id = 12 thì cách lưu trữ như sau:
ID | post_id | meta_key | meta_value |
---|---|---|---|
# - auto increment | 12 | link_download | https://freetuts.net/download.php |
# - auto increment | 12 | link_demo | https://freetuts.net/demo.php |
Lúc này muốn lấy danh sách key của bài viết có id = 12 thì quá đơn giản phải không nào :)
2. Meta Boxes là gì?
Khi bạn đăng nhập vào admin và bạn edit một bài viết nào đó thì các khối trong giao diện ta gọi là các Meta Boxes. Vậy Meta Boxes là các khối hiển thị dữ liệu cho phép người dùng chỉnh sửa và lưu lại trong trang quản lý bài viết của WordPress.
Các vị trí mà mình kẻ ô màu đỏ chính là các Meta Boxes. Vậy mỗi Meta Box sẽ có những đặc điểm như thế nào? Làm sao để có thể phân biệt các Meta Boxes? Để trả lời câu hỏi này thì chúng ta tiếp tục tìm hiểu nhé.
3. Hàm add_meta_box trong WordPress
Hàm add_meta_box()
dùng để thêm một Meta Box vào trong giao diện admin của WordPress, hàm này có cú pháp như sau:
add_meta_box($id, $title, $callback, $screen, $context, $priority, $callback_args);
Trong đó:
$id
: Là ID của meta box, ID này phải là duy nhất không trùng với các Meta Boxes khác, kể cả các Meta Boxes mặc định của WordPress.$title
: Tiêu đề của Meta Box$callback
: Hàm callback dùng để hiển thị mã HTML nằm bên trong Meta Box$screen
: Hay còn gọi là page. Đối tượng mà Meta Box sẽ hiển thị, có thể là Page, Post hoặc là một custom post type.$context
: Vị trí mà Meta Box sẽ hiển thị bên trên giao diện. Chúng ta có ba vị trí đó là normal, advanced và side.$priority
: Mức độ ưu tiên của Meta box, có bốn giá trị là default, core, high, và low.$callback_args
: Một mảng các tham số truyền vào Meta Box
Lưu ý: Action Hook của Meta Box có tên là
add_meta_boxes
.
Ví dụ: Thêm một Meta Box có tên là Thể Loại vào Post
Như thường lệ bạn tạo một file tên là my-meta-boxes.php
nằm trong thư mục include
và đừng quên require
nó ở file wp-learn.php
nhé. Nếu bạn chưa biết cấu trúc thì hãy xem lại bài tìm hiểu plugin là gì nhé.
Tiếp theo bạn hãy nhập nội dung sau vao file vừa tạo trên.
function add_metabox() { add_meta_box('the-loai', 'Thể Loại', 'show_metabox_contain', 'post', 'advanced', 'high', array(1, 2, 3)); } function show_metabox_contain($post, $metabox) { echo "Nội dung của metabox"; } add_action('add_meta_boxes', 'add_metabox');
Bạn vào admin edit một bài post bất kì thì sẽ thấy một ô với giao diện như sau:
Bây giờ ta sẽ tìm hiểu chi tiết hơn nữa nhé.
Tham số truyền vào hàm callback
Như ở ví dụ trên thì trong hàm callback mặc định sẽ có hai tham số truyền vào, tham số đầu tiên là $post
và đây chính là một đối tượng lưu trữ thông tin của bài viết hiện tại. Tham số thứ hai là $metabox
lưu trữ thông tin của metabox như $id
, $title
và các $callback_args
.
Bây giờ bạn sửa lại hàm show_metabox_contain()
như sau:
function show_metabox_contain($post, $metabox) { var_dump($post); var_dump($metabox); }
Chạy lên bạn sẽ thấy giao diện như sau:
Bạn để ý phần in giá trị của $metabox
sẽ có một key là args
, đây chính là giá trị các tham số truyền vào lúc add_meta_box
.
$context và $priority
Đây là hai giá trị mà có lẽ bạn thắc mắc nhất phải không nào :) Thực ra nó không có gì to tác cả mà chỉ là vị trí hiển thị của meta box trong giao diện thôi.
$context
là vị trí hiển thị, chúng ta có hai vị trí chính đó là bên sidebar và main contain.$priority
là độ ưu tiên hiển thị, bạn hãy tự mình thay đổi các giá trị để xem kết quả nhé.
4. Căn bản về Meta data
Vấn đề về xử lý meta data rất nhiều và mình sẽ dành nó ở một bài nâng cao, vì vậy trong phần này mình sẽ hướng dẫn các bạn cách sử dụng căn bản thôi nhé.
Trước khi đọc phần 4 này thì bạn hãy xem kỹ phần 1 nhé vì ở đó mình có giới thiệu cách lưu trữ của bảng postmeta
.
Hiển thị giao diện
Giả sử trong phần Meta box thể loại mình sẽ có 3 loại đó là video, text hoặc image, lúc này trong hàm hiển thị nội dung meta box ta sẽ show nó ra ở dạng select để người dùng chọn. Bạn sửa lại hàm show_metabox_contain
như sau:
function show_metabox_contain($post, $metabox) { // Input hidden bảo mật wp_nonce_field(basename(__FILE__), "meta-box-the-loai-nonce"); ?> <select name="meta-box-the-loai"> <?php // Danh sách thể loại $option_values = array('Video', 'Image', "Text"); // Lấy thông tin trong database $the_loai = get_post_meta($post->ID, "meta-box-the-loai", true); // Lặp qua các thể loại và thiết lập selected foreach($option_values as $key => $value) { if($value == $the_loai) { ?> <option selected value="<?php echo $value; ?>"><?php echo $value; ?></option> <?php } else { ?> <option value="<?php echo $value; ?>"><?php echo $value; ?></option> <?php } } ?> </select> <?php }
Chạy lên bạn sẽ thấy giao diện như sau:
Mình sẽ giải thích nội dung của hàm này một chút.
Đoạn code dưới đây ta có thể ví nó như là một input hidden dùng để xử lý vấn đề bảo mật, nó sẽ sinh ra một ô input hidden bạn có thể dùng firebug để xem.
wp_nonce_field(basename(__FILE__), "meta-box-the-loai-nonce");
Đoạn code dưới đây sẽ lấy thông tin trong bảng postmeta
, tham số truyền vào là ID và KEY cần lấy, giá trị true sẽ nói cho WordPress biết là sẽ trả về giá trị đơn thay vì trả về một mảng (đỡ mất công phải xử lý mảng để lấy giá trị).
$the_loai == get_post_meta($post->ID, "meta-box-the-loai", true);
Các đoạn code còn lại thì quá đơn giản rồi :)
Xử lý lưu dữ liệu
Trên là vấn đề hiển thị giao diện, tiếp theo chúng ta cần phải xử lý lưu lại thông tin. Để lưu trữ thông tin thì ta sẽ phải sử dụng một Hook Action tên là save_post
, action này sẽ xảy ra khi người dùng click save bài viết. Bây giờ bạn bổ sung một đoạn code sau vào phía bên dưới của file my-meta-boxes.php
.
function save_metabox_data($post_id, $post, $update) { // Đây chính là input hidden Security mà ta đã tạo ở hàm show_metabox_contain if (!isset($_POST["meta-box-the-loai"]) || !wp_verify_nonce($_POST["meta-box-the-loai-nonce"], basename(__FILE__))) { return $post_id; } // Kiểm tra quyền if(!current_user_can("edit_post", $post_id)) { return $post_id; } // Nếu auto save thì không làm gì cả if(defined("DOING_AUTOSAVE") && DOING_AUTOSAVE) { return $post_id; } // Vì metabox này dành cho Post nên phải kiểm tra có đúng vậy không? if('post' != $post->post_type){ return $post_id; } // Lấy thông tin từ client $metabox_the_loai = (isset($_POST["meta-box-the-loai"])) ? $_POST["meta-box-the-loai"] : ''; // Cập nhật thông tin, hàm này sẽ tạo mới nếu như trong db chưa tồn tại update_post_meta($post_id, "meta-box-the-loai", $metabox_the_loai); } add_action('save_post', 'save_metabox_data', 10, 3);
Trong code mình có giải thích rồi nên mình không giải thích lại nữa.
Và đây chính là toàn bộ nội dung của file my-meta-boxes.php
.
/*PHẦN HIỂN THỊ BOX META*/ function add_metabox() { add_meta_box('the-loai', 'Thể Loại', 'show_metabox_contain', 'post', 'advanced', 'high', array(1, 2, 3)); } function show_metabox_contain($post, $metabox) { // Input hidden bảo mật wp_nonce_field(basename(__FILE__), "meta-box-the-loai-nonce"); ?> <select name="meta-box-the-loai"> <?php // Danh sách thể loại $option_values = array('Video', 'Image', "Text"); // Lấy thông tin trong database $the_loai = get_post_meta($post->ID, "meta-box-the-loai", true); // Lặp qua các thể loại và thiết lập selected foreach($option_values as $key => $value) { if($value == $the_loai) { ?> <option selected value="<?php echo $value; ?>"><?php echo $value; ?></option> <?php } else { ?> <option value="<?php echo $value; ?>"><?php echo $value; ?></option> <?php } } ?> </select> <?php } add_action('add_meta_boxes', 'add_metabox'); /*PHẦN XỬ LÝ LƯU TRỮ TRONG CSDL*/ function save_metabox_data($post_id, $post, $update) { // Đây chính là input hidden Security mà ta đã tạo ở hàm show_metabox_contain if (!isset($_POST["meta-box-the-loai"]) || !wp_verify_nonce($_POST["meta-box-the-loai-nonce"], basename(__FILE__))) { return $post_id; } // Kiểm tra quyền if(!current_user_can("edit_post", $post_id)) { return $post_id; } // Nếu auto save thì không làm gì cả if(defined("DOING_AUTOSAVE") && DOING_AUTOSAVE) { return $post_id; } // Vì metabox này dành cho Post nên phải kiểm tra có đúng vậy không? if('post' != $post->post_type){ return $post_id; } // Lấy thông tin từ client $metabox_the_loai = (isset($_POST["meta-box-the-loai"])) ? $_POST["meta-box-the-loai"] : ''; // Cập nhật thông tin, hàm này sẽ tạo mới nếu như trong db chưa tồn tại update_post_meta($post_id, "meta-box-the-loai", $metabox_the_loai); } add_action('save_post', 'save_metabox_data', 10, 3);
Hãy chạy lên và thử lưu lại xem kết quả có đúng không nhé :) Nếu sai thì tức là bạn đã thực hiện các thao tác bị lỗi rồi đấy.
5. Lời kết
Như vậy mình đã giới thiệu toàn bộ kiến thức về Meta Boxes và cách tạo Meta Box trong WordPress. Bên cạnh đó mình có giới thiệu sơ lược về cách sử dụng metadata, đặc biệt là hai hàm update_post_meta
và get_post_meta
. Bài tiếp theo chúng ta sẽ tìm hiểu rõ hơn về cách sử dụng Metadata.