WordPress-Widget-la-gi-dinh-nghia-wolfactive-949x475
02/08/2020

WordPress: Thiết Kế Theme (P12: Create Widget)

Chào mừng các bạn đến với series WordPress Thiết Kế Theme của tụi mình. Ở phần 12 này, mình sẽ viết về cách tạo một Widget trên WordPress. Chắc hẳn đối với các bạn cũ, thì việc tạo một Widget cho bản thân mình không còn xa lạ gì nữa, vậy còn các bạn mới thì hẵn sẽ rất là bỡ ngỡ nhỉ. Vậy mình cùng tìm hiểu một tí về widget và cách tạo chúng nhé.

1/ Widget

Widget nó cũng gần giống như ShortCode về việc các bạn đổ dữ liệu vào chúng và lấy chúng ra. Tuy nhiên ShortCode bạn cần phải đăng ký sử dụng chúng trên Widget Text và có thể gọi chúng ở bất kì nơi đâu trong template của mình. Còn Widget nó sẽ hạn chế hơn vì nó chỉ có thể hiện thị chủ yếu trên Sidebar mà thôi. Mà đối với việc chúng ta làm một website cho khác hàng thì viết Widget cho khách hàng sử dụng là dễ tiếp cận hơn là viết short code. Giờ mình cùng tìm hiểu cách tạo chúng nhé.

2/ Chuẩn bị

Trước khi chúng ta bắt tay vào làm cái gì thì cũng phải chuẩn bị nguyên liệu trước cái đã nhỉ :D. Trước hết các bạn cần tạo một file để viết một Widget cho mình. Ở đây mình tạo file php tên “popular_post_widget“. Sau đó mình include nó vào file function.

$file_includes = [
     'includes/theme-setup.php',                // General theme setting
     'includes/acf-options.php',  // ACF Option page
     'includes/resize.php',
     'includes/short-code.php',
     'includes/popular_post_widget.php',
 ];

Đây là cách include file của mình, các bạn có thể đọc lại cách include của mình tại đây Hoặc các bạn có thể include bằng require hoặc include tùy các bạn.

Bước kế tiếp mình sẽ bắt đầu ướp gia vị hay còn được gọi là sơ chế cho file “popular_post_widget“, cụ thể như sau:

Tạo class

class Most_Popular_Post_Widget extends WP_Widget{
      public function __construct(){}
      public function form($instance){}
      public function widget($args,$instance){}
      public function update($new_instance, $old_instance){}
} 
function _wolfactive_most_popular_post_widget(){
      register_widget('Most_Popular_Post_Widget');
}
add_action('widgets_init','_wolfactive_most_popular_post_widget');

OKIE, Vậy là chúng đã đã chuẩn bị và sơ chế xong món Widget của mình rồi nhỉ. Kế tiếp chúng ta sẽ bắt đầu chế biến món Widget này nhé. Mà trước khi bắt đầu thì mình sẽ giải thích trước ở từng function mình tạo ở trên cái đã nhỉ

  • construct: dùng để khai báo Widget, bao gồm id và tên, mô tả của widget (Tuy nhiên ở phần này mình chỉ sử dụng đến id và tên hiển thị thôi).
  • form: có nhiệm vụ hiển thị và lấy thông tin từ khung nhập thông tin bạn tạo
  • widget: hiển thị nội dung widget ngoài giao diện template
  • update: thêm, cập nhật lại thông tin của Widget.
  • register_widget: đăng kí widget (chỗ này các bạn nhớ ghi giống với tên class nhé ).

Giải thích đã xong rồi nhỉ, giờ mình cùng chế biến nó nhé 😀

Construct Function

Đầu tiên các bạn cần khởi tạo thông tin cho widget trước ở trong function _construct. Cụ thể như sau:

parent::__construct(
            'most_popular_widget', // id widget
            esc_html__('Wolfactive Popular Post','base-theme'), // Tên hiển thị của widget
            array(
                'description' => esc_html__( 'Display Wolfactive Popular Post','base-theme') // mô tả nội dung widget
            )
        );

Ở đây mình có ghi là base-theme chính là tên theme của các bạn, tuy nhiên ở đây các bạn ghi hay không vẫn được. Không sao cả nhé. Giờ mình xem kết quả đầu tiên nó sẽ ra như thế nào hen.

Wow nhìn widget mình tạo xong, tự nhiên thấy mình đẹp trai, xinh gái hẳn hen các bạn. 😀 . Tuy nhiên vẫn chưa xong đâu nhé! Sau khi mình khởi tạo nó thì mình đến bước tiếp theo nhé là tạo form cho Widget ở trong function form.

form function

if(isset($instance['title'])){
   $title = $instance['title'];
} else {
   $title = '';
}
if(isset($instance['post_count'])){
   $postCount = $instance['post_count'];
} else {
   $postCount = 1;
}
if(isset($instance['include_date'])){
   $showDate = $instance['include_date'];
} else {
   $showDate = false;
}
if(isset($instance['sort_by'])){
   $sort_by = $instance['sort_by'];
} else {
   $sort_by = 'date';
}
?>
<div>
   <p><label for="<?php echo $this->get_field_id('title');?>"> <?php esc_html_e('Title:','base-theme')?></label></p>
   <input type="text" class="widefat" id="<?php echo $this->get_field_id('title')?>" name="<?php echo $this->get_field_name('title') ?>" value="<?php echo esc_attr($title); ?>" />
</div>
<p>
   <label for="<?php echo $this->get_field_id('post_count') ?>"><?php esc_html_e('Post Count') ?></label>
   <input type="number" class="tiny-text" id="<?php echo $this->get_field_id('post_count')?>" min="1" max="5" value="<?php echo intval($postCount); ?>" name="<?php echo $this->get_field_name('post_count') ?>"/>
</p>
<p>
   <label for="<?php echo $this->get_field_id('include_date')?>"><?php esc_html_e('Show Date','base-theme')?></label>
   <input name="<?php echo $this->get_field_name('include_date') ?>" <?php checked($showDate)?> type="checkbox" class="wolfactive__widget-input" id="<?php echo $this->get_field_id('include_date')?>" />
</p>
<p>
   <label for="<?php echo $this->get_field_id('sort_by')?>"><?php esc_html_e('Sort By:','base-theme')?></label>
   <select id="<?php echo $this->get_field_id('sort_by')?>" name="<?php echo $this->get_field_name('sort_by')?>">
      <option <?php selected($sort_by,'date');?> value="date"><?php esc_html_e('Most Recent'); ?></option>
      <option <?php selected($sort_by,'rand');?> value="rand"><?php esc_html_e('Random'); ?></option>
   </select>
</p>
<?php

Đoạn code trên mình tạo bao gồm các field như sau: nhập tên Widget, số bài viết sẽ hiển thị, chọn hiển thị ngày tháng, chọn loại sắp xếp bài viết. Các bạn để ý ở bước này mình có ghi $this->get_field_id(‘abcxyz’) hoặc get_field_name(‘abcxyz’) thì đây chính là bước bạn tạo idname cho field ấy. Bạn có thể ghi bất kì cái gì bạn muốn nhé. Và ở mục Value nó sẽ kiểm tra đoạn if trên có giá trị không nếu có thì sẽ đưa vào. Tương tự như vậy, những field khác cũng như thế.

Tuy nhiên ở đây có một bước mình tạo hơi khác tí chính là phần select. Các bạn nhìn vào sẽ thấy mình sử dụng hàm selected(tên biến, value), value ở đây mình lấy theo quy ước sắp xếp của query WordPress do đó mình dùng sắp xếp theo daterand.

update function

Như vậy mình đã xong hai giai đoạn là khởi tạo và tạo form nhập. Giờ mình sẽ sang giai đoạn 3, lấy dữ liệu từ form mình nhập nhé, đây chính là function update đấy

public function update($new_instance, $old_instance){
   $instance = array();
   $instance['title'] = sanitize_text_field($new_instance['title']);
   $instance['post_count'] = intval($new_instance['post_count']);
   $instance['include_date'] = boolval($new_instance['include_date']);
   $instance['sort_by'] = WolfactiveOrderSort($new_instance['sort_by']);
   return $instance;
}

Ở function này mình tạo một biến $instance ở dạng mảng và chỉ sử dụng mỗi biến $new_instance, dù vậy mình vẫn dữ biến $old_instance lại và không xóa nó đi. Vì nếu mình xóa, WordPress sẽ báo lỗi các bạn. À mà các bạn thấy sử dụng hàm WolfactiveOrderSort đễ đưa giá trị vào biến $instance. Và đây là hàm WolfactiveOrderSort của mình (các bạn tạo bên class nhé).

function WolfactiveOrderSort($input){
   $value = array('date','rand');
   if(in_array($input, $value,true)){
      return $input;
   } return 'date';
}

Giờ các bạn kiểm tra Widget mình bằng cách nhập rồi save lại, các bạn có thể dùng var_dump để kiểm tra giá trị bên trong biến $instance như thế nào ở trong hàm form.

Như vậy là gần xong rồi đó. Giờ mình cùng nhau display nó ra ngoài template nhé.

widget function

public function widget($args,$instance){
   echo $args['before_widget'];
   if(isset($instance['title']))
   {
      $title=apply_filters('widget_title',$instance['title']);
      echo $args['before_title'].esc_html($title).$args['after_title'];
   }
   $most_popular = array(
      'showposts' => $instance['post_count'],
      'meta_key' => 'post_views_count',
      'orderby' => $instance['sort_by'],
      'post_type' => 'post',
      'post_status' => 'publish',
);
   $popular_post_query = new WP_Query($most_popular);
?>
<div class="popular__post">
  <div class="popular__post-container">
   <?php
      while ($popular_post_query->have_posts()):$popular_post_query->the_post();
         $views = getPostViews(get_the_id());
   ?>
      <div class="popupar__post-item my-10">
            <div class="nw__post-item row-divide">
                  <div class="nw__image col-divide-4">
                        <a href="<?php echo get_permalink(); ?>"><img src="<?php echo get_the_thumbnail() ?>" alt="Image"></a>
                  </div>
                  <div class="nw__infomation col-divide-8">
                        <div class="nw__post-title nw__post-title--small">
                              <a href="<?php echo get_permalink(); ?>"><?php echo wp_trim_words( get_the_title(), 10, '...' );?></a>
                        </div>
<?php                   if($instance['include_date']){ ?>
                  <div class="nw__editor-date open-sanrif">
                        <span class="date-time open-sanrif"><?php echo get_the_date( 'F j, Y' ) ?></span>
                  </div>
<?php } ?>
                  </div>
            </div>
      </div>
<?php
endwhile;
?></div>
</div>
<?php
echo $args['after_widget'];
}

Có lẽ các bạn sẽ thắc mắc $args[‘after_widget’], before_widget, before_title, after_title ở đâu ra. Đó chính là ở trong phần bạn tạo Widget đấy. Nói nôm na là mở thẻ và đóng thẻ á. Ví dụ như mình có một widget được tạo như sau:

register_sidebar(array(
'name' => 'Wolfactive Sidebar',
'id' => 'wolfactive-sidebar',
'before_widget' => '<div class="wolfactive-sidebar">',
'after_widget' => '</div>',
'before_title' => '<h2 class="title--section text--upcase">',
'after_title' => '</h2>',
));

Đấy các bạn thấy chứ :D. Các bạn cũng có thể coi lại cách mình tạo sidebar tại đây và đây là kết quả của mình.

Tổng kết

Như vậy mình đã hướng dẫn các bạn xong phần tạo widget trên wordpress rồi đó! Chúc các bạn thành công và một ngày vui vẻ nhé. Mọi thông tin hay thắc mắc các bạn cứ liên hệ fanpage tụi mình nhé <3. Cảm ơn các bạn đã ủng hộ WolfActive tụi mình.

Vui lòng chọn size trước khi đặt hàng (*)