Cách tự tạo một Meta Box đơn giản toàn tập




data vpn
Bài này thuộc phần 9 của 10 phần trong serie WordPress nâng cao

WordPress có tính năng Custom Field giúp người dùng dễ dàng thêm các dữ liệu thêm vào một post type nào đó. Nhưng khi sử dụng Custom Field, chúng ta hầu như chỉ có thể làm bằng một thao tác là chọn tên khoá (key) rồi điền giá trị, như vậy rất bất tiện.

Ở đây chắc ai cũng biết qua plugin SEO by Yoast phải không? Các dữ liệu liên quan tới SEO của plugn này được người dùng khai báo thông qua cái khung như dưới này.

seowp-yoastnoindex

Các dữ liệu đó cũng là custom field trong WordPress nhưng nó sẽ giúp người dùng dễ dàng khai báo thông tin thuận tiện hơn. Và những cái khung này, người ta gọi là Meta Box.

Nếu bạn không thích code thì plugin Advanced Custom Field sẽ giúp bạn tạo ra các meta box dễ dàng.

Meta Box là gì?

Meta Box nghĩa là một cái hộp nhập liệu được tích hợp trong khu vực soạn thảo nội dung, và các dữ liệu sẽ được gửi vào trong cơ sở dữ liệu của website. Nhưng hiện nay, Meta Box đa phần được ứng dụng để làm việc với Meta Data (gồm wp_usermeta, wp_commentmetawp_postmeta).

Trong bài viết này, mình sẽ hướng dẫn bạn cách tự tạo meta box để xử lý post meta data (dữ liệu của custom field). Đại loại là thêm hoặc sửa giá trị trong một custom field nào đó.

Nên xem trước:

Các bước tạo meta box

Chuẩn bị – Tạo plugin mới

Để thực hành trong bài này, tốt hơn bạn nên tự tạo ra một plugin mới bằng cách tạo một file demo-metabox.php trong thư mục /wp-content/plugins/, sau đó khai báo thông tin plugin.

  <?php /* Plugin Name: Ví dụ Meta Box Author: Thạch Phạm Description: Hướng dẫn tạo meta box Author URI: https://onet.vn */

Và nhớ là kích hoạt plugin này lên.

Bước 1. Khai báo meta box

Bước này chúng ta sẽ tạo ra một cái khung meta box trong khu vực soạn thảo trước. Để tạo một khung meta box, chúng ta sẽ sử dụng hàm add_meta_box() trong WordPress với cấu trúc như sau:

add_meta_box( $id, $title, $callback, $screen, $context, $priority, $callback_args );

Trong đó:

  • $id: Tên ID của cái khung.
  • $title: Tiêu đề hiển thị của khung meta box.
  • $callback: Hàm hiển thị các form bằng HTML để nó làm việc với dữ liệu.
  • $screen: Tên post type mà meta box này sẽ được hiển thị, nó có các giá trị là post, page, dashboard, link, attachment hoặc tên custom post type (lưu ý là tên được viết dưới dạng slug).
  • $context: Kiểu hiển thị meta box, gồm normal, advanced hoặc side.
  • $priority: Thứ tự ưu tiên hiển thị, bao gồm high, core, default hoặc low.
  • $callback_args: Các tham số mà bạn muốn trả về hàm callback.

Tuy nhiên khi làm việc, chúng ta có thể sẽ không cần sử dụng hết các tham số trong hàm này mà chỉ sử dụng các tham số quan trọng (5 tham số đầu tiên hoặc ít hơn).

Các bạn phải lưu ý là hàm add_meta_box() không thể gọi riêng lẻ mà bạn cần phải đặt nó vào một hàm nào đó của riêng bạn, sau đó móc vào action hookadd_meta_boxes để thực thi.

Ví dụ ở bài này, mình sẽ tạo ra một cái khung meta box với tên Liên hệ như sau:

 /**  Khai báo meta box **/
 function onetidc_meta_box() {
  add_meta_box( 'thong-tin', 'Thông tin ứng dụng', 'onetidc_thongtin_output', 'post' );
}
 add_action( 'add_meta_boxes', 'onetidc_meta_box' );

Trong đó,

  • thong-tin: là $id.
  • Thông tin ứng dụng: là $title.
  • onetidc_thongtin_output: là $callback.
  • post: là $screen.

Bây giờ bạn hãy vào khu vực Post và thêm/sửa một post sẽ thấy cái meta box của mình.

Hiển thị meta box với hàm add_meta_box

Hiển thị meta box với hàm add_meta_box

Nếu bạn thấy cái lỗi call_user_func() thì nghĩa là chúng ta chưa viết cái hàm callback nên nó thấy thiếu, chúng ta sẽ làm ngay đây.

Bước 2. Thiết lập callback

Callback nghĩa là một hàm mà nó sẽ in ra nội dung bên trong cái box đó, mình lấy ví dụ đơn giản thế này để hiển thị một đoạn chữ nhé.

 function onetidc_thongtin_output() {
 	echo 'Đây là thông tin trong meta box';
}

Dĩ nhiên kết quả bây giờ sẽ là như thế này.

metabox-callb ack-simple

Nhưng mà ví dụ trong bài này, mình sẽ tạo ra hai cái thẻ <input> bên trong đó để người ta nhập liệu, ví dụ mình muốn tạo ra một trường nhập liệu để nhập Link Download (sử dụng custom field) thì mình sẽ viết lại như sau:

 /**  Khai báo callback  @param $post là đối tượng WP_Post để nhận thông tin của post **/
 function onetidc_thongtin_output( $post ) {
  // Tạo trường Link Download  echo ( '<label for="link_download">Link Download: </label>' );
echo ('<input type="text" id="link_download" name="link_download" value="'.esc_attr( $link_download ).'" />');
}

Kết quả ta có:

metabox-callback-demo

Ở đoạn trên là các nội dung HTML để tạo ra một form mà thôi, nhưng các bạn lưu ý cho mình là ở cái biến $link_download ở trên nó là cái biến mà chúng ta sẽ hiển thị nội dung mà người dùng đã nhập vào để nó hiển thị ra nếu nó đã được khai báo.

Nhưng vấn đề là nếu bây giờ bạn thử điền giá trị vào rồi cập nhật lại bài viết nó sẽ không được lưu, đơn giản là chúng ta chưa thiết lập cho nó lưu dữ liệu nhập vào.

Nhưng mà trước khi lưu dữ liệu vào, chúng ta viết thêm đoạn này vào hàm onetidc_thongtin_output để khai báo cho hệ thống hiểu $link_download là cái biến gì vì ta chưa tạo ra cho nó.

 /**  Khai báo callback  @param $post là đối tượng WP_Post để nhận thông tin của post **/
 function onetidc_thongtin_output( $post ) {
  $link_download = get_post_meta( $post->ID, '_link_download', true );
// Tạo trường Link Download  echo ( '<label for="link_download">Link Download: </label>' );
echo ('<input type="text" id="link_download" name="link_download" value="'.esc_attr( $link_download ).'" />');
}

Trong đó, hàm get_post_meta mình đã giải thích tại bài hướng dẫn custom field rồi đấy.

Bước 3. Thiết lập lưu dữ liệu nhập vào meta box

Chúng ta đã có meta box, đã có một trường nhập dữ liệu và trường đó sẽ in dữ liệu ra trên khung nhập liệu nếu nó có giá trị. Nhưng vấn đề là bây giờ nó chưa có được lưu vào cơ sở dữ liệu khi nhập vào nên chúng ta phải tạo ra một hàm riêng để xử lý việc này, và hàm này chúng ta sẽ móc vào action hook save_post để thực thi khi lưu dữ liệu post type.

 /**  Lưu dữ liệu meta box khi nhập vào  @param post_id là ID của post hiện tại **/
 function onetidc_thongtin_save( $post_id ) {
  $link_download = sanitize_text_field( $_POST['link_download'] );
update_post_meta( $post_id, '_link_download', $link_download );
}
 add_action( 'save_post', 'onetidc_thongtin_save' );

Hàm này rất đơn giản, trước hết là nó sẽ làm sạch các dữ liệu được nhập vào cái trường link_download ($_POST['link_download'] là nó lấy dữ liệu gửi đi từ trường dựa vào thuộc tínhname trong thẻ <input> của nó). Làm sạch ở đây nghĩa là nó sẽ loại bỏ các ký tự đặc biệt như <, ; để tránh gây lỗi phát sinh và cũng hạn chế SQL Injection & XSS.

Sau đó, hàm update_post_meta sẽ tiến hành lưu lại các dữ liệu ở biến $link_download ở trên vào custom field tên là _link_download. Nếu chưa có nó sẽ tạo mới.

Bây giờ bạn hãy thử vào nội dung và nhập dữ liệu vào rồi lưu lại, bạn sẽ thấy nó đã được lưu.

metabox-callback-demo02

Toàn bộ code phần này

 <?php /*  Plugin Name: Ví dụ Meta Box  Author: Thạch Phạm  Description: Hướng dẫn tạo meta box  Author URI: https://onet.vn */
  /**  Khai báo meta box **/
 function onetidc_meta_box() {
  add_meta_box( 'thong-tin', 'Thông tin ứng dụng', 'onetidc_thongtin_output', 'post' );
}
 add_action( 'add_meta_boxes', 'onetidc_meta_box' );
/**  Khai báo callback  @param $post là đối tượng WP_Post để nhận thông tin của post **/
 function onetidc_thongtin_output( $post ) {
  $link_download = get_post_meta( $post->ID, '_link_download', true );
// Tạo trường Link Download  echo ( '<label for="link_download">Link Download: </label>' );
echo ('<input type="text" id="link_download" name="link_download" value="'.esc_attr( $link_download ).'" />');
}
  /**  Lưu dữ liệu meta box khi nhập vào  @param post_id là ID của post hiện tại **/
 function onetidc_thongtin_save( $post_id ) {
  $link_download = sanitize_text_field( $_POST['link_download'] );
update_post_meta( $post_id, '_link_download', $link_download );
}
 add_action( 'save_post', 'onetidc_thongtin_save' );

Bước 4. Lấy dữ liệu ra ngoài template

Dĩ nhiên bạn đã có giá trị trong custom field rồi thì việc hiển thị ra ngoài template của theme chỉ là chuyện nhỏ, bạn cứ làm nó hiển thị với hàm get_post_meta như dưới đây để lấy giá trị của field _link_download.

get_post_meta( $post->ID, '_link_download', true );

Vấn đề bảo mật

Khi chúng ta làm việc với việc gửi và lưu dữ liệu từ form thì vấn đề bảo mật cực kỳ quan trọng và đáng để quan tâm, bởi khi lưu dữ liệu nó sẽ lưu vào cơ sở dữ liệu nên chúng ta phải tin chắc là các dữ liệu được lưu vào là an toàn, đáng tin cậy.

Ngoài việc escape các ký tự đặc biệt với hàm esc_attr và sanitize_text_field mà mình có dùng ở trong bài thì một việc khác nữa bạn cần nên sử dụng khi làm việc với meta box là sử dụng Nonce (Number used once).

Nonce ở đây bạn hãy hiểu nó sẽ sinh ra một chuỗi mã xác thực (với dạng số) vào mỗi lần mà chúng ta gửi dữ liệu vào form. Sau đó chúng ta có thể xác thực cái Nonce này xem nó có hợp lệ hay không, nếu có thì chúng ta sẽ cho nó xử lý việc lưu dữ liệu, còn nếu không phải thì nên cho nó out ra. Việc này sẽ giúp bạn chống được một vài kiểu tấn công thông dụng như XSS hay CSRF.

Bước 1. Tạo Nonce

Bây giờ hãy quay lại hàm callback là onetidc_thongtin_output của chúng ta, ở đây chúng ta sẽ tạo ra một nonce với hàm wp_nonce_field và gắn nó một cái tên và một cái hành động.

 function onetidc_thongtin_output( $post ) {
  $link_download = get_post_meta( $post->ID, '_link_download', true );
wp_nonce_field( 'save_thongtin', 'thongtin_nonce' );
// Tạo trường Link Download  echo ( '<label for="link_download">Link Download: </label>' );
echo ('<input type="text" id="link_download" name="link_download" value="'.esc_attr( $link_download ).'" />');
}

Trong đó,save_thongtin là tên hành động mà chúng ta sẽ sử dụng để kiểm tra sau này,thongtin_nonce là tên của nonce để lấy giá trị nonce.

Ngay sau khi thêm đoạn đó, bạn xem mã nguồn HTML của trang soạn thảo nội dung sẽ thấy nó tạo ra một trường ẩn với tên là thongtin_nonce và có giá trị là một dãy số, chúng ta sẽ sử dụng cái giá trị đó để kiểm tra khi lưu dữ liệu.

metabox-callback-demo03

Bây giờ, ở hàmonetidc_thongtin_save, chúng ta chỉ cần thêm hai điều kiện rẽ nhánh rằng sẽ không lưu dữ liệu nếu nonce chưa có giá trị và giá trị nonce không hợp lệ như dưới đây.

 function onetidc_thongtin_save( $post_id ) {

$thongtin_nonce = $_POST[‘thongtin_nonce’];
// Kiểm tra nếu nonce chưa được gán giá trị if( !isset( $thongtin_nonce ) ) {

return;
}
// Kiểm tra nếu giá trị nonce không trùng khớp if( !wp_verify_nonce( $thongtin_nonce, ‘save_thongtin’ ) ) {

return;
}

// Lưu dữ liệu nếu thoả điều kiện $link_download = sanitize_text_field( $_POST[‘link_download’] );
update_post_meta( $post_id, ‘_link_download’, $link_download );
}
add_action( ‘save_post’, ‘onetidc_thongtin_save’ );

Vậy là xong rồi đó. ?

Lời kết

Trong bài này, mình tạm thời dừng lại việc tạo một field nhập liệu đơn giản. Và khi nào có thời gian thêm, mình sẽ hướng dẫn bạn thêm cách tạo các loại field khác như radio button, dropdown list,…vì nó khá dài dòng.




data vpn

Leave your comment