Actions và Filter Hooks là gì?

Actions hook là gì?

Actions là một trong 2 loại Hooks, chúng cung cấp cách để chạy hàm tại một số điểm neo trong quá trình chạy cách hàm thuộc WordPress Core, plugins và themes. Các hàm này thì trái ngược với filter hook là chạy được liền mạch và không làm thay đổi các giá trị như filter hook.

function wporg_callback() {
    // do something
}
add_action( 'init', 'wporg_callback' );

Một ví dụ về init hook, thực tế chi tiết của Actions hook thì series của anh Thạch Phạm đã nêu khá rõ rồi, Nam sẽ lướt qua để đỡ mất thời gian

Gia tăng hiệu năng bằng việc gỡ các hooks không cần thiết

Đây là một ví dụ khá hay và phù hợp với việc phát triển WordPress, hình dung bạn muốn gỡ một function nặng (như slider chẳng hạn) vì giao diện hiện tại không dùng đến, lúc này bạn sẽ sử dụng hàm

  • remove_action
  • remove_filter
function wporg_disable_slider() {
	// Make sure all parameters match the add_action() call exactly.
	remove_action( 'template_redirect', 'wporg_setup_slider', 9 );
}
// Make sure we call remove_action() after add_action() has been called.
add_action( 'after_setup_theme', 'wporg_disable_slider' );

Việc gỡ bỏ các hàm không cần thiết sẽ giúp cho hiệu năng Website WordPress của bạn trở nên tối ưu hơn.

Xác định điều kiện để chạy logic theo từng hooks

function wporg_modify_content( $content ) {
	switch ( current_filter() ) {
		case 'the_content':
			// Do something.
			break;
		case 'the_excerpt':
			// Do something.
			break;
	}
	return $content;
}

add_filter( 'the_content', 'wporg_modify_content' );
add_filter( 'the_excerpt', 'wporg_modify_content' );

Khi chạy add_filter vào 2 hàm the_content và the_excerpt (Nội dung và tóm tắt bài viết), bạn có thể dùng hàm current_filter() để trả về hooks hiện hành và thực hiện các thay đổi theo điều kiện mong muốn.

Kiểm tra xem Hooks này đã chạy bao nhiêu lần

function wporg_custom() {
   // If save_post has been run more than once, skip the rest of the code.
   if ( did_action( 'save_post' ) !== 1 ) {
      return;
   }
   // ...
}
add_action( 'save_post', 'wporg_custom' );

Đây là đoạn mã khá hay với đoạn did_action(‘tên hook’), bạn có thể giới hạn số lần hook này chạy.

Custom Hook: Tự tạo hooks cho riêng mình

Để thực hiện việc này chúng ta sử dụng hàm do_action và apply_filters, trong đó do_action là để tạo action hook mới còn apply_filters để tạo filters hook mới (Sẽ được tin dùng nhất khi in các dữ liệu ra trình duyệt)

Ví dụ cụ thể: tạo action hook ở vị trí mong muốn

Giả dụ trong 1 file nào đó của plugin, bạn muốn bổ sung vị trí action hook nhằm chèn một thông báo chẳng hạn, lúc này bạn dùng hàm

do_action( 'wporg_after_settings_page_html' );

Lúc này bạn có thể dễ dàng đẩy vào callback function mong muốn

add_action( 'wporg_after_settings_page_html', 'myprefix_add_settings' );
function myprefix_add_settings() {
echo "Xin chào";
}

Ví dụ cụ thể: tạo tham số để lọc với custom post type

function wporg_create_post_type() {
    $post_type_params = [/* ... */];

    register_post_type(
        'post_type_slug',
        apply_filters( 'wporg_post_type_params', $post_type_params )
    );
}

Trong quá trình đăng ký post type sẽ tạo 1 filters hook tên là ‘wporg_post_type_params’, lưu ý là filter hook có đặc tính như sau

Note that filters filters take data, modify it, and return it.

WordPress handbook

Tức là lúc này filters wporg_post_type_params sẽ trả về giá trị mong muốn vào biến $post_type_params (tham số của custom post type)

function myprefix_change_post_type_params( $post_type_params ) {
	$post_type_params['hierarchical'] = true;
	return $post_type_params;
}
add_filter( 'wporg_post_type_params', 'myprefix_change_post_type_params' );

Sau khi chạy hàm myprefix_change_post_type_params, $post_type_params sẽ được trả về khi kết thúc hàm wporg_post_type_params

Filter Hook là gì?

Filters are one of the two types of Hooks.
They provide a way for functions to modify data during the execution of WordPress Core, plugins, and themes. They are the counterpart to Actions.
Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. Filters expect to have something returned back to them.

WordPress Plugin Handbook

Như vậy filters sẽ lấy dữ liệu, xử lý và trả về ngay trong quá trình chạy của WordPress Core, plugins và themes.

Ví dụ của filter, bổ sung tiêu đề cho biến $title có sẵn

function wporg_filter_title( $title ) {
	return 'The ' . $title . ' was filtered';
}
add_filter( 'the_title', 'wporg_filter_title' );

Đây là ví dụ của hàm wporg_filter_title($title), ngoài ra, ta có thể bổ sung các biến và tham số vào các thành phần có sẵn của WordPress

function wporg_css_body_class( $classes ) {
	if ( ! is_admin() ) {
		$classes[] = 'wporg-is-awesome';
	}
	return $classes;
}
add_filter( 'body_class', 'wporg_css_body_class' );

Như ở ví dụ trên thì ta đã ghép vào hook body_class một phần tử là wporg-is-awesome, nhưng chỉ dành riêng cho người đăng nhập thôi

Cách sử dụng action và filter hook với Woocommerce

Như rất nhiều WordPress plugins khác, Woocommerce cung cấp rất nhiều hook để người dùng có thể phát triển và mở rộng nền tảng.

Việc sử dụng lại các hook có sẵn luôn được khuyến khích, nếu tạo mới hook, bạn cần có sự suy nghĩ về lâu dài.

Sử dụng Lifecycle hook

Hẳn bạn sẽ không còn xa lạ với cách thức phát triển WordPress sử dụng các action hook để làm giàu nội dung cho các vị trí có sẵn, ví dụ trong màn sản phẩm chi tiết, bạn muốn đẩy một cái banner giảm giá vào hook woocommerce_single_product_summary chẳng hạn, lúc này bạn chỉ cần chèn 1 hàm call back vào action hook đó

Một số vị trí mà Lifecycle hook thường hiện diện đó là:

  • Vòng lặp sản phẩm (Product loop)
  • Nội dung email
  • Render một loại nội dung
  • Sản phẩm hoặc đơn hàng khi thay đổi trạng thái

Về mặt đặc tính, lifecycle hooks

  • Thường đi theo cặp (before và after…)
  • Luôn là action hook (Chương trình vẫn xử lý, Action hook dù không chạy cũng không ảnh hưởng đến logic của hàm)

Dưới đây là một ví dụ của Lifecycle hook khi nó đặt trong 1 hàm hiển thị khuyến mại

		function woocommerce_get_current_promotions( ...$args ) {
    /* Any initial prep, then first lifecycle hook... */
    do_action( 'woocommerce_before_get_current_promotions', $args );
    /* ...Do actual work, then final lifecycle hook... */
    do_action( 'woocommerce_after_get_current_promotions', $result, $args );
    /* ...Return the result, optionally via a filter... */
    return apply_filters( 'woocommerce_get_current_promotions', $result, $args );
}

	

Ta thấy chúng trả về 2 hooks

  • woocommerce_before_get_current_promotions
  • woocommerce_after_get_current_promotions

Trong đó hàm after trả về cả một biến kết quả cùng tham số $result và $args.

The ‘before’ hook will generally always provide callbacks with the arguments array, if there is one
The ‘after’ hook will generally also provide callbacks with the function’s return value, if there is one

Woocommerce Developer Handbook

Sử dụng Escape Hook

Escape hook là việc để cho hàm dừng xử lý ngay tại thời điểm đó, khi mà bạn đã chắc chắn mình chỉ cần những tính năng như vậy thôi.

  • Escape Hooks luôn là filters (nhận dữ liệu, xử lý và trả về)
  • Luôn đảm bảo null-safety (định nghĩa điều kiện null để tránh gây lỗi)
		function get_product_metrics( $args ): array {
    $pre = apply_filters( 'pre_woocommerce_get_product_metrics', null, $args );

    if ( $pre !== null ) {
        return (array) $pre;
    }

    /* ...Default logic... */
    return $metrics;
}