Cách tạo nhóm metabox vô hạn trong WordPress

Cách tạo nhóm metabox vô hạn trong WordPress

Nhu cầu tùy biến trên website là vô hạn, có đôi lúc tưởng như WordPress đã chạm đến giới hạn nhưng thật sự là không, WordPress cho đến hiện tại vẫn đủ sức để làm rất nhiều thứ, kể cả môt hệ thống thông tin dành cho một doanh nghiệp cỡ tầm trung. Trong bài viết này mình sẽ chia sẻ với bạn một phương pháp tùy biến metabox mới mà rất nhiều plugin lớn sử dụng phương pháp đã này, đó là cách tạo nhóm metabox vô hạn trong WordPress.

Bài viết này nói về meta box, nhưng là một phương pháp áp dụng mở rộng.

Thiết lập các hàm tạo

Trước khi viết code mình sẽ tạo ra các hàm, đây là một thói quen của mình, và cũng là cách mà mình giúp bạn hiểu một cách rõ ràng hơn. Trong phần này mình sẽ tạo ra 3 hàm (tương tự như tạo metabox) đó là hàm tạo metabox, hàm tạo các ô nhập liệu, và hàm lưu dữ liệu. Các hàm lần lượt như sau:

function add_moremtb_meta() {
   add_meta_box(
              'moremtb-details',
              'Thông tin mở rộng',
              'moremtb_details_init',
              'post');
}

function moremtb_details_init() {
}

function moremtb_meta_save( $post_id ) {
}

Trong cách tạo metabox bạn đã biết để tạo hai metabox bạn cần móc hai hàm tạo metabox và hàm lưu dữ liệu vào hai hook acction là add_meta_boxes và save_post. Và như vậy bạn được thêm hai dòng như sau:

add_action( 'add_meta_boxes', 'add_moremtb_meta' );
add_action( 'save_post', 'moremtb_meta_save' );

Tạo các hộp meta và mã Javascript

Đây là bước quan trọng nhất, và cũng là khâu sẽ tốn nhiều thời gian. Tại đây bạn phải thiết lập các trường cần thiết của bạn. Ví dụ, mình cần tạo ra một log để lưu nội dung. Mỗi 1 nội dung mình có 1 ID đi kèm. Như vậy mình sẽ cần tạo ra hai trường nhập nội dung và ID. Phần này mình sẽ viết trong hàm moremtb_details_init() như sau:

function moremtb_details_init() {
  global $post;
  //hiển thị các trường xác thực
  wp_nonce_field( 'addmoreinfo', 'moremtb_nonce' );
  ?>
    <div id="moremtb_meta_item">
  <?php

  //lấy dữ liệu đã được thêm trước đó
  $moremtbDetails = get_post_meta($post->ID,'moremtbDetails',true);

  $c = 0;
  if (is_array($moremtbDetails)){
    if ( count( $moremtbDetails ) > 0) {
      foreach( $moremtbDetails as $moremtbDetail ) {
         if ( isset( $moremtbDetail['ids'] ) || isset( $moremtbDetail['contents'] ) ) {
            printf( '<p>Mã ID<input type="text" name="moremtbDetails[%1$s][ids]" value="%2$s" /> Mô tả : <textarea name="moremtbDetails[%1$s][contents]" rows="4" cols="50" >%3$s</textarea><a href="#" class="remove-package">%4$s</a></p>', $c, $moremtbDetail['ids'], $moremtbDetail['contents'], 'Xóa bỏ' );
            $c = $c +1;
         }
      }
    }
  }

  ?>

      <span id="output-package"></span>
      <a href="#" class="add_package"><?php _e('Thêm thông tin'); ?></a>
    </div>

  <?php
  }

Bước trên bạn chú ý vào name của các control. Chúng đều phải được gắn kèm với một tên meta nhất định (ở đây là moremtbDetails). Cơ bản thì để tạo một metabox bình thường như thế này là xong hàm này. Tuy nhiên trong bài viết này mình hướng dẫn các bạn có thể tạo ra nút nhân bản nhiều nhóm metabox như thế này nữa, do đó mình cần làm thêm một số công đoạn nữa, đó là thêm mã Javascript để hoạt động. Bạn thêm đoạn này ngay dưới thẻ </div> cuối cùng của đoạn mã trên nhé.

<script>
  var $ =jQuery.noConflict();
  $(document).ready(function() {
    var count = <?php echo $c; ?>;
    $(".add_package").click(function() {
      count = count + 1;
      $('#output-package').append('<p> Mã ID <input type="text" name="moremtbDetails['+count+'][ids]" value="" /> Mô tả : <textarea name="moremtbDetails['+count+'][contents]" rows="4" cols="50" ></textarea><a href="#" class="remove-package"><?php echo "Xóa bỏ"; ?></a></p>' );
      return false;
    });
    $(document.body).on('click','.remove-package',function() {
    $(this).parent().remove();
    });
  });
</script></div>

Như vậy là bạn đã hoàn thành được khâu quan trọng rồi. Nếu muốn thêm nội dung thì bạn có thể thêm các hộp meta box và thay đổi thuộc tính name của trường đó theo cú pháp “moremtbDetails['Số thứ tực'][tên trường]“.

Kết quả tạo hộp meta và mã Javascript

Kết quả tạo hộp meta và mã Javascript

Viết hàm lưu dữ liệu

Việc cuối cùng rất dễ dàng như vô cùng quan trọng đó là bạn phải viết hàm lưu trữ dữ liệu. Tại hàm moremtb_meta_save đã tạo, bạn thêm vào các nội dung như sau:

function moremtb_meta_save( $post_id ) {
  if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
     return;
  if ( !isset( $_POST['moremtb_nonce'] ) )
     return;
  if ( !wp_verify_nonce( $_POST['moremtb_nonce'], 'addmoreinfo' ) )
     return;
  $moremtbDetails = $_POST['moremtbDetails'];
  update_post_meta($post_id,'moremtbDetails',$moremtbDetails);
}
Kết quả của dữ liệu là một biến mảng.

Kết quả của dữ liệu là một biến mảng.

Bây giờ việc lấy dữ liệu cũng không quá khó khăn, bạn chỉ cần gọi lệnh get_post_meta($post->ID,'moremtbDetails',true); kết quả trả về là một mảng đa chiều để bạn có thể sử dụng hàm lặp lấy ra dữ liệu cần thiết. Chúc bạn thành công !