Hiển thị random widget trên sidebar

Cập nhật lần cuối vào

Nếu bạn đang tìm cách hiển thị các widget theo kiểu random hoặc hiển thị random chỉ một widget trên sidebar nào đó thì bạn hoàn toàn có thể áp dụng code. Cách đơn giản và hoàn chỉnh nhất vẫn là sử dụng bộ lọc sidebars_widgets do WordPress hỗ trợ.

Hiển thị random tất cả các widget

Đoạn code bên dưới chúng ta sẽ áp dụng bộ lọc sidebars_widgets để đảo lại thứ tự của tất cả các widget trong sidebar rồi trả về đúng số lượng các widget.

function hocwp_theme_custom_sidebars_widgets_filter( $sidebars_widgets ) {
	$sidebars = array(
		'after_category_recent_post'
	);
	foreach ( $sidebars as $sidebar_index ) {
		if ( isset( $sidebars_widgets[ $sidebar_index ] ) ) {
			shuffle( $sidebars_widgets[ $sidebar_index ] );
		}
	}

	return $sidebars_widgets;
}

add_filter( 'sidebars_widgets', 'hocwp_theme_custom_sidebars_widgets_filter' );

Ở đoạn code bên trên thì biến $sidebars sẽ chứa tất cả các sidebar mà bạn muốn tùy chỉnh, nếu như bạn chỉ muốn thao tác trên 1 sidebar nào đó thì bạn bỏ biến này và bỏ luôn vòng lặp foreach, tạo biến $sidebar_index là id sidebar mà bạn muốn hiển thị random widget.

Hiển thị random 1 widget

Bằng cách chỉnh sửa lại một chút đoạn code ở ví dụ 1 bên trên thì chúng ta sẽ cho hiển thị chỉ có 1 widget ra bên ngoài mà thôi.

function hocwp_theme_custom_sidebars_widgets_filter( $sidebars_widgets ) {
	$sidebars = array(
		'after_category_recent_post'
	);
	foreach ( $sidebars as $sidebar_index ) {
		if ( isset( $sidebars_widgets[ $sidebar_index ] ) ) {
			shuffle( $sidebars_widgets[ $sidebar_index ] );
			$sidebars_widgets[ $sidebar_index ] = array_slice( $sidebars_widgets[ $sidebar_index ], 0, 1 );
		}
	}

	return $sidebars_widgets;
}

add_filter( 'sidebars_widgets', 'hocwp_theme_custom_sidebars_widgets_filter' );

Sau khi đả đảo thứ tự các widget lại bằng hàm shuffle thì bạn chỉ việc lấy ra 1 widget bất kỳ ở đầu hoặc ở cuối hoặc lấy ở vị trí nào cũng được.

Hiển thị random widget bằng cách viết làm hàm của WordPress

Cách viết lại hàm này chỉ sử dụng khi mà bạn không còn cách nào khác để thay thế, trong trường hợp này mình khuyên các bạn nên dùng bộ lọc thay vì viết lại hàm.

function hocwp_dynamic_sidebar_random_widget( $index = 1 ) {
	global $wp_registered_sidebars, $wp_registered_widgets;

	if ( is_int( $index ) ) {
		$index = "sidebar-$index";
	} else {
		$index = sanitize_title( $index );
		foreach ( (array) $wp_registered_sidebars as $key => $value ) {
			if ( sanitize_title( $value['name'] ) == $index ) {
				$index = $key;
				break;
			}
		}
	}

	$sidebars_widgets = wp_get_sidebars_widgets();
	if ( empty( $wp_registered_sidebars[ $index ] ) || empty( $sidebars_widgets[ $index ] ) || ! is_array( $sidebars_widgets[ $index ] ) ) {
		/** This action is documented in wp-includes/widget.php */
		do_action( 'dynamic_sidebar_before', $index, false );
		/** This action is documented in wp-includes/widget.php */
		do_action( 'dynamic_sidebar_after', $index, false );

		/** This filter is documented in wp-includes/widget.php */

		return apply_filters( 'dynamic_sidebar_has_widgets', false, $index );
	}

	/**
	 * Fires before widgets are rendered in a dynamic sidebar.
	 *
	 * Note: The action also fires for empty sidebars, and on both the front end
	 * and back end, including the Inactive Widgets sidebar on the Widgets screen.
	 *
	 * @since 3.9.0
	 *
	 * @param int|string $index Index, name, or ID of the dynamic sidebar.
	 * @param bool $has_widgets Whether the sidebar is populated with widgets.
	 *                                Default true.
	 */
	do_action( 'dynamic_sidebar_before', $index, true );
	$sidebar = $wp_registered_sidebars[ $index ];

	$did_one    = false;
	$my_widgets = (array) $sidebars_widgets[ $index ];
	$count_wg   = count( $my_widgets );
	$key        = array_rand( $my_widgets );
	$id         = $my_widgets[ $key ];
	$count      = 0;
	while ( ! isset( $wp_registered_widgets[ $id ] ) && $count < $count_wg ) {
		$id = array_rand( $my_widgets );
		$count ++;
	}
	$params = array_merge(
		array(
			array_merge( $sidebar, array(
				'widget_id'   => $id,
				'widget_name' => $wp_registered_widgets[ $id ]['name']
			) )
		),
		(array) $wp_registered_widgets[ $id ]['params']
	);

	// Substitute HTML id and class attributes into before_widget
	$classname_ = '';
	foreach ( (array) $wp_registered_widgets[ $id ]['classname'] as $cn ) {
		if ( is_string( $cn ) ) {
			$classname_ .= '_' . $cn;
		} elseif ( is_object( $cn ) ) {
			$classname_ .= '_' . get_class( $cn );
		}
	}
	$classname_                 = ltrim( $classname_, '_' );
	$params[0]['before_widget'] = sprintf( $params[0]['before_widget'], $id, $classname_ );

	/**
	 * Filters the parameters passed to a widget's display callback.
	 *
	 * Note: The filter is evaluated on both the front end and back end,
	 * including for the Inactive Widgets sidebar on the Widgets screen.
	 *
	 * @since 2.5.0
	 *
	 * @see register_sidebar()
	 *
	 * @param array $params {
	 *
	 * @type array $args {
	 *         An array of widget display arguments.
	 *
	 * @type string $name Name of the sidebar the widget is assigned to.
	 * @type string $id ID of the sidebar the widget is assigned to.
	 * @type string $description The sidebar description.
	 * @type string $class CSS class applied to the sidebar container.
	 * @type string $before_widget HTML markup to prepend to each widget in the sidebar.
	 * @type string $after_widget HTML markup to append to each widget in the sidebar.
	 * @type string $before_title HTML markup to prepend to the widget title when displayed.
	 * @type string $after_title HTML markup to append to the widget title when displayed.
	 * @type string $widget_id ID of the widget.
	 * @type string $widget_name Name of the widget.
	 *     }
	 * @type array $widget_args {
	 *         An array of multi-widget arguments.
	 *
	 * @type int $number Number increment used for multiples of the same widget.
	 *     }
	 * }
	 */
	$params = apply_filters( 'dynamic_sidebar_params', $params );

	$callback = $wp_registered_widgets[ $id ]['callback'];

	/**
	 * Fires before a widget's display callback is called.
	 *
	 * Note: The action fires on both the front end and back end, including
	 * for widgets in the Inactive Widgets sidebar on the Widgets screen.
	 *
	 * The action is not fired for empty sidebars.
	 *
	 * @since 3.0.0
	 *
	 * @param array $widget_id {
	 *     An associative array of widget arguments.
	 *
	 * @type string $name Name of the widget.
	 * @type string $id Widget ID.
	 * @type array|callable $callback When the hook is fired on the front end, $callback is an array
	 *                                       containing the widget object. Fired on the back end, $callback
	 *                                       is 'wp_widget_control', see $_callback.
	 * @type array $params An associative array of multi-widget arguments.
	 * @type string $classname CSS class applied to the widget container.
	 * @type string $description The widget description.
	 * @type array $_callback When the hook is fired on the back end, $_callback is populated
	 *                                       with an array containing the widget object, see $callback.
	 * }
	 */
	do_action( 'dynamic_sidebar', $wp_registered_widgets[ $id ] );

	if ( is_callable( $callback ) ) {
		call_user_func_array( $callback, $params );
		$did_one = true;
	}

	/**
	 * Fires after widgets are rendered in a dynamic sidebar.
	 *
	 * Note: The action also fires for empty sidebars, and on both the front end
	 * and back end, including the Inactive Widgets sidebar on the Widgets screen.
	 *
	 * @since 3.9.0
	 *
	 * @param int|string $index Index, name, or ID of the dynamic sidebar.
	 * @param bool $has_widgets Whether the sidebar is populated with widgets.
	 *                                Default true.
	 */
	do_action( 'dynamic_sidebar_after', $index, true );

	/**
	 * Filters whether a sidebar has widgets.
	 *
	 * Note: The filter is also evaluated for empty sidebars, and on both the front end
	 * and back end, including the Inactive Widgets sidebar on the Widgets screen.
	 *
	 * @since 3.9.0
	 *
	 * @param bool $did_one Whether at least one widget was rendered in the sidebar.
	 *                            Default false.
	 * @param int|string $index Index, name, or ID of the dynamic sidebar.
	 */

	return apply_filters( 'dynamic_sidebar_has_widgets', $did_one, $index );
}

Như trong ví dụ bên trên mình viết lại, chỉnh sửa cách hoạt động của hàm dynamic_sidebar trong bộ nhân của WordPress. Cách này vẫn hoạt động bình thường nhưng chỉ tương thích cho tới khi WordPress cập nhật lại cách hoạt động của hàm mà bạn chỉnh sửa, do vậy trong tương lai khi mà WordPress thay đổi hàm thì rất có thể hàm của bạn sẽ không hoạt động và bạn cũng sẽ phải viết lại để hàm tương thích với WordPress mới tốt hơn.

Theo dõi
Thông báo của
guest

3 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất
Phản hồi nội tuyến
Xem tất cả bình luận
Minh Khánh
5 năm trước

Ko có demo hay hình ảnh cho dễ hình dung, hix

Minh Khánh
5 năm trước

vâng, nhưng có demo hay ảnh vẫn tốt hơn cho người xem