Search code examples
jquerysqlajaxwordpressplugins

I'm getting "Bad request" using ajax in custom WordPress plugin


I am trying to create a form in my first WordPress app, but the moment I send the Post data using $.ajax() I get the error "Bad request".

Bad request received screenshot

I tried several solutions, even using Chat GTP, but I can't fix this error.

Any help will be really appreciated.

My JS code:

jQuery(document).ready(function($) {
    // Verificar si my_ajax_obj está definido
    if (typeof my_ajax_obj !== 'undefined') {
        console.log(my_ajax_obj);
        
        // Capturamos el evento submit del formulario
        $("#dhl_guias_form").on("submit", function(event) {
            event.preventDefault();
            
            // Serializamos los datos del formulario y los convertimos en JSON
            var formData =  $("#dhl_guias_form").serialize()

            console.log(formData);
    
         
            
      
          
            // Realizamos la solicitud POST utilizando $.ajax
            jQuery.ajax({

                type: "POST",
            
                url: my_ajax_obj.ajax_url,        
                
                data: formData,
                action: 'astral_save_form',
                beforesend: function(){
                    alert("hello");
                    console.log("ajax");                    
                    console.log(my_ajax_obj);
                    console.log(my_ajax_obj.ajax_url);
                },
                nonce: my_ajax_obj.nonce,
                
               
                success: function(response) {
                    // Éxito en la solicitud
                    console.log(response);
                    console.log("OK");
                },
                error: function(xhr, status, error) {
                    // Error en la solicitud
                    console.log(error);
                    console.log("error");
                }
            });
        });
    } else {
        console.log("my_ajax_obj no está definido");
    }
});

My PHP code:

<?php
/*
Plugin Name: Astral
Plugin URI: https://www.ejemplo.com
Description: Descripción del plugin.
Version: 1.0
Author: Tu Nombre
Author URI: https://www.tunombre.com
*/

// Activar el plugin
register_activation_hook(__FILE__, 'astral_plugin_activation');

function astral_plugin_activation() {
    // Código para activar el plugin
    global $wpdb;
    $table_name = $wpdb->prefix . 'dhl_guias'; // Nombre de la tabla
    $charset_collate = $wpdb->get_charset_collate();
    $sql = "CREATE TABLE $table_name (
        id INT NOT NULL AUTO_INCREMENT,
        nombre VARCHAR(100) NOT NULL,
        direccion VARCHAR(100) NOT NULL,
        PRIMARY KEY (id)
    ) $charset_collate;";
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
}

// Desactivar el plugin
register_deactivation_hook(__FILE__, 'astral_plugin_deactivation');

function astral_plugin_deactivation() {
    // Código para desactivar el plugin
}


function astral_create_menu() {
    add_menu_page(
        'Astral',               // Título de la Página
        'Astral Menu',          // Título del Menú
        'manage_options',       // Capability
        'astral-menu',          // Slug del Menú
        'astral_menu_callback', // Callback para mostrar el contenido del menú
        'dashicons-admin-generic', // Icono
        1                       // Posición del menú en el panel de administración
    );
}

add_action('admin_menu', 'astral_create_menu'); // Crear Menú

function astral_menu_callback() {
    // Código para mostrar el contenido del menú Astral
    include plugin_dir_path(__FILE__) . 'astral_visual.php';
}

add_action( 'admin_enqueue_scripts', 'my_enqueue' );
function my_enqueue( $hook ) {
   if ( 'toplevel_page_astral-menu' !== $hook ) {
      return;
   }

   wp_enqueue_script(
      'ajax-script',
      plugins_url( 'js/astral.js', __FILE__ ),
      array( 'jquery' ),
      
   );

   $title_nonce = wp_create_nonce( 'title_example' );
   wp_localize_script(
      'ajax-script',
      'my_ajax_obj',
      array(
         'ajax_url' => admin_url( 'admin-ajax.php' ),
         'nonce'    =>wp_create_nonce( 'nonce' )
         
      )
   );
}

add_action('wp_ajax_astral_save_form', 'astral_save_form');

function astral_save_form() {
    check_ajax_referer('astral_ajax_nonce', 'nonce'); // Verificar el nonce para mayor seguridad

    global $wpdb;
    $table_name = $wpdb->prefix . 'dhl_guias';

    $field1 = sanitize_text_field($_POST['field1']);
    $field2 = sanitize_text_field($_POST['field2']);

    $wpdb->insert(
        $table_name,
        array(
            'id' => NULL,
            'nombre' => $field1,
            'direccion' => $field2
        )
    );

    wp_die(); // Finaliza la ejecución de la solicitud AJAX
}

My form (astral_visual.php):

<form id="dhl_guias_form" method="POST">
    <input type="text" name="field1" placeholder="Campo 1" /><br>
    <input type="text" name="field2" placeholder="Campo 2" /><br> 
    <button type="submit" id="save" name="save">GUARDAR</button>
</form>

Solution

  • There are some mistakes and errors in your code.

    Note: As Stack Overflow is an English-speaking community, I have translated mostly everything.

    The PHP main plugin code:

    <?php
    /*
    Plugin Name: Astral
    Plugin URI: https://www.example.com
    Description: Plugin description.
    Version: 1.0
    Author: Your name
    Author URI: https://www.yourname.com
    */
    
    // Plugin activation - Create 'dhl_guias' table in database
    register_activation_hook(__FILE__, 'astral_plugin_activation');
    function astral_plugin_activation() {
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    
        global $wpdb;
        
        dbDelta("
            CREATE TABLE {$wpdb->prefix}dhl_guias (
            id INT NOT NULL AUTO_INCREMENT,
            nombre VARCHAR(100) NOT NULL,
            direccion VARCHAR(100) NOT NULL,
            PRIMARY KEY (id)
        ) {$wpdb->get_charset_collate()}");
    }
    
    // Plugin deactivation
    register_deactivation_hook(__FILE__, 'astral_plugin_deactivation');
    function astral_plugin_deactivation() {
        // your code
    }
    
    // Add a menu in the WordPress admin
    add_action('admin_menu', 'astral_create_menu'); 
    function astral_create_menu() {
        add_menu_page(
            'Astral',               // Page title
            'Astral Menu',          // Menu title
            'manage_options',       // Capability
            'astral-menu',          // Menu slug
            'astral_menu_callback', // The function to be called for content output
            'dashicons-admin-generic', // Icon
            1                       // Position in the Admin menu order
        );
    }
    
    // Function called by the menu
    function astral_menu_callback() {
        // Code to display the content (calling an external file)
        include plugin_dir_path(__FILE__) . 'astral_visual.php';
    }
    
    // Register JavaScript external files
    add_action( 'admin_enqueue_scripts', 'my_enqueue' );
    function my_enqueue( $hook ) {
       if ( 'toplevel_page_astral-menu' !== $hook ) {
          return;
       }
    
        wp_enqueue_script( 'astral-ajax-script', 
            plugins_url( 'js/astral.js', FILE ), 
            array( 'jquery' ),'1.0.0', true ); 
    
       wp_localize_script(
          'astral-ajax-script',
          'astral_params',
          array(
             'ajax_url' => admin_url( 'admin-ajax.php' ),
             'nonce'    => wp_create_nonce( 'astral_nonce' )
          )
       );
    }
    
    add_action('wp_ajax_astral_save_form', 'astral_save_form');
    function astral_save_form() {
        // Check the Ajax request to prevent external insecure requests
        check_ajax_referer('astral_nonce', 'security'); 
    
        global $wpdb;
    
        if( isset($_REQUEST['form_data'])) {
            $data = array(); // initializing
            parse_str($_REQUEST['form_data'], $data);  
    
            if( isset($data['fullname'])  && isset($data['address'])
            && ! empty($data['fullname']) && ! empty($data['address']) ) {
    
                // Inserting the some data in the database
                $wpdb->insert( "{$wpdb->prefix}dhl_guias",  array(
                    'id' => NULL,
                    'nombre' => sanitize_text_field($data['fullname']),
                    'direccion' => sanitize_text_field($data['address'])
                ) );
                echo "Success! The data has been saved to the database";
            } else {
                echo "Warning: Some form fields have not been filled";
            }
        } else {
            echo "Warning: The form data has not ben sent";
        }
        wp_die(); // End silently (mandatory)
    }
    

    The HTML form (added to astral_visual.php external file):

    <form id="dhl-guias" method="POST">
        <label for="fullname">Nombre completo:</label><br>
        <input type="text" id="fullname" name="fullname" placeholder="Agrega tu nombre completo aquí" /><br>
        <label for="address">Dirección:</label><br>
        <input type="text" id="address" name="address" placeholder="Añade tu dirección aquí" /><br><br>
        <button type="submit" id="save" name="save">Guardar</button><br>
        <p class="message"></p>
    </form>
    

    The jQuery / JavaScript astral.js external file

    jQuery( function($) {
        // check that the localized variable astral_params is defined
        if (typeof astral_params !== 'undefined') {
            console.log(astral_params);
            
            // On submitting the form event
            $('form#dhl-guias').on('submit', function(e) {
                e.preventDefault(); // Stop default form post action
                
                // Serializing form data
                var formData =  $(this).serialize()
    
                // Sending the post request via Ajax
                $.ajax({
                    type: "POST",
                    url: astral_params.ajax_url,
                    datatype: 'json',
                    data: { 
                        'action': 'astral_save_form',
                        'form_data': formData,
                        'security': astral_params.nonce
                    },
                    beforesend: function( xhr ){
                        console.log("beforesend");
                        console.log(xhr);                    
                    },
                    success: function(response) {
                        $('form p.message').html(response); // add a message
    
                        console.log("success");
                        console.log(response);
                    },
                    error: function(xhr, status, error) {
                        console.log("error");
                        console.log(xhr);
                        console.log(error);
                    }
                });
            });
        } else {
            console.log('"astral_params" is not defined');
        }
    });
    

    Tested and works. When the form is filled, an entry is added to the database table.