Widget trong WordPress ai cũng hiểu nó là một block nội dung được đặt trong một khu vực được chỉ định, khu vực này ta thường gọi là Widget Area hoặc Sidebar. Ngoài các widget có sẵn như Recent Posts, Recent Comments,…thì nếu muốn có thêm widget bạn phải cài plugin hoặc một số theme cũng cho bạn thêm vài widget tùy chọn.
Vậy làm thế nào để hiểu quy trình tạo một widget ra sao? Ở bài này mình sẽ phân tích kỹ lưỡng cách tạo một widget là như thế nào, nhưng dĩ nhiên là bạn cần có sẵn kiến thức PHP ví dụ như bạn nên hiểu Class và đối tượng trong PHP là thế nào.
Khái niệm về cách tạo widget
Xem trước: Widgets API – WordPress Codex
Trong WordPress đã có sẵn một class tên là WP_Widget, trong class này có những method (phương thức), nghĩa là bạn phải viết các phương thức này theo chuẩn của nó, không được thiếu mà cũng không có thừa và phải viết đúng tên phương thức.
Trong class WP_Widget
có tổng cộng 3 phương thức bắt buộc, bao gồm:
__construct: Phương thức khởi tạo này sẽ có nhiệm vụ khai báo tên widget, mô tả widget.
form: Phương thức này sẽ hỗ trợ bạn tạo các form nhập liệu bên trong một widget, xem hình dưới.
update: Phương thức này sẽ hỗ trợ bạn lưu dữ liệu mà người dùng đã nhập vào các form mà bạn đã tạo bằng phương thức form.
widget: Phương thức này sẽ giúp bạn gọi dữ liệu và hiển thị ra ngoài website khi bạn gắn cái widget này lên.
Ngoài ra, trong class này bạn cũng phải khai báo một phương thức nào đó do bạn tùy chọn để thiết lập tên và mô tả của widget. Một số thì dùng phương thức __construct()
và một số thì tự tạo một phương thức khác. Ở đây mình chọn cách tự tạo phương thức vì nó dễ nhìn và dẽ hiểu hơn.
Chuẩn bị
Bạn có thể thực hành bài này bằng cách viết code vào file functions.php
trong theme, nhưng tốt hơn hết là bạn tạo một plugin đi. Tạo một file với tên nào đó ở thư mục wp-content/plugins
và viết đoạn này ở đầu file
<?php
/*
Plugin Name: Test Widget
Plugin URI: https://thachpham.com
Description: Thực hành tạo widget item.
Author: Thach Pham
Version: 1.0
Author URI: http://google.com
*/
Khỏi cần nói cũng biết, các code thực hành trong bài này bạn viết vào bên dưới dòng trên nhé.
6 bước tạo widget item
Bước 1. Khởi tạo widget
Đầu tiên, để khởi tạo một widget thì ta có 4 đoạn sau để khởi tạo.
/*
* Khởi tạo widget item
*/
add_action( ‘widgets_init’, ‘create_thachpham_widget’ );
function create_thachpham_widget() {
register_widget(‘Thachpham_Widget’);
}
Trong đó, Thachpham_Widget
là class mà chút nữa chúng ta sẽ tạo.
Bước 2. Tạo class và cấu trúc các phương thức
Như mình đã nói, bây giờ chúng ta sẽ tạo một class mang tên Thachpham_Widget kế thừa cái class WP_Widget
mặc định, trong đó sẽ có 3 phương thức bắt buộc là form
, update
, widget
và kèm theo một phương thức để đặt tên cho widget. Ta có như sau.
/**
* Tạo class Thachpham_Widget
*/
class Thachpham_Widget extends WP_Widget {/**
* Thiết lập widget: đặt tên, base ID
*/
function __construct() {}
/**
* Tạo form option cho widget
*/
function form( $instance ) {}
/**
* save widget form
*/function update( $new_instance, $old_instance ) {
}
/**
* Show widget
*/function widget( $args, $instance ) {
}
}
Mình đã có comment rõ ràng trong đó rồi nhé.
Bây giờ bạn thử lưu lại xem và có thấy phần Appearance -> Widget của mình xuất hiện thêm một cục không ghi tên như hình dưới không, nếu có thì bạn đã làm đúng.
Bước 3: Đặt tên cho widget (__construct)
Ở bước này, chúng ta sẽ làm việc trong phương thức __construct()
nhé. Bây giờ ta sẽ tạo cho nó một cái mảng bao gồm các giá trị như sau:
function __construct() {
parent::__construct (
‘thachpham_widget’, // id của widget
‘ThachPham Widget’, // tên của widgetarray(
‘description’ => ‘Mô tả của widget’ // mô tả
)
);
}
Trong đó, các thông tin mình đã có ghi chú thích vào trong đó rồi nhé.
Bây giờ chúng ta gắn cái biến này vào đoạn sau.
Bây giờ lưu lại và vào Appearance -> Widget tìm cái tên widget mà bạn vừa tạo ra nào.
Bước 4: Tạo form cho widget (form)
Bất kỳ widget nào cũng nên có một form nhập liệu để khách nhập những tùy chọn hay giá trị nào đó vào đây, bạn có thể sử dụng dropdown, checkbox,…nhưng ở đây mình sẽ dùng input loại text cho đơn giản.
Trong bước này ta sẽ làm việc trong phương thức form()
nhé. Phương thức này ta có một biến là $instance
.
Đầu tiên ra khai báo một mảng như sau:
//Biến tạo các giá trị mặc định trong form
$default = array(
‘title’ => ‘Tên của bạn’
);
Mảng này có vai trò thiết lập các giá trị mặc định cho từng form. Ví dụ bạn có một form tên title thì giá trị mặc định của nó nếu người dùng chưa nhập vào là Tên của bạn, nếu bạn có nhiều form thì làm thêm nhiều giá trị trong mảng này.
Kế tiếp là viết thêm đoạn này
//Gộp các giá trị trong mảng $default vào biến $instance để nó trở thành các giá trị mặc định
$instance = wp_parse_args( (array) $instance, $default);
Đoạn này bạn hiểu đơn giản là nó sẽ lôi toàn bộ giá trị mảng của biến $default
sang biến $instance
.
Tiếp tục viết thêm một đoạn này
//Tạo biến riêng cho giá trị mặc định trong mảng $default
$title = esc_attr( $instance[‘title’] );
Đơn giản là ta đưa $instance['title']
vào một biến cho dễ nhớ, dễ viết. Trong đó, $title
là biến sẽ chứa giá trị của tiêu đề lấy từ khóa title
trong mảng $instance
.
Và cuối cùng là đoạn quan trọng nhất, chúng ta sẽ tạo ra một cái trường nhập liệu và nó sẽ hiển thị giá trị là biến $title. Điều này có nghĩa là nếu như sau này chúng ta truyền giá trị mới cho $title thì nó cũng sẽ hiển thị ra.
//Hiển thị form trong option của widget
echo "Nhập tiêu đề <input class="widefat" type="text" name="’".$this->get_field_name(‘title’)."’ value=’".$title."’ />";
Bây giờ bạn lưu lại và mở widget ra sẽ thấy có một form và thuộc tính mặc định như sau:
Bạn có thể thử bằng cách nhập một cái gì đó vào form rồi ấn Save lại thì thấy nó không được lưu lại mà toàn trả về giá trị mặc định. Đó là do chúng ta chưa viết code cho phương thức update
.
Toàn bộ code trong bước này:
/**
* Tạo form option cho widget
*/
function form( $instance ) {
parent::form( $instance );//Biến tạo các giá trị mặc định trong form
$default = array(
‘title’ => ‘Tiêu đề widget’
);//Gộp các giá trị trong mảng $default vào biến $instance để nó trở thành các giá trị mặc định
$instance = wp_parse_args( (array) $instance, $default);//Tạo biến riêng cho giá trị mặc định trong mảng $default
$title = esc_attr( $instance[‘title’] );//Hiển thị form trong option của widget
echo "Nhập tiêu đề <input class="widefat" type="text" name="’".$this->get_field_name(‘title’)."’ value=’".$title."’ />";}
Bước 5. Lưu giá trị khi nhập form (update)
Bước này ta sẽ làm việc với phương thức update()
. Trong phương thức này ta có hai tham số chính là $new_instance
được dùng để lưu những giá trị sau khi ấn nút Save và $old_instance
là giá trị cũ trong cơ sở dữ liệu. Sau khi dữ liệu nhập vào được lưu thì ta sẽ return nó ra.
Ta có
$instance = $old_instance;
$instance[‘title’] = strip_tags($new_instance[‘title’]);
return $instance;
Nghĩa là ở trên mình sẽ lưu lại các giá trị trong form nhập tiêu đề. Hàm strip_tags()
được sử dụng để cho cái form không thực thi PHP và HTML.
Toàn bộ code sẽ là
/**
* save widget form
*/function update( $new_instance, $old_instance ) {
parent::update( $new_instance, $old_instance );$instance = $old_instance;
$instance[‘title’] = strip_tags($new_instance[‘title’]);
return $instance;
}
Bây giờ bạn thử viết gì vào form rồi lưu lại, các giá trị sẽ lưu lại.
Bước 6. Xuất dữ liệu hiển thị ra ngoài
Ta đã tạo form, rồi lưu dữ liệu trong form vào. Vậy làm thế nào để có thể xuất nó hiển thị ra ngoài đây? Trong bước này ta sẽ làm việc với phương thức widget để hiển thị nó ra ngoài.
Trong phương thức này ta có 2 tham số là $args
để khai báo các giá trị thuộc tính của một widget (title, các thẻ HTML,..) và $instance
là giá trị mà khách đã nhập vào form trong widget.
Nếu bạn muốn sử dụng lại các thuộc tính bên trong widget thì tốt hơn hết bạn nên extract cái array trong widget ra thành từng biến riêng. Ta có:
extract( $args );
Sau đó, để hiển thị giá trị của một form thì ta chỉ cần echo $instance['form_name']
. Như ví dụ này thì ta có $instance['title']
.
Nhưng do cái form này là ta nhập tiêu đề của widget nên bạn nên thêm filter hook cho nó để đúng chuẩn trong WordPress.
echo apply_filters( ‘widget_title’, $instance[‘title’] );
Nhưng mà đợi đã, ta không thể viết chay như vậy, tại sao? Bởi vì trong Widget nó có những cái hook như hook vị trí trước widget (before widget), sau widget (after widget) và quan trọng là nếu bạn hiển thị cái tiêu đề widget như thế kia thì không được do ta thiếu hook $before_widget
và $after_widget
, hai biến này là hook in ra thẻ heading để tiêu đề widget hiển thị đúng “phong cách”.
Như vậy, ta tạm đưa đoạn apply_filters()
vào trong một biến:
$title = apply_filters( ‘widget_title’, $instance[‘title’] );
Sau đó ta viết như sau:
echo $before_widget;//In tiêu đề widget
echo $before_title.$title.$after_title;// Nội dung trong widget
echo "ABC XYZ";
// Kết thúc nội dung trong widget
echo $after_widget;
Như vậy, khi in widget ra bạn bắt buộc phải echo thêm biến $before_widget
và $after_widget
để bọc nội dung lại, không có nó không có hiển thị đâu nhé.
Và kết quả là:
Toàn bộ code trong bước này là:
function widget( $args, $instance ) {extract( $args );
$title = apply_filters( ‘widget_title’, $instance[‘title’] );echo $before_widget;
//In tiêu đề widget
echo $before_title.$title.$after_title;// Nội dung trong widget
echo "ABC XYZ";
// Kết thúc nội dung trong widget
echo $after_widget;
}
Quá dễ phải không nào.
Tải source code
Thực hành – Tạo widget hiển thị bài ngẫu nhiên
Bạn đã biết cách tạo một widget là như thế nào rồi, vậy thì tại sao lại không thực hành nó ngay? Ở đây mình sẽ thực hành cách tạo một widget hiển thị bài viết ngẫu nhiên với tùy chọn cho phép khách nhập số lượng bài cần hiển thị bằng việc ứng dụng khái niệm Loop và Query.
</pre>
<pre>class Random_Post extends WP_Widget {function __construct() {
parent::__construct(
‘random_post’,
‘Bài ngẫu nhiên’,
array( ‘description’ => ‘Widget hiển thị bài viết ngẫu nhiên’ )
);
}function form( $instance ) {
$default = array(
‘title’ => ‘Tiêu đề widget’,
‘post_number’ => 10
);
$instance = wp_parse_args( (array) $instance, $default );
$title = esc_attr($instance[‘title’]);
$post_number = esc_attr($instance[‘post_number’]);echo ‘<p>Nhập tiêu đề <input type="text" class="widefat" name="’.$this->get_field_name(‘title’).’" value="’.$title.’"/></p>’;
echo ‘<p>Số lượng bài viết hiển thị <input type="number" class="widefat" name="’.$this->get_field_name(‘post_number’).’" value="’.$post_number.’" placeholder="’.$post_number.’" max="30" /></p>’;}
function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance[‘title’] = strip_tags($new_instance[‘title’]);
$instance[‘post_number’] = strip_tags($new_instance[‘post_number’]);
return $instance;
}function widget( $args, $instance ) {
extract($args);
$title = apply_filters( ‘widget_title’, $instance[‘title’] );
$post_number = $instance[‘post_number’];echo $before_widget;
echo $before_title.$title.$after_title;
$random_query = new WP_Query(‘posts_per_page=’.$post_number.’&orderby=rand’);if ($random_query->have_posts()):
echo "<ol>";
while( $random_query->have_posts() ) :
$random_query->the_post(); ?><li><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></li>
<?php endwhile;
echo "</ol>";
endif;
echo $after_widget;}
}
add_action( ‘widgets_init’, ‘create_randompost_widget’ );
function create_randompost_widget() {
register_widget(‘Random_Post’);
}</pre>
<pre>
Lời kết
Như vậy là bạn đã biết qua cách tạo một widget là như thế nào rồi đúng không nào? Thoạt nhìn code có thể bạn nghĩ nó khó nhưng thật ra nó chẳng có gì khó cả và mình tin là bạn có thể tự làm được sau khi đọc kỹ bài của mình.
Nếu có gì thắc mắc, hãy comment phía dưới nhé.
Tham khảo: Cách tạo widget nhanh với scbFramework – WordPressKite
Xem tiếp bài trong serie
Phần trước: Cách tự tạo một Meta Box đơn giản toàn tập