如何将Ajax连接到外部php文件

时间:2018-08-30 21:09:32

标签: javascript php ajax

我是Ajax的新手,我用php和javascript编写了以下代码。我用Ajax编写了该呼叫,但觉得有问题。除了调用insert.php文件之外,其他所有功能都正常。

    <div class="container">
    <form action="" method="post" id="add_days_form">
         <div class="table-responsive">
            <span id="error"></span>
               <table class="table table-bordered" id="add_all">
                  <tr>
                         <th>Enter Day</th>
                         <th>Enter Time</th>
                         <th>Enter Stage</th>
                         <th>Enter Class Name</th>
                         <th><button type="button" name="add" class="btn btn-success btn-sm add"><i class="fas fa-plus"></i></button> </th>

                     </tr> 
               </table>
               <br/>
               <div align="center">
                   <input type="submit" name="submit" class="btn btn-info" value="Insert">
               </div>
        </div>
     </form>
</div>
<script>    
        $(document).ready(function(){
        $(document).on('click','.add',function(){
        var html='';
        html +='<tr>';
        html += '<td><input type="date" name="slot_date[]" class="form-control day"/></td>';
        html +='<td><select name="slot_time[]" class="form-control slot"><option value="">Select Slot</option><?php echo fill_slots(); ?></select></td>';
        html +='<td><select name="slot_stage[]" class="form-control stage"><option value="">Select Stage</option><?php echo fill_stages(); ?></select></td>';
        html +='<td><select name="slot_class[]" class="form-control class"><option value="">Select Class Name</option><?php echo fill_classes(); ?></select></td>';
        html +='<td><button type="button" name="remove" class="btn btn-danger btn-sm remove"><i class="fas fa-minus"></i></button></td></tr>';
        $('#add_all').append(html);
                         });

        $(document).on('click','.remove',function(){
                $(this).closest('tr').remove(); 
            });

        $('#add_days_form').on('submit', function(event){
                event.preventDefault();
                var error = '' ;
                $('.day').each(function(){
                    var count =1;
                    if ($(this).val()=='')
                        {
                            error+="<p>Enter Date at Row Number " +count+ "</p>";
                            return false;
                        }
                    count = count + 1;

                });
                $('.slot').each(function(){
                    var count=1;
                    if($(this).val()==''){

                        error+="<p>Enter Time at Row Number " +count+ "</p>";
                        return false;
                    }
                    count = count + 1;
                });
                $('.stage').each(function(){
                    var count=1;
                    if($(this).val()==''){

                        error+="<p>Enter Stage at Row Number " +count+ "</p>";
                        return false;
                    }
                    count = count + 1;
                });
                $('.class').each(function(){
                    var count=1;
                    if($(this).val()==''){

                        error+="<p>Enter Class at Row Number " +count+ "</p>";
                        return false;
                    }
                    count = count +1;
                });

                var form_data = $(this).serialize();
                if(error == ''){
                    $.ajax({
                        url:"insert.php",
                        method:"POST",
                        data:form_data,
                        success:function(data)
                        {
                            if(data == 'ok')
                                {
                                    $('#add_all').find("tr:gt(0)").remove();
                                    $('#error').html('<div class="alert alert-success">Day Saved</div>');}
                        }
                    });

                }
                else{
                    $('#error').html('<div class="alert alert-danger">' +error+ '</div>');
                }
            });

        });

        </script>

这是我的insert.php文件,其中包含我要运行并发送回Ajax的脚本:

        <?php
        include "../includes/db.php";
        if(isset($_POST['slot_date']))
        {
            $slot_date = $_POST['slot_date'];
            $slot_date_name = date('l', strtotime($slot_date));
            $slot_time = $_POST['slot_time'];
            $slot_stage = $_POST['slot_stage'];
            $slot_class = $_POST['slot_class'];

            for($count = 0; $count < count($slot_date); $count++)

            {
                $query="INSERT INTO day_slot_stage_class(day_date,day_name,slot_id,stage_id,swim_class_id) VALUES ('{$slot_date}', {$slot_date_name}', {$slot_time}' , {$slot_stage} ,'{$slot_class}')";

                $run_query=mysqli_query($connection,$query);
                confirmQuery($run_query);

            }

            }
           $result = mysqli_fetch_all($run_query,MYSQLI_ASSOC);

            if(isset($result)){
                echo 'ok';          
        }
        ?>

能否请您帮我找出问题所在?

1 个答案:

答案 0 :(得分:0)

问题:

在insert.php中:

Error 2 - strtotime() expects parameter 1 to be string, array given in file path-to/insert.php on line 7
Error 8 - Array to string conversion in file path-to/insert.php on line 14
Error 2 - mysqli_fetch_all() expects parameter 1 to be mysqli_result, boolean given in file path-to/insert.php on line 33

因此,$query sql语句中的值是错误的。也缺少一些撇号:

INSERT INTO day_slot_stage_class (day_date, day_name, slot_id, stage_id, swim_class_id) VALUES (
    'Array', 
    Thursday', 
    Array' , 
    Array ,
    'Array'
)

$slot_date_name应该在for循环之内。

语句$result = mysqli_fetch_all($run_query,MYSQLI_ASSOC);根本没有任何关系。

还需要一个错误处理/报告系统,以便能够捕获/跟踪最终的错误。阅读“多样化”

在index.php中:

您的ajax请求没有error回调。这也是为什么您没有在屏幕上看到任何错误的原因。请参见“我的代码”

简而言之,为了维持您的编码风格,您在insert.php中的代码应如下所示:

<?php

include "../includes/error_handlers.php";
include "../includes/db.php";

$slot_date = $_POST['slot_date'] ?? [];
$slot_time = $_POST['slot_time'] ?? [];
$slot_stage = $_POST['slot_stage'] ?? [];
$slot_class = $_POST['slot_class'] ?? [];

for ($count = 0; $count < count($slot_date); $count++) {
    $slot_date_name = date('l', strtotime($slot_date[$count]));

    $query = "INSERT INTO day_slot_stage_class (
                    day_date,
                    day_name,
                    slot_id,
                    stage_id,
                    swim_class_id
                ) VALUES (
                    '{$slot_date[$count]}',
                    '{$slot_date_name}',
                    '{$slot_time[$count]}',
                    '{$slot_stage[$count]}',
                    '{$slot_class[$count]}'
                )";

    mysqli_query($connection, $query);
}

echo 'ok';

请参阅,不检查操作是否成功,因为在包含的文件error_handlers.php中定义了两个错误处理函数,它们捕获每个错误/警告/通知/等。


多样化:

  • 您需要ajax请求的“错误”回调以及“成功”的回调。
  • 您需要客户端和服务器端验证。我建议使用验证插件。 This是强大的。这是我的最爱。
  • 使用准备好的语句以避免sql injection。因此,请阅读this
  • 您应该使用面向对象的mysqli而不是过程性的mysqli。例如:$connection->prepare($sql)代替mysqli_prepare($connection, $sql)
  • 您应该熟悉错误处理/报告。因此,请阅读thisthis
  • 重要:由于您只是执行ajax请求,因此将名为“ submit”的按钮定义为type="button"<input type="button" name="submit"...>。仅当您想以标准方式提交表单时,例如,使用type="submit"按钮。使用action标签的form属性。
  • 尝试避免在JavaScript中使用php代码,例如在$(document).on('click', '.add', function () {...}fill_slotsfill_stages函数中使用。
  • 我建议对表使用DataTables库。一个很棒的图书馆。它可以与Bootstrap完美结合。另请参见this library
  • 图标应类似于:fill_classes,而不像<i class="fa ..."></i>。全面搜索并正确搜索。
  • <i class="fas ...">函数中,使用$(selector).each()参数而不是count变量。参见$(selector).each()
  • 在JS中,使用严格的等号(index)而不是宽松的等号(===)。

我的代码:

别忘了与您一起更改==中的数据库凭据。

同样,非常重要:阅读我提供给您的有关错误处理/报告的文档,然后尝试实现它。即将:

  • 只需在文件中定义两个功能-includes/db.phpset_error_handler。然后将文件包含在其他项目页面中。
  • 要启用内部报告功能-就像我在下面的set_exception_handler中所做的那样。

如果操作正确,则不再需要手动检查错误,因为这些功能将为您处理一切。

index.php

includes/db.php

insert.php

<?php

function fill_slots() {
    $options = '';
    $options .= '<option value="1">Slot 1</option>';
    $options .= '<option value="2">Slot 2</option>';
    $options .= '<option value="3">Slot 3</option>';
    $options .= '<option value="4">Slot 4</option>';
    $options .= '<option value="5">Slot 5</option>';
    $options .= '<option value="6">Slot 6</option>';

    return $options;
}

function fill_stages() {
    $options = '';
    $options .= '<option value="1">Stage 1</option>';
    $options .= '<option value="2">Stage 2</option>';
    $options .= '<option value="3">Stage 3</option>';
    $options .= '<option value="4">Stage 4</option>';
    $options .= '<option value="5">Stage 5</option>';
    $options .= '<option value="6">Stage 6</option>';

    return $options;
}

function fill_classes() {
    $options = '';
    $options .= '<option value="1">Class 1</option>';
    $options .= '<option value="2">Class 2</option>';
    $options .= '<option value="3">Class 3</option>';
    $options .= '<option value="4">Class 4</option>';
    $options .= '<option value="5">Class 5</option>';
    $options .= '<option value="6">Class 6</option>';

    return $options;
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo</title>

        <!-- CSS assets -->
        <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" type="text/css" rel="stylesheet" />
        <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" type="text/css" rel="stylesheet">

        <!-- JS assets -->
        <script src="https://code.jquery.com/jquery-3.3.1.min.js" type="text/javascript"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>

        <script type="text/javascript">
            $(document).ready(function () {
                $(document).on('click', '.add', function () {
                    var rowTemplate = $('#rowTemplateContainer tbody').html();
                    $('#add_all tbody').append(rowTemplate);
                });

                $('#add_all').on('click', '.remove', function () {
                    $(this).closest('tr').remove();
                });

                $('#saveButton').on('click', function (event) {
                    var errors = [];

                    $('#add_all .day').each(function (index) {
                        if ($(this).val() === '') {
                            errors.push('Enter Date at Row Number ' + (index + 1));
                        }
                    });

                    $('#add_all .slot').each(function (index) {
                        if ($(this).val() === '') {
                            errors.push('Enter Time at Row Number ' + (index + 1));
                        }
                    });

                    $('#add_all .stage').each(function (index) {
                        if ($(this).val() === '') {
                            errors.push('Enter Stage at Row Number ' + (index + 1));
                        }
                    });

                    $('#add_all .class').each(function (index) {
                        if ($(this).val() === '') {
                            errors.push('Enter Class at Row Number ' + (index + 1));
                        }
                    });

                    if (errors.length > 0) {
                        $('#error').html('<div class="alert alert-danger">' + errors.join('<br/>') + '</div>');
                        return false;
                    }

                    $.ajax({
                        method: 'post',
                        dataType: 'html',
                        url: 'insert.php',
                        data: $('#add_days_form').serialize(),
                        success: function (response, textStatus, jqXHR) {
                            $('#add_all').find("tr:gt(0)").remove();
                            $('#error').html('<div class="alert alert-success">Day Saved</div>');
                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            /*
                             * When a HTTP error occurs, errorThrown receives the "reason phrase" of the
                             * HTTP response message - such as "Not Found", or "Internal Server Error".
                             */
                            var message = errorThrown;

                            /*
                             * If the body of the HTTP response message exists, then it
                             * is saved in the responseText property of the jqXHR object.
                             */
                            if (jqXHR.responseText !== null && jqXHR.responseText !== 'undefined' && jqXHR.responseText !== '') {
                                message = jqXHR.responseText;
                            }

                            $('#error').html('<div class="alert alert-danger">' + message + '</div>');
                        }
                    });
                });
            });
        </script>
    </head>
    <body>

        <div class="container">
            <form action="" method="post" id="add_days_form">
                <span id="error"></span>

                <div class="table-responsive">
                    <table id="add_all" class="table table-bordered">
                        <thead>
                            <tr>
                                <th>Enter Day</th>
                                <th>Enter Time</th>
                                <th>Enter Stage</th>
                                <th>Enter Class Name</th>
                                <th>
                                    <button type="button" name="add" class="btn btn-success btn-sm add">
                                        <i class="fa fa-plus"></i>
                                    </button>
                                </th>
                            </tr>
                        </thead>
                        <tbody></tbody>
                    </table>

                    <br/>

                    <div align="center">
                        <input type="button" id="saveButton" name="submit" class="btn btn-info" value="Insert">
                    </div>
                </div>
            </form>
        </div>

        <table id="rowTemplateContainer" style="display: none;">
            <tbody>
                <tr>
                    <td>
                        <input type="date" name="slot_date[]" class="form-control day"/>
                    </td>
                    <td>
                        <select name="slot_time[]" class="form-control slot">
                            <option value="">Select Slot</option>
                            <?php echo fill_slots(); ?>
                        </select>
                    </td>
                    <td>
                        <select name="slot_stage[]" class="form-control stage">
                            <option value="">Select Stage</option>
                            <?php echo fill_stages(); ?>
                        </select>
                    </td>
                    <td>
                        <select name="slot_class[]" class="form-control class">
                            <option value="">Select Class Name</option>
                            <?php echo fill_classes(); ?>
                        </select>
                    </td>
                    <td>
                        <button type="button" name="remove" class="btn btn-danger btn-sm remove">
                            <i class="fa fa-minus"></i>
                        </button>
                    </td>
                </tr>
            </tbody>
        </table>

    </body>
</html>

includes / db.php

<?php

require '../includes/db.php';
require_once '../includes/InvalidInputValue.php';

use App\InvalidInputValue;

/*
 * ======================
 * Read the posted values
 * ======================
 */
$slotDate = $_POST['slot_date'] ?? [];
$slotTime = $_POST['slot_time'] ?? [];
$slotStage = $_POST['slot_stage'] ?? [];
$slotClass = $_POST['slot_class'] ?? [];

// Number of rows.
$numberOfRows = count($slotDate);

// The names of the days.
$slotDateName = [];

// Eventual errors.
$errors = [];

/*
 * =====================================================
 * Validate the values. If invalid values were provided,
 * activate the "error" callback of the ajax request.
 * =====================================================
 */
try {
    // Check if any data provided.
    if ($numberOfRows === 0) {
        throw new InvalidInputValue('You did\'t provide any data');
    }

    for ($i = 0; $i < $numberOfRows; $i++) {
        // Validate the date.
        if (empty($slotDate[$i])) {
            $errors[] = 'Enter Date at Row Number ' . ($i + 1);
        } /* Other validations here using elseif statements */ else {
            // Add the current name of the day to the list.
            $slotDateName[$i] = date('l', strtotime($slotDate[$i]));
        }

        // Validate the time.
        if (empty($slotTime[$i])) {
            $errors[] = 'Enter Time at Row Number ' . ($i + 1);
        } /* Other validations here using elseif statements */

        // Validate the stage.
        if (empty($slotStage[$i])) {
            $errors[] = 'Enter Stage at Row Number ' . ($i + 1);
        } /* Other validations here using elseif statements */

        // Validate the class.
        if (empty($slotClass[$i])) {
            $errors[] = 'Enter Class at Row Number ' . ($i + 1);
        } /* Other validations here using elseif statements */
    }

    if ($errors) {
        throw new InvalidInputValue(implode('<br/>', $errors));
    }
} catch (InvalidInputValue $exc) {
    /*
     * Throw an error to be catched by the "error" callback of the ajax request.
     * This can be achieved by sending a specific or a custom response header to the client.
     *
     *  - Specific header: A header containing any already assigned status code.
     *  - Custom header: A header containing any NOT already assigned status code. This type of
     *    headers have the reason phrase "Unassigned" in the official HTTP Status Code Registry.
     *
     * @link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml HTTP Status Code Registry.
     */
    header('HTTP/1.1 500 Internal Server Error', TRUE, 500);
    echo $exc->getMessage();
    exit();
}

/*
 * ===================================
 * Insert the values into the db table
 * ===================================
 */

/*
 * -----------------------------------------------------------
 * Step 1: Prepare the sql statement for execution - ONLY ONCE
 * -----------------------------------------------------------
 */

/*
 * The SQL statement to be prepared. Notice the so-called markers,
 * e.g. the "?" signs. They will be replaced later with the
 * corresponding values when using mysqli_stmt::bind_param.
 *
 * @link http://php.net/manual/en/mysqli.prepare.php
 */
$sql = 'INSERT INTO day_slot_stage_class (
            day_date,
            day_name,
            slot_id,
            stage_id,
            swim_class_id
        ) VALUES (
            ?, ?, ?, ?, ?
        )';

/*
 * Prepare the SQL statement for execution - ONLY ONCE.
 *
 * @link http://php.net/manual/en/mysqli.prepare.php
 */
$statement = mysqli_prepare($connection, $sql);

/*
 * -----------------------------------------
 * Step 2: Save the values into the db table
 * -----------------------------------------
 */
for ($i = 0; $i < $numberOfRows; $i++) {
    /*
     * Bind variables for the parameter markers (?) in the
     * SQL statement that was passed to prepare(). The first
     * argument of bind_param() is a string that contains one
     * or more characters which specify the types for the
     * corresponding bind variables.
     *
     * @link http://php.net/manual/en/mysqli-stmt.bind-param.php
     */
    mysqli_stmt_bind_param($statement, 'ssiii'
            , $slotDate[$i]
            , $slotDateName[$i]
            , $slotTime[$i]
            , $slotStage[$i]
            , $slotClass[$i]
    );

    /*
     * Execute the prepared SQL statement.
     * When executed any parameter markers which exist will
     * automatically be replaced with the appropriate data.
     *
     * @link http://php.net/manual/en/mysqli-stmt.execute.php
     */
    mysqli_stmt_execute($statement);
}

/*
 * ---------------------------------
 * Step 3: Close the used components
 * ---------------------------------
 */

/*
 * Close the prepared statement. It also deallocates the statement handle.
 * If the statement has pending or unread results, it cancels them
 * so that the next query can be executed.
 *
 * @link http://php.net/manual/en/mysqli-stmt.close.php
 */
mysqli_stmt_close($statement);

/*
 * Close the previously opened database connection.
 * Not really needed because the PHP engine closes
 * the connection anyway when the PHP script is finished.
 *
 * @link http://php.net/manual/en/mysqli.close.php
 */
mysqli_close($connection);

includes / InvalidInputValue.php

<?php

/*
 * This page contains the code for creating a mysqli connection instance.
 */

// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'tests');
define('USERNAME', 'root');
define('PASSWORD', 'root');

/*
 * Enable internal report functions. This enables the exception handling,
 * e.g. mysqli will not throw PHP warnings anymore, but mysqli exceptions
 * (mysqli_sql_exception).
 *
 * MYSQLI_REPORT_ERROR: Report errors from mysqli function calls.
 * MYSQLI_REPORT_STRICT: Throw a mysqli_sql_exception for errors instead of warnings.
 *
 * @link http://php.net/manual/en/class.mysqli-driver.php
 * @link http://php.net/manual/en/mysqli-driver.report-mode.php
 * @link http://php.net/manual/en/mysqli.constants.php
 */
$mysqliDriver = new mysqli_driver();
$mysqliDriver->report_mode = (MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

/*
 * Create a new db connection.
 *
 * @see http://php.net/manual/en/mysqli.construct.php
 */
$connection = mysqli_connect(HOST, USERNAME, PASSWORD, DATABASE, PORT);

表定义

<?php

namespace App;

/**
 * Custom exception. Thrown when posted user input values are invalid.
 */
class InvalidInputValue extends \Exception {

}