Проблемы:
In 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:
У вас нет error
обратного вызова для вашего запроса ajax. Это также является причиной, почему вы не видите никаких ошибок на экране. См «Мой код» .
Короче говоря, поддерживая ваш стиль кодирования, ваш код в 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
определены две функции обработки ошибок, которые перехватывают каждую ошибку / предупреждение / уведомление / и т. Д.
<Ч />
Разнообразный:
- Вам нужен обратный вызов "error" для запроса ajax вместе с запросом "success".
- Вам нужны как клиентские, так и серверные проверки. Я бы предложил использовать плагин проверки. Этот является мощным. Это был мой любимый.
- Используйте подготовленные операторы, чтобы избежать sql инъекций . Так что читайте это .
- Вы должны использовать объектно-ориентированный mysqli вместо процедурного. Например:
$connection->prepare($sql)
вместо mysqli_prepare($connection, $sql)
.
- Вам следует ознакомиться с обработкой ошибок / составлением отчетов. Так что читайте это и это .
- Важно: Поскольку вы просто выполняете ajax-запрос, определите кнопку с именем «submit» как
type="button"
one: <input type="button" name="submit"...>
. Используйте кнопки type="submit"
только тогда, когда вы хотите отправить форму стандартным способом, например, используя атрибут action
тега form
.
- Старайтесь избегать использования php-кода в javascript, как в вашем
$(document).on('click', '.add', function () {...}
, где вы вызываете функции fill_slots
, fill_stages
и fill_classes
.
- Я бы предложил использовать библиотеку DataTables для таблиц. Отличная библиотека. И он отлично работает в сочетании с Bootstrap . Смотрите эту библиотеку тоже.
- Значки должны быть такими:
<i class="fa ..."></i>
, а не <i class="fas ...">
. Поиск общий и правильный.
- Внутри ваших
$(selector).each()
функций используйте параметр index
вместо переменной count. См. $ (селектор) .each () .
- В JS используйте строгие равенства (
===
) вместо свободных (==
).
<Ч />
Мой код:
Не забудьте изменить учетные данные БД в includes/db.php
на свои.
И, опять же, очень важно: прочитайте документы, которые я дал вам относительно обработки ошибок и составления отчетов, а затем попытайтесь реализовать их. Это собирается:
- Просто определите две функции -
set_error_handler
и set_exception_handler
- в файле. Затем включить файл в другие страницы проекта.
- Чтобы включить функции внутреннего отчета - как я делал в
includes/db.php
ниже.
Если вы все сделаете правильно, вам больше не нужно будет проверять ошибки «вручную», поскольку эти функции позаботятся обо всем за вас.
index.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>
insert.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);
* * включает в себя один тысяча сто тридцать четыре / db.php * ** 1136 тысячу сто тридцать пять *
<?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);
включает / InvalidInputValue.php
<?php
namespace App;
/**
* Custom exception. Thrown when posted user input values are invalid.
*/
class InvalidInputValue extends \Exception {
}
Определение таблицы
CREATE TABLE `day_slot_stage_class` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`day_date` varchar(100) DEFAULT NULL,
`day_name` varchar(100) DEFAULT NULL,
`slot_id` int(11) DEFAULT NULL,
`stage_id` int(11) DEFAULT NULL,
`swim_class_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;