钩子文档

admin_post_{$action}

💡 云策文档标注

概述

admin_post_{$action} 是一个 WordPress 动态 Hook,用于处理经过身份验证的管理员 POST 请求中的自定义操作。它允许开发者创建自定义的 GET 或 POST 请求处理器,基于请求参数中的 'action' 值触发特定函数。

关键要点

  • 这是一个动态 Hook,名称格式为 admin_post_$action,其中 $action 对应请求中的 'action' 参数。
  • 用于处理自定义的 GET 或 POST 请求,例如表单提交或 AJAX 调用。
  • 需要配合 add_action() 注册处理函数,函数内应处理请求并生成响应,通常使用 exit() 结束。
  • 对于未登录用户,可以使用 admin_post_nopriv_$action Hook 来处理请求。
  • 请求数据可通过 $_GET、$_POST 或 $_REQUEST 数组访问。

代码示例

add_action( 'admin_post_add_foobar', 'prefix_admin_add_foobar' );
add_action( 'admin_post_nopriv_add_foobar', 'prefix_admin_add_foobar' );

function prefix_admin_add_foobar() {
    status_header(200);
    exit("Server received '{$_REQUEST['data']}' from your browser.");
}

注意事项

  • 处理函数应使用 exit() 或 die() 来结束执行,避免后续输出干扰。
  • 确保安全措施,如验证 nonce 和权限检查,特别是在处理敏感操作时。
  • Hook 名称必须与请求中的 'action' 参数完全匹配,包括大小写。

📄 原文内容

Fires on an authenticated admin post request for the given action.

Description

The dynamic portion of the hook name, $action, refers to the given request action.

More Information

This hook allows you to create custom handlers for your own custom GET and POST requests. The admin_post_ hook follows the format “admin_post_$action“, where $action is your GET or POST request’s ‘action‘ parameter.

Usage:

If you needed to create a request or form handler for an “add_foobar” action request, you would create a hook like this:

add_action( 'admin_post_add_foobar', 'prefix_admin_add_foobar' );

function prefix_admin_add_foobar() {
// Handle request then generate response using echo or leaving PHP and using HTML
}

Using the above example, any time a GET or POST request is sent to WordPress, and the request’s ‘action‘ parameter is set to ‘add_foobar‘, this hook will be automatically executed. For example, the following HTML content would execute the above hook when the user clicks either Submit.

<br>
<a href="http://www.example.com/wp-admin/admin-post.php?action=add_foobar&data=foobarid">Submit</a><br>

<br>
<form action="http://www.example.com/wp-admin/admin-post.php" method="post"><br>
<input type="hidden" name="action" value="add_foobar"><br>
<input type="hidden" name="data" value="foobarid"><br>
<input type="submit" value="Submit"><br>
</form><br>

Note: The data value (foobarid) would be available in your hook function from the $_GET, $_POST or $_REQUEST array as is applicable.

Example:

This following example allows you to hook the GET or POST requests from the above html.

add_action( 'admin_post_add_foobar', 'prefix_admin_add_foobar' );

//this next action version allows users not logged in to submit requests
//if you want to have both logged in and not logged in users submitting, you have to add both actions!
add_action( 'admin_post_nopriv_add_foobar', 'prefix_admin_add_foobar' );

function prefix_admin_add_foobar() {
status_header(200);
//request handlers should exit() when they complete their task
exit("Server received '{$_REQUEST['data']}' from your browser.");
}

Source

do_action( "admin_post_{$action}" );

Changelog

Version Description
2.6.0 Introduced.

User Contributed Notes

  1. Skip to note 4 content

    <form action="">
    	<input type="hidden" name="action" value="generate_csv" />
    	<input type="submit" name="submit" class="button button-primary" value="Generate & Download CSV File" />
    </form>
    /**
     * Generate CSV File.
     */
    
    add_action( 'admin_post_generate_csv', 'lunchbox_generate_orders_csv' );
    function lunchbox_generate_orders_csv() {
    
    	global $wpdb;
    
    	$filename = 'lunchbox-orders';
    	$generatedDate = $generatedDate = date('d-m-Y His');
    
    	/**
    	 * output header so that file is downloaded
    	 * instead of open for reading.
    	 */
    	header("Pragma: public");
    	header("Expires: 0");
    	header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    	header("Cache-Control: private", false);
    	header('Content-Type: text/csv; charset=utf-8');
    	// header("Content-Type: application/octet-stream");
    	header("Content-Disposition: attachment; filename="" . $filename . " " . $generatedDate . ".csv";" );
    	// header('Content-Disposition: attachment; filename=lunchbox_orders.csv');
    	header("Content-Transfer-Encoding: binary");
    
    	/**
    	 * create a file pointer connected to the output stream
    	 * @var [type]
    	 */
    	$output = fopen('php://output', 'w');
    	$results = $wpdb->get_results( "SELECT * FROM $wpdb->posts WHERE post_type = 'shop_order'", ARRAY_A );
    
    	/**
    	 * output the column headings
    	 */
    	fputcsv( $output, array('Order ID', 'Order Title', 'Order Date'));
    
    	foreach ( $results as $key => $value ) {
    		// $array[] = '';
    		$modified_values = array( 
    			$value['ID'],
    			$value['post_title'],
    			$value['post_date']
    		);
    
    		fputcsv( $output, $modified_values );
    	}
    	return $output;
    }

  2. Skip to note 5 content

    This hook allows us to create our own handler for GET or POST request. for example we want to call a function when form is submitted, we can do this with the following code.

    <form action="http://www.example.com/wp-admin/admin-post.php" method="post"><br />
    <input type="hidden" name="action" value="our_action_hook"><br />
    <input type="submit" value="Submit"><br />
    </form>

    This will submit form on the following url
    http://www.example.com/wp-admin/admin-post.php?action=our_action_hook

    in our function.php we can call the hook as “admin_post_” followed by {$action}

    add_action( 'admin_post_our_action_hook', 'am_our_action_hook_function' );
    function am_our_action_hook_function() {
        // do something
    }

  3. Skip to note 6 content

    You can not submit a form from post edit page in admin area.
    You can add a button with url to admin-post.php and pass arg as http query like :

    $my_form_nonce = wp_create_nonce( 'my_form_nonce' );
    $get_data = http_build_query( array( 
        'my_form_nonce' => $my_form_nonce, 
        'action' => 'my_form_response', 
        'post_id' => $post->ID, 
    ) );
    
    $url = admin_url( 'admin-post.php' ) . '?' . $get_data;
    add an a tag with the href="$url". 

    Then in your admin_init add action like:

    add_action( 'admin_post_my_form_response', 'wpdocs_form_callback' );
    
    // callback function 
    
    function wpdocs_form_callback() {
    	// can access &_GET
    	// can check nonce 
    	// $post_id = $_GET['post_id'];
    }