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é 🙂

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
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_downloadlink_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. WordPress 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
    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_metaBài tiếp theo
chúng ta sẽ tìm hiểu rõ hơn về cách sử dụng Metadata.

Nguồn: freetuts.net

Leave a Reply

Your email address will not be published. Required fields are marked *