In this tutorial, I'll walk through creating a complete home style search wizard for a construction company website using WordPress REST API. This solution handles form submissions, file uploads, email notifications, and includes proper security measures.
Overview
We'll build:
A multi-step search wizard frontend
Secure REST API endpoints
File upload handling
Email notification system
Comprehensive logging
Step 1: Setting Up the REST API Endpoint
First, we register our custom endpoint:
add_action('rest_api_init', function () {
register_rest_route('fox-api/v1', '/send-search-data', [
'methods' => 'POST',
'callback' => 'handle_search_data',
'permission_callback' => function($request) {
$nonce = $request->get_header('X-WP-Nonce');
return wp_verify_nonce($nonce, 'wp_rest');
}
]);
});
Key security features:
Nonce verification for all requests
Proper route namespace (fox-api/v1)
POST method only
Step 2: Handling Form Submissions
Our handler function processes the data:
function handle_search_data(WP_REST_Request $request) {
try {
// Verify nonce
if (!wp_verify_nonce($request->get_header('X-WP-Nonce'), 'wp_rest')) {
return new WP_REST_Response(['error' => 'Invalid token'], 403);
}
$data = $request->get_params();
$files = $request->get_file_params();
// Process data and files...
return new WP_REST_Response(['success' => true]);
} catch (Exception $e) {
return new WP_REST_Response(['error' => $e->getMessage()], 500);
}
}
Step 3: File Upload Handling
Secure file upload implementation:
if (!empty($files['survey_file'])) {
require_once(ABSPATH . 'wp-admin/includes/file.php');
$upload = wp_handle_upload($files['survey_file'], [
'test_form' => false,
'mimes' => [
'pdf' => 'application/pdf',
'dwg' => 'application/acad',
'dxf' => 'application/dxf',
'jpg|jpeg' => 'image/jpeg',
'png' => 'image/png'
]
]);
if ($upload && !isset($upload['error'])) {
// Create attachment post
$attachment_id = wp_insert_attachment([
'post_mime_type' => $upload['type'],
'post_title' => sanitize_file_name($files['survey_file']['name']),
'post_status' => 'inherit'
], $upload['file']);
}
}
Key points:
Uses WordPress's secure file handling
Restricts allowed file types
Creates proper media library attachments
Step 4: Email Notifications
Here's our email function:
function send_data_to_email($submission_data) {
$to = get_option('admin_email');
$subject = 'New Home Style Search Submission';
$body = "<h2>New Submission Details</h2>";
$body .= "<p><strong>Date:</strong> " . date('F j, Y g:i a') . "</p>";
// Build email content from submission data
foreach ($submission_data as $section => $values) {
$body .= "<h3>" . ucfirst($section) . "</h3>";
if (is_array($values)) {
$body .= "<ul>";
foreach ($values as $value) {
$body .= "<li>" . esc_html($value) . "</li>";
}
$body .= "</ul>";
} else {
$body .= "<p>" . esc_html($values) . "</p>";
}
}
$headers = [
'Content-Type: text/html; charset=UTF-8',
'From: Website <noreply@' . $_SERVER['HTTP_HOST'] . '>'
];
return wp_mail($to, $subject, $body, $headers);
}
Features:
HTML formatted emails
Automatic content generation
Proper escaping of all output
Step 5: Frontend Implementation
JavaScript to handle the form submission:
async function submitForm() {
const formData = new FormData();
// Add form data
formData.append('styles', JSON.stringify(selectedStyles));
// Add other fields...
try {
const response = await fetch(foxApiSettings.root + 'fox-api/v1/send-search-data', {
method: 'POST',
headers: {
'X-WP-Nonce': foxApiSettings.nonce
},
body: formData
});
if (!response.ok) throw new Error('Submission failed');
const data = await response.json();
// Handle success
} catch (error) {
console.error('Error:', error);
// Show error to user
}
}
Security Considerations
Nonce Verification:
Required for all API requests
Prevents CSRF attacks
Works for both authenticated and non-authenticated users
Input Validation:
Validate all incoming data
Sanitize before processing
File Upload Security:
Restrict allowed file types
Use WordPress's built-in handlers
Store files outside web root when possible
Performance Optimizations
Logging System:
$log_dir = WP_CONTENT_DIR . '/fox-search-logs';
if (!file_exists($log_dir)) wp_mkdir_p($log_dir);
file_put_contents(
$log_dir . '/search_' . date('Y-m-d') . '.log',
print_r($data, true),
FILE_APPEND
);
Caching:
Cache API responses when appropriate
Consider transient for frequently accessed data
Conclusion
This implementation provides a complete solution for:
Multi-step form handling
Secure file uploads
Email notifications
Comprehensive logging
REST API best practices
The system is flexible enough to adapt to various use cases while maintaining security and performance standards.
Top comments (0)