| name | ajax-handler |
| description | Create AJAX handlers for WordPress admin and frontend. Use when handling asynchronous requests from JavaScript, form submissions, or dynamic content loading. |
AJAX Handler
Create AJAX handlers for admin and frontend requests.
Create Handler
File: includes/ajax/class-form-handler.php
<?php
namespace WPPB\Ajax;
use WPPB\Core\Hooker;
defined( 'ABSPATH' ) || exit;
class FormHandler {
private Hooker $hooker;
public function __construct( Hooker $hooker ) {
$this->hooker = $hooker;
}
public function init(): void {
$this->hooker->add_action(
'wp_ajax_wppb_submit_form',
$this,
'handle_submit'
);
$this->hooker->add_action(
'wp_ajax_nopriv_wppb_submit_form',
$this,
'handle_submit'
);
}
public function handle_submit(): void {
if ( ! check_ajax_referer( 'wppb_form_nonce', 'nonce', false ) ) {
wp_send_json_error(
array(
'message' => __( 'Invalid nonce', '__PLUGIN_TEXTDOMAIN__' ),
),
403
);
}
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error(
array(
'message' => __( 'Permission denied', '__PLUGIN_TEXTDOMAIN__' ),
),
403
);
}
$name = isset( $_POST['name'] ) ? sanitize_text_field( $_POST['name'] ) : '';
$email = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : '';
if ( empty( $name ) || empty( $email ) ) {
wp_send_json_error(
array(
'message' => __( 'Required fields missing', '__PLUGIN_TEXTDOMAIN__' ),
),
400
);
}
$result = $this->process_form( $name, $email );
if ( ! $result ) {
wp_send_json_error(
array(
'message' => __( 'Processing failed', '__PLUGIN_TEXTDOMAIN__' ),
),
500
);
}
wp_send_json_success(
array(
'message' => __( 'Form submitted', '__PLUGIN_TEXTDOMAIN__' ),
'data' => $result,
)
);
}
private function process_form( string $name, string $email ) {
return array(
'id' => 123,
'name' => $name,
);
}
}
Frontend JavaScript
jQuery( document ).ready( function( $ ) {
$( '#my-form' ).on( 'submit', function( e ) {
e.preventDefault();
$.ajax( {
url: wppbData.ajaxUrl,
type: 'POST',
data: {
action: 'wppb_submit_form',
nonce: wppbData.nonce,
name: $( '#name' ).val(),
email: $( '#email' ).val()
},
success: function( response ) {
if ( response.success ) {
console.log( response.data.message );
} else {
console.error( response.data.message );
}
},
error: function( xhr ) {
console.error( 'AJAX error' );
}
} );
} );
} );
Localize Script
$this->assets->localize_script(
'wppb-main',
'wppbData',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'wppb_form_nonce' ),
)
);
Admin Only Handler
public function init(): void {
$this->hooker->add_action(
'wp_ajax_wppb_admin_action',
$this,
'handle_admin_action'
);
}
Public Handler
public function init(): void {
$this->hooker->add_actions(
$this,
array(
'wp_ajax_wppb_public_action',
'wp_ajax_nopriv_wppb_public_action',
)
);
}
public function wp_ajax_wppb_public_action(): void {
}
public function wp_ajax_nopriv_wppb_public_action(): void {
$this->wp_ajax_wppb_public_action();
}
Response Methods
Success
wp_send_json_success(
array(
'message' => __( 'Success', '__PLUGIN_TEXTDOMAIN__' ),
'data' => $data,
)
);
Error
wp_send_json_error(
array(
'message' => __( 'Error', '__PLUGIN_TEXTDOMAIN__' ),
),
400
);
Custom JSON
wp_send_json(
array(
'custom' => 'response',
),
200
);
Register in Service Provider
<?php
namespace WPPB\Providers;
use WPPB\Abstracts\AbstractServiceProvider;
use WPPB\Ajax\FormHandler;
class AjaxServiceProvider extends AbstractServiceProvider {
public function register(): void {
$this->singleton(
'ajax.form',
FormHandler::class
);
}
public function boot(): void {
$this->container->get( 'ajax.form' )->init();
}
}
Security Checklist
Rules
- Create handlers in
includes/ajax/
- Use
wp_ajax_{action} for logged-in users
- Use
wp_ajax_nopriv_{action} for non-logged-in users
- Always verify nonce
- Always check permissions
- Sanitize all input
- Use wp_send_json_success/error
- Localize ajaxUrl and nonce
- Action name must match JavaScript