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

Rate this post

Nếu bạn bước vào quá trình lập trình giao diện WordPress, việc một số widget hiện tại không đáp ứng nhu cầu và nảy sinh tạo widget đi kèm giao diện đó là không tránh khỏi.

Widget WordPress là gì?

Widget được hiểu là các thành phần có khả năng di động (kéo thả) thêm bớt trong những khu vực (gọi là sidebar) trong WordPress.

Một sidebar và các widget bên trong
Một sidebar và các widget bên trong

Tất nhiên, để tạo ra sidebar hay widget thì đều cần phải đăng ký thông qua các function có sẵn của WordPress.

Trước đây, Code Tốt từng có bài viết hướng dẫn tạo Custom Widget nhưng kèm theo các query bài viết. Hôm nay, ta sẽ tìm hiểu cách tạo toàn bộ là các mục nhập field kết hợp cả plugin Advanced Custom Fields.

Cách tạo Widget và cả Sidebar trong WordPress

Để bắt đầu, mình sẽ lấy ví dụ một module từ một trong các giao diện HTML để làm minh họa. Ở đây, ta nhận thấy ở cuối trang của giao diện này có 2 widget cần đăng ký:

Ví dụ về widget trong giao diện mẫu

Ta có một nhiệm vụ quan trọng là làm sao để bố cục này trở thành một widget, và tạo một sidebar để đăng ký widget.

Đăng ký Widget trong WordPress

Mình tiến hành đăng ký Widget này như sau sử dụng function register_sidebar():

// functions.php
function codetot_widget_init() {
  register_sidebar( array(
     'name'          => 'Top Footer',
     'id'            => 'top_footer',
     'before_widget' => '<div class="col-lg-6 xs-feature-item"><div class="xs-feature-group wow fadeInLeft"><div class="media">',
     'after_widget'  => '</div></div></div>',
     'before_title'  => '<h4 class="xs-title">',
     'after_title'   => '</h4>'
  ) );
}
add_action('widgets_init', 'codetot_widget_init');

Mình gọi tên Sidebar này là Top Footer. Có 2 phần cần wrap div trước và sau như các bạn thấy, bao gồm trong mỗi widget (có 3 <div>) và class heading của title (thường dùng H4, H5 hoặc H6).

Khởi tạo Widget mới trong WordPress

Đầu tiên, ta cần lưu ý tới function register_widget() rằng nó cần đăng ký 1 class extends từ WP_Widget ra.

Ta sẽ bắt đầu cũng vẫn trong function codetot_widget_init vừa viết ra ở trên như sau:

function codetot_widget_init() {
  register_sidebar(...);
  register_widget('CodeTot_Top_Footer_Widget');
}
add_action('widgets_init', 'codetot_widget_init');
class CodeTot_Top_Footer_Widget extends WP_Widget {}

Giờ, ta sẽ cần đăng ký các lớp và thuộc tính cho class ta vừa tạo để đăng ký widget như sau:

class CodeTot_Top_Footer_Widget extends WP_Widget {
   public function __construct() {}
   public function form( $instance ) {}
   public function update( $new_instance, $old_instance ) {}
   public function widget( $args, $instance ) {}
}

Lần lượt, ta có các phương thức sau:

public function __construct() {}

Bạn sẽ đăng ký tên Widget, mô tả và các tùy chọn bổ sung trong khi thêm widget.

public function form() {}

Đây là nơi bạn quyết định các form sẽ hiển thị trong widget để người dùng nhập. Trong bài viết này, ta sẽ thử thêm form nhập bằng cả cách thông thường lẫn sử dụng plugin Advanced Custom Fields.

public function update() {}

Đây là phần bạn khai báo các giá trị sẽ được thay thế khi người dùng cập nhật nội dung widget.

public function widget() {}

Đây là function sẽ hiển thị các nội dung của trong widget ra bên ngoài.

Ta sẽ làm việc với từng function của class để rõ hơn.

CLASS Đăng ký Widget

Khai báo tên và các thông tin bổ sung cho widget

Ở bước này, ta cần thực hiện việc đăng ký tên hiển thị cho widget như sau:

public function __construct() {
   $options = array(
      'description' => __('A widget to add Two Up on Top Footer sidebar.', 'codetot')
   );
   parent::__construct( 'top_footer_widget', '[*] Top Footer Widget', $options );
}

Trong code mẫu ở trên, ta khai báo “description” (mô tả) cho widget và đăng ký lần lượt widget_id, widget_name.

Khai báo các mục nhập trong Widget backend

public function form( $instance ) {
   $title = ! empty( $instance['title'] ) ? $instance['title'] : esc_html__( 'Title', 'upreseller' );
   ?>
   <p>
      <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
         <?php esc_attr_e( 'Title:', 'codetot' ); ?>
      </label>
      <input
         class="widefat"
         id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
         name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
         type="text"
         value="<?php echo esc_attr( $title ); ?>">
   </p>
   <?php
}

Code mẫu ở trên cho phép đăng ký Title và hiển thị như sau trong backend:

Đăng ký field Title trong Widget

Nếu bạn sử dụng Advanced Custom Fields (bản PRO), bạn đăng ký bằng cách tạo Field Group với điều kiện là Widget khớp nhé:

Đăng ký field widget trong ACF

Kết quả hiển thị rất dễ nhìn:

Mục nhập field của widget

Function Cập nhật widget

public function update( $new_instance, $old_instance ) {
   $instance = $old_instance;
   $instance['title'] = isset( $new_instance['title'] ) ? wp_strip_all_tags( $new_instance['title'] ) : '';
   return $instance;
}

Trong function ở trên, mình chỉ cần đăng ký cho field nào đăng ký trong class thôi, các mục nhập field đăng ký thông qua ACF Field Group thì không cần nhé.

Hiển thị widget WordPress đã đăng ký ra bên ngoài

Bước này giống như bạn xếp hình vậy, lưu ý có một số biến được WordPress quy định bạn phải thêm vào, ví dụ: before_widget, before_title, after_title hay after_widget nhé.

Ta lần lượt wrap các thành phần đã có kết quả vào kết hợp với các markup mình mong muốn như sau:

public function widget( $args, $instance ) {
   if ( ! isset( $args['widget_id'] ) ) {
      $args['widget_id'] = $this->id;
   }

   // widget ID with prefix for use in ACF API functions
   $widget_id = 'widget_' . $args['widget_id'];

   $description = get_field( 'description', $widget_id ) ? get_field( 'description', $widget_id ) : '';
   $image = get_field( 'image', $widget_id ) ? get_field( 'image', $widget_id ) : '';
   $button = get_field( 'button', $widget_id ) ? get_field( 'button', $widget_id ) : '';

   echo $args['before_widget'];
   if (!empty($image)) {
      echo '<div class="widget__image-block">';
      echo '<img class="widget__image" src="' . $image . '" alt="' . $instance['title'] . '">';
      echo '</div>';
   }
   echo '<div class="widget__block-content">';
   if ( ! empty( $instance['title'] ) ) {
      echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
   }
   if ( ! empty( $description ) ) {
      echo $description;
   }
   if( !empty($button['url']) && !empty($button['title']) ) :
      echo '<div class="widget__cta">';
      echo '<a href="' . $button['url'] . '" class="btn btn-primary widget__button">' . $button['title'] . '</a>';
      echo '</div>';
   endif;
   echo '</div>';
   echo $args['after_widget'];
}

Trong ví dụ ở trên, mình cần lấy các biến từ cả ACF lẫn field mình đăng ký và output vào bằng cách sử dụng echo của PHP.

Kết luận

Đăng ký widget để hiển thị các nội dung mong muốn là một bài toán thông minh giúp giao diện của bạn có nhiều tính năng hỗ trợ tương thích toàn diện trong quá trình phát triển. Đây cũng là cách nhiều giao diện magazine (tạp chí) tận dụng thông qua các Sidebar như Homepage để tăng khả năng tùy biến bố cục mà ta thường thấy.

Nguồn tham khảo bổ sung

How to Create a WordPress Widget From Scratch (Kinsta)

Viết một bình luận


Chuyên gia về Web
Bạn muốn làm việc với dịch vụ website do chúng tôi triển khai?
Gọi tư vấn 0982.90.4343
Chuyên gia về Web
Bài viết liên quan

02/01/2024

Fix lỗi npm không thể cài các package devDependencies
Khi cài đặt dự án,  có lúc bạn sẽ cài mãi cũng không đủ các package npm, đặc biệt là...
Gọi file PHP trong WordPress

19/09/2023

Cài đặt và sử dụng WP-CLI trên môi trường Linux
Trên một số môi trường Hosting có thể cung cấp SSH hoặc Terminal access, song không có sẵn WP-CLI để...
Import database MySQL lớn trên môi trường Docker

06/08/2023

Import database MySQL lớn trên môi trường Docker
Mình sử dụng EasyPanel để quản lý các Docker và build môi trường app. Nay gặp tình huống phải import...

28/01/2023

Hướng dẫn cài đặt php extension mongodb trên Mac OS M1
Khi bạn muốn hỗ trợ MongoDB trên dòng Mac M1, phần cài đặt sẽ cần một chút lưu ý. Hướng...