我是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';
}
?>
能否请您帮我找出问题所在?
答案 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
中定义了两个错误处理函数,它们捕获每个错误/警告/通知/等。
多样化:
$connection->prepare($sql)
代替mysqli_prepare($connection, $sql)
。type="button"
:<input type="button" name="submit"...>
。仅当您想以标准方式提交表单时,例如,使用type="submit"
按钮。使用action
标签的form
属性。$(document).on('click', '.add', function () {...}
,fill_slots
和fill_stages
函数中使用。fill_classes
,而不像<i class="fa ..."></i>
。全面搜索并正确搜索。<i class="fas ...">
函数中,使用$(selector).each()
参数而不是count变量。参见$(selector).each()。index
)而不是宽松的等号(===
)。我的代码:
别忘了与您一起更改==
中的数据库凭据。
同样,非常重要:阅读我提供给您的有关错误处理/报告的文档,然后尝试实现它。即将:
includes/db.php
和set_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 {
}