Hướng dẫn tạo Meta Box trong WordPress

Hướng dẫn tạo Meta Box trong WordPress

Meta box là một trong những thành phần hỗ trợ rất tốt việc thêm dữ liệu trong các loại post của WordPres. Thông thường bạn có thể sử dụng custom fields để có thể thêm một số thông tin bổ sung, nhưng nhược điểm của custom fields là nó không nhất quán và tạo ra nhiều trường với id khó kiểm soát cho việc hiển thị ngoài theme. Meta box sẽ khắc phục nhược điểm đó. Bạn có thể bắt gặp meta box trong phần thêm sản phẩm của woocomerce, đó là một dạng meta box, nhưng hôm nay mình sẽ hướng dẫn để tạo ra một meta box đơn giản nhất.

Meta Box trong WordPress

Meta box là một dạng custome thường được các plugin sử dụng để bổ sung cho các loại post, Các meta box sẽ sử dụng dữ liệu meta để lưu trữ giá trị. Các dữ liệu data được meta box sử dụng bao gồm: wp_postmetawp_commentmeta và wp_usermeta.

Trong bài viết này mình sẽ tạo meta box cho một custom post type mà mình đã làm ở bài Hướng dẫn tạo Custom Post Type trong WordPress Bạn có thể xem lại bài viết để hiểu rõ về cách tạo một custom post type.

Cách tạo meta box trong WordPress

Tạo meta box

WordPress đưa ra một hàm để hỗ trợ việc thêm meta box đó là add_meta_box();

Cấu trúc hàm như sau: add_meta_box( $id, $title, $callback, $screen, $context, $priority, $callback_args );

Trong đó:

  • $id: Id của hộp.
  • $title: tiêu đề hiển thị của hộp.
  • $callback: hàm hiển thị form.
  • $screen: slug post type, như post, page, dashboard, custom post type.
  • $context: kiểu hiển thị  như normal, advanced hoặc side.
  • $priority: thứ tự ưu tiên như high, core, default hoặc low.
  • $callback_args: mảng các tham số trả về hàm trong $callback.

add_meta_box() là một lời gọi hàm không thể thực thi ở ngoài hàm, vì thế bạn cần tạo một hàm và nhét nó vào. Ví dụ như:

function services_meta_box(){ 
     add_meta_box( 'cost-services', 'Giá dịch vụ', 'form_gia_dich_vu', 'dich-vu' );
}

Bạn thêm hàm này ở file funtions.php của theme nhé. Meta box này mình không cần thêm nhiều tham số, chỉ một vài tham số quan trong như:

  • cost-services: id của meta box này. Lưu ý không để trùng nhé.
  • Giá dịch vụ: Tên của meta box này, nó sẽ hiển thị ở trên khung.
  • form_gia_dich_vu: đây là tên hàm tí nữa mình sẽ tạo để chèn form nhập liệu vào.
  • dich-vu: đâu là slug của custom post type mà mình đã tạo lúc trước.

Bây giờ bạn chỉ mới xong bước tạo meta box chứ chưa thể lôi nó lên post được, bạn cần móc cái hàm vừa tạo vào một hook action có tên add_meta_boxes như sau:

add_action( 'add_meta_boxes', 'cost-services' );

Như vậy là đã xong, bạn có thể vào chỗ custom post type và thấy meta box vừa tạo xuất hiện. Tuy nhiên sẽ có một số lỗi như thế này:

Lỗi này là do mình chưa có tạo hàm chứa form cho callback, bây giờ tạo nhé.

Tạo form nhập liệu cho meta box

Trong hàm này mình chỉ tạo ra một form bằng cách echo ra các control html. Lưu ý là mình cần tạo ra một biến và dùng get_post_meta để lấy lên giá trị đã lưu để show lên lại control nhé. Code cụ thể như sau.

function form_gia_dich_vu($post){ 
   $cost_services = get_post_meta( $post->ID, '_cost_services', true );    
   echo ( '<label for="cost_services">Giá dịch vụ: </label>' ); 
   echo ('<input type="text" id="cost_services" name="cost_services" value="'.esc_attr( $cost_services ).'" />');
}

Bạn phải lưu ý các thông tin trong control như thuộc tính name nhé, vì đây sẽ là tường được lưu vào csdl. Bây giờ đã có form, bạn cần làm một số bước nữa để lưu dữ liệu cần thiết.

Lưu dữ liệu meta box vào theme

Để lưu dữ liệu bạn cần tạo ra một hàm với thông số ID post.

function gia_dich_vu_save( $post_id )
{
   $cost_services = sanitize_text_field( $_POST['cost_services'] );
   update_post_meta( $post_id, '_cost_services', $cost_services );
}
add_action( 'save_post', 'gia_dich_vu_save' );

Hàm trên rất dễ hiểu, chỉ có một hàm đó là sanitize_text_field(), đây là hàm do wp tạo ra để bảo vệ dữ liệu được truyền đến CSDL tránh gây ra các lỗi, đặc biệt là không tạo ra lỗ hổng bảo mật.

Tiếp theo là sử dụng hàm update_post_meta() để cập nhật giá trị từ biến $cost_services vào trường _cost_services trong csdl cho bài viết có id là $post_id.

Việc cuối cùng là thêm một hook action tên save_post và truyền hàm trên vào để thực thi.

Hoàn thành một meta box giá cho dịch vụ

Hoàn thành một meta box giá cho dịch vụ

Hiển thị dữ liệu meta box lên theme trong WordPress

Đã có dữ liệu của meta box, bây giờ chỉ việc hiển thị dữ liệu này trong theme. Tương tự như các dữ liệu meta bình thường khác, để hiển thị dữ liệu này bạn cũng chỉ cần sử dụng hàm get_post_meta($id_post, $slug_meta, true). Ví dụ bạn cần lấy dữ liệu trong post dịch vụ thì cần hiển thì code như sau:

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

Bảo mật khi truyền dữ liệu meta box

Trong bài Tấn công website bằng kỹ thuật CSRF và cách phòng chống mình đã nói về một kiểu tấn công thông qua việc đánh lừa người dùng. Và một cách để chống lại kỹ thuật này là xác thực. Trong WordPress cung cấp một cách thức để làm việc này.

Bâu giờ bạn quay lại hàm form_gia_dich_vu() và thêm một đoạn sau vào dưới biến $cost_services

wp_nonce_field( 'save_cost_services', 'cost_services_nonce' );

sau đó vào hàm gia_dich_vu_save() và thêm đoạn này vào trên cùng

  $cost_services_nonce = $_POST['cost_services_nonce'];
  // nếu nonce chưa được gán giá trị
  if( !isset( $cost_services_nonce ) ) {
     return;
  }
  // nếu giá trị nonce không trùng khớp
  if( !wp_verify_nonce( $cost_services_nonce, 'save_cost_services' ) ) {
     return;
  }

Như vậy là bạn có thể tránh được một lỗ hổng tấn công rồi đấy. Code đầy đủ như sau:

function services_meta_box()function services_meta_box(){ add_meta_box( 'cost-services', 'Thông tin dịch vụ', 'form_gia_dich_vu', 'dich-vu' );}add_action( 'add_meta_boxes', 'services_meta_box' );
function form_gia_dich_vu($post){ $cost_services = get_post_meta( $post->ID, '_cost_services', true ); wp_nonce_field( 'save_cost_services', 'cost_services_nonce' );    echo ( '<label for="cost_services">Giá dịch vụ: </label>' ); echo ('<input type="text" id="cost_services" name="cost_services" value="'.esc_attr( $cost_services ).'" />');}
function gia_dich_vu_save( $post_id ){ $cost_services_nonce = $_POST['cost_services_nonce']; // nếu nonce chưa được gán giá trị if( !isset( $cost_services_nonce ) ) { return; } // nếu giá trị nonce không trùng khớp if( !wp_verify_nonce( $cost_services_nonce, 'save_cost_services' ) ) { return; } $cost_services = sanitize_text_field( $_POST['cost_services'] ); update_post_meta( $post_id, '_cost_services', $cost_services );}add_action( 'save_post', 'gia_dich_vu_save' );

Chúc bạn thành công!

Đoàn Tuấn

Tác giả: ĐOÀN CÔNG TUẤN

Với niềm đam mê về khoa học công nghệ thông tin, đặc biệt là lập trình. Tôi đã thành lập blog Tuandc.com để lưu trữ và chia sẻ những kiến thức thực tế có được trong quá trình làm việc. Với kinh nghiệm gần 10 năm làm việc trong lĩnh vực, những kiến thức tôi chia sẻ hy vọng sẽ giúp được phần nào đó.