LẬP TRÌNH PLUGIN
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

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.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

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 postspostmeta thôi bởi vì đa số chúng ta sử dụng nó thường xuyên.

eav design wordpress png

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. 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.

meta boxes wordpress png

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, advancedside.
  • $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é.

meta boxes wordpress 5 png

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:

meta boxes wordpress 2 png

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:

meta boxes wordpress 3 png

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:

meta boxes wordpress 4 png

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_metaget_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.

Cùng chuyên mục:

Child theme là gì? Cách tạo Child theme trong WordPress

Child theme là gì? Cách tạo Child theme trong WordPress

Cách tạo Shortcodes trong WordPress từ A-Z

Cách tạo Shortcodes trong WordPress từ A-Z

Cách sửa lỗi SSL trong WordPress và cài đặt

Cách sửa lỗi SSL trong WordPress và cài đặt

Sử dụng  CSS & JavaScript trong Wordpress

Sử dụng CSS & JavaScript trong Wordpress

Cách tạo và sử dụng các template file trong theme Wordpress

Cách tạo và sử dụng các template file trong theme Wordpress

Cách tạo Widget trong Theme WordPress

Cách tạo Widget trong Theme WordPress

Theme trong WordPress là gì? Cách cài đặt Theme trong WordPress

Theme trong WordPress là gì? Cách cài đặt Theme trong WordPress

Cách tạo Theme WordPress từ Scratch từ A-Z

Cách tạo Theme WordPress từ Scratch từ A-Z

Bài 06: Tạo trang quản lý Options trong WordPress

Bài 06: Tạo trang quản lý Options trong WordPress

Ở bài trước mình có nêu ra một ví dụ về quản lý thông tin…

Bài 05: Options API trong WordPress: add_option / get_option ...

Bài 05: Options API trong WordPress: add_option / get_option ...

Trong database của WordPress bạn sẽ thấy một table ten là [prefix]_options, table này sẽ…

Bài 04: Tìm hiểu Hooks , Action và Filter trong WordPress

Bài 04: Tìm hiểu Hooks , Action và Filter trong WordPress

Bạn đã từng nghe khái niệm lập trình hướng sự kiện trong các Framework như…

Bài 02: WordPress API là gì? Danh sách API trong WordPress

Bài 02: WordPress API là gì? Danh sách API trong WordPress

Đáng lẽ mình không viết bài này nhưng lúc đang viết bài tiếp theo thì…

Bài 01: WordPress là gì? Nên làm website bằng WordPress?

Bài 01: WordPress là gì? Nên làm website bằng WordPress?

WordPress là một CMS được phát triển trên ngôn ngữ lập trình PHP ...

Bài 12: Custom Taxonomy  trong WordPress

Bài 12: Custom Taxonomy trong WordPress

Bài trước mình đã hướng dẫn bạn tạo một thể loại bài viết mới bằng…

Bài 11: Tạo Custom Post Type trong WordPress

Bài 11: Tạo Custom Post Type trong WordPress

Đây là các thể loại mặc định có sẵn sau khi bạn cài đặt WordPress.…

Bài 10: Hiển thị metadata ngoài frontend

Bài 10: Hiển thị metadata ngoài frontend

Sẵn có bạn hỏi làm thế nào để hiển thị nội dung bài viết ra…

Bài 09: Bốn bước custom Meta Boxes trong WordPress

Bài 09: Bốn bước custom Meta Boxes trong WordPress

Tới bài thứ chín này thì khái niệm Custom Meta Boxes không còn xa lạ…

Bài 08: Metadata API trong WordPress

Bài 08: Metadata API trong WordPress

WordPress sử dụng mô hình EAV nhằm giúp lập trình viên có thể tùy biến…

Bài 06: Tạo menu trong Admin WordPress

Bài 06: Tạo menu trong Admin WordPress

Ở bài tạo trang quản lý Options mình đã hướng dẫn các bạn thêm một…

Bài 03: Các bước tạo plugin trong WordPress (căn bản)

Bài 03: Các bước tạo plugin trong WordPress (căn bản)

Như ta biết WordPress là một CMS mã nguồn mở giúp quản lý nội dung…

Top