WordPress

ajax — Dane formularza API REST WordPress: Formularz nie został przesłany, gdy nie załączono żadnych plików

  • 10 kwietnia, 2024
  • 6 min read
ajax — Dane formularza API REST WordPress: Formularz nie został przesłany, gdy nie załączono żadnych plików


Piszę wtyczkę, aby wyświetlić niestandardowy formularz w interfejsie użytkownika. Formularz zawiera różne pola wejściowe (głównie tekst) i jedno wejście wielu plików.

Przesyłanie wysyła dane za pośrednictwem wywołania ajax do punktu końcowego interfejsu API odpoczynku. Wszystko jest w porządku, dopóki nie prześlę plików: formularz zostanie przesłany, a funkcja wywołania zwrotnego punktu końcowego zapisuje dane w MyQSql. Jeśli jednak spróbuję przesłać formularz bez przesyłania żadnego pliku (pole nie jest obowiązkowe), pojawia się komunikat o błędzie „Wystąpił błąd podczas przesyłania formularza” (jest drukowany, jeśli wywołanie ajax nie działa).

Co ja robię źle?

Oto mój kod

<form id= "idp_sight_form" action="" method="post" enctype="multipart/form-data">

<?php
wp_nonce_field('wp_rest'); ?>
<div class="form-body">
    <div class="full-field">                  
        <input type="text" id="first_name" name="first_name" placeholder="First Name" >
    </div>   
    <div class="full-field">                  
        <input type="text" id="last_name" name="last_name" placeholder="Last Name" >
    </div> 
    <div class="full-field">
        <label for="imageUpload">Choose a maximum of 3 images to upload (jpg, png - size < 5MB):</label><br/>
        <div id="drop-area">
        <span class="drop-text">Drag and drop files here or click to browse</span>
        <input type="file" id="file-input" name="file-input[]" accept=".jpg, .png" multiple style="display: none;">
        </div>
        <div id="file-list"></div>
        <span id="fileError" style="color: red;"></span><br/>
    </div>
</div> 
<div class="form-footer">   
    <input id="submit-form" type="submit" name="submit" value="Submit">
</div><!--closes form-footer-->
</form>

<script>
//Function to send form to rest_api
jQuery(document).ready(function($) {
    $("#idp_sight_form").submit(function(event) 
        {
            event.preventDefault();
            var form = $(this);
            formParam = form.serialize();        
            var ajaxFiles = new FormData(this);
         // Listen for file selection change event
         $('#file-input').on('change', function() {
                handleFiles($(this)[0].files);
            });
            // Get the drop area element
            var dropArea = document.getElementById('drop-area');
            // Prevent default behavior when files are dragged over the drop area
            dropArea.addEventListener('dragover', function(e) {
                e.preventDefault();
            }, false);
            // Handle dropped files
            dropArea.addEventListener('drop', function(e) {
                e.preventDefault();
            }, false);
            // Function to handle files
            function handleFiles(files) {
                // Loop through files
                for (var i = 0; i < files.length; i++) {
                    var file = files[i];                    
                    ajaxFiles.append('file-input[]', file); // Append each file to FormData
                }
            }
           // Append form data to FormData
            ajaxFiles.append('form_data', formParam);

                // Check if any files are uploaded
                var filesUploaded = false;
                for (var pair of ajaxFiles.entries()) {
                    if (pair[0] === 'file-input[]' && pair[1].name) {
                        filesUploaded = true;
                        break;
                    }
                }
            // Check if any files are uploaded
            if (filesUploaded) {
                $.ajax({
                    url:"<?php echo get_rest_url(null, 'sight-form-tethys/v1/register_data'); ?>",
                    type: "POST",
                    data: ajaxFiles,
                    processData: false,
                    contentType: false,
                    success: function(res) {
                        //grabbing the response as res uses the WP_Rest_Response written in the handler of the rest api
                        form.hide();
                        $("#form-success").html(res).fadeIn();
                    },
                    error: function() {
                        form.hide();
                        $("#form-error").html("There was an error submitting your form").fadeIn();
                    }
                })
            } else {
                // If no files are uploaded, submit the form without files
                $.ajax({
                    url: "<?php echo get_rest_url(null, 'sight-form-tethys/v1/register_data'); ?>",
                    type: "POST",
                    data: formParam,
                    success: function(res) {
                        form.hide();
                        $("#form-success").html(res).fadeIn();
                    },
                    error: function() {
                        form.hide();
                        $("#form-error").html("There was an error submitting your form").fadeIn();
                    }
                });               
            }

        })        
        
});
</script> 

a poniżej znajduje się funkcja wywołania zwrotnego zarejestrowana w punkcie końcowym

public function register_data_function($data){  
    // Handle file uploads
    $params = $data->get_params();
    $wp_nonce = $params['_wpnonce'];

    if($params['form_data']) {
        parse_str($params['form_data'], $form_data_array);
        $files_data = $data->get_file_params();
        $wp_nonce = $form_data_array['_wpnonce'];
    }
            
    if(!wp_verify_nonce($wp_nonce, 'wp_rest')){

        return new WP_Rest_Response(array('message' => 'Form not submitted'), 401);
        
    }       
    //check for a folder where to store images
    global $wp_filesystem;
    // It is a WordPress core file, that's why we manually include it 
    require_once ( ABSPATH . '/wp-admin/includes/file.php' );   
    //Just instantiate as follows 
    WP_Filesystem();
    $files_folder = WP_CONTENT_DIR .'/sighting-form-images';
    if(!file_exists($files_folder)){
        mkdir($files_folder, 0755, true);
    }
    $uploaded_files = [];
    
    // Check if there are any files uploaded
    if (!empty($files_data)) {

        // Iterate over each file input field
        foreach ($files_data as $file_input) {
            // Iterate over each file in the input field
            foreach ($file_input['tmp_name'] as $index => $tmp_name) {
                // Validate file type (ensure it's an image)
                $mime_type = mime_content_type($tmp_name);
                $file_type = sanitize_mime_type($mime_type);
                if (strpos($file_type, 'image') === false) {
                    // If the file is not an image, skip it and return an error response
                    return new WP_Rest_Response(array('message' => 'Only image files are allowed'), 400);
                }
                // Construct unique file path (append index to filename if necessary)
                $file_name = sanitize_file_name($file_input['name'][$index]);
                $file_extension = pathinfo($file_name, PATHINFO_EXTENSION);
                $file_base_name = pathinfo($file_name, PATHINFO_FILENAME);
                $counter = 0;
                $new_file_name = $file_name;
                while (file_exists($files_folder . " . $new_file_name)) {
                    $counter++;
                    $new_file_name = $file_base_name . '_' . $counter . '.' . $file_extension;
                }
                $file_path = $files_folder . " . $new_file_name;

                // Move the uploaded file to the destination folder
                if (move_uploaded_file($tmp_name, $file_path)) {
                    
                    // File moved successfully
                
                    $file_url = site_url('/wp-content/sighting-form-images/') . $new_file_name;
                    //$uploaded_files[] = $file_path;
                    $uploaded_files[] = $file_url; 
                } else {
                    // Error handling if file move fails
                    return new WP_Rest_Response(array('message' => 'Failed to move file'), 500);
                }

                
            }
        }
        $fileUrl = implode(';', $uploaded_files);
    } else { 
        // Handle if no files are uploaded
        return new WP_Rest_Response(array('message' => 'No files uploaded'), 400);
    }

    //I unset the parameters I don't need in the response

    unset($form_data_array['_wpnonce']);
    unset($form_data_array['_wp_http_referer']);

    global $wpdb;
    $table_name = $wpdb->prefix . 'sight_form_data';
    
    $data_array = array(
        'first_name' => sanitize_text_field($form_data_array['first_name']),
        'last_name' => sanitize_text_field($form_data_array['last_name']),
        'fileUrl' => sanitize_text_field($fileUrl)

    );
    //file_put_contents($files_folder. '/somefile.txt', print_r($data_array, true), FILE_APPEND);
    $result = $wpdb->insert($table_name, $data_array);
    //file_put_contents($files_folder. '/somefile.txt', print_r($result, true), FILE_APPEND);

    // Check for errors
    if ($result === false) {
        // There was an error inserting data, print out the error for debugging
        return new WP_Rest_Response(array('Error saving data'), 200);
    } 
    return new WP_Rest_Response(array('Your form has been submitted succesfully'), 200);
}


Źródło

Warto przeczytać!  5 powodów, dla których WPBeginner przeszedł z Sucuri na Cloudflare