Ошибка с формированием url | jquery-ajax-json-php | Failed to load resource: the server responded with a status of 404 (Not Found)
Привет всем!
OS: Windows 10, IDE: VSCode, WebServer: XAMPP
Проходил этот курс only-to-top.ru/blog/programming/2019-11-11-jquery-ajax-json-php.html (не реклама). Все прекрасно работает, кроме пагинации. При попытке переключить страницу, в браузере выдаёт ошибки, показанные на скриншоте:
Проблема заключается в создании правильного url'а. Но вот где и какой правильный url надо поставить - это вопрос.
Я уже пытался и так менять url и сяк - ничего не получилось. Пытался даже найти на том форуме ответ - его там не оказалось.
Может быть кто-нибудь проходил этот мини-курс и знает что почём? Помогите, пожалуйста :)))
Код относящийся к пагинации:
core.php
<?php
// показывать сообщения об ошибках
ini_set("display_errors", 1);
error_reporting(E_ALL);
// URL домашней страницы
$home_url = "http://localhost/rest_api";
// страница указана в параметре URL, страница по умолчанию одна
$page = isset($_GET["page"]) ? $_GET["page"] : 1;
// установка количества записей на странице
$records_per_page = 4;
// расчёт для запроса предела записей
$from_record_num = ($records_per_page * $page) - $records_per_page;
read_paging.php
<?php
// установим HTTP-заголовки
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
// подключение файлов
include_once "../config/core.php";
include_once "../shared/utilities.php";
include_once "../config/database.php";
include_once "../objects/product.php";
// utilities
$utilities = new Utilities();
// создание подключения
$database = new Database();
$db = $database->getConnection();
// инициализация объекта
$product = new Product($db);
// запрос товаров
$stmt = $product->readPaging($from_record_num, $records_per_page);
$num = $stmt->rowCount();
// если больше 0 записей
if ($num > 0) {
// массив товаров
$products_arr = array();
$products_arr["records"] = array();
$products_arr["paging"] = array();
// получаем содержимое нашей таблицы
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
// извлечение строки
extract($row);
$product_item = array(
"id" => $id,
"name" => $name,
"description" => html_entity_decode($description),
"price" => $price,
"category_id" => $category_id,
"category_name" => $category_name
);
array_push($products_arr["records"], $product_item);
}
// подключим пагинацию
$total_rows = $product->count();
$page_url = "rest_api/api/product/read_paging.php";
$paging = $utilities->getPaging($page, $total_rows, $records_per_page, $page_url);
$products_arr["paging"] = $paging;
// установим код ответа - 200 OK
http_response_code(200);
// вывод в json-формате
echo json_encode($products_arr);
} else {
// код ответа - 404 Ничего не найдено
http_response_code(404);
// сообщим пользователю, что товаров не существует
echo json_encode(array("message" => "Товары не найдены"), JSON_UNESCAPED_UNICODE);
}
utilities.php
<?php
class Utilities
{
public function getPaging($page, $total_rows, $records_per_page, $page_url)
{
// массив пагинации
$paging_arr = array();
// кнопка для первой страницы
$paging_arr["first"] = $page > 1 ? "$page_url?page=1" : "";
// подсчёт всех товаров в базе данных для подсчета общего количества страниц
$total_pages = ceil($total_rows / $records_per_page);
// диапазон ссылок для показа
$range = 2;
// отображать диапазон ссылок вокруг текущей страницы
$initial_num = $page - $range;
$condition_limit_num = ($page + $range) + 1;
$paging_arr["pages"] = array();
$page_count = 0;
for ($x = $initial_num; $x < $condition_limit_num; $x++) {
// убедимся, что $x > 0 И $x <= $total_pages
if (($x > 0) && ($x <= $total_pages)) {
$paging_arr["pages"][$page_count]["page"] = $x;
$paging_arr["pages"][$page_count]["url"] = "$page_url?page=$x";
$paging_arr["pages"][$page_count]["current_page"] = $x == $page ? "yes" : "no";
$page_count++;
}
}
// кнопка для последней страницы
$paging_arr["last"] = $page < $total_pages ? "$page_url?page=$total_pages" : "";
// формат json
return json_encode($paging_arr);
}
}
products.js
// HTML список товаров
function readProductsTemplate(data, keywords) {
let read_products_html =
`
<!-- Форма для поиска товаров -->
<form id="search-product-form" action="#" method="post">
<div class="input-group pull-left w-30-pct">
<input type="text" value="` +
keywords +
`" name="keywords" class="form-control product-search-keywords" placeholder="Поиск товаров..." />
<span class="input-group-btn">
<button type="submit" class="btn btn-default" type="button">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
</div>
</form>
<!-- При нажатии загружается форма создания товара -->
<div id="create-product" class="btn btn-primary pull-right m-b-15px create-product-button">
<span class="glyphicon glyphicon-plus"></span> Создать товар
</div>
<!-- Начало таблицы -->
<table class="table table-bordered table-hover">
<!-- Создание заголовков колонок -->
<tr>
<th class="w-15-pct">Название</th>
<th class="w-10-pct">Цена</th>
<th class="w-10-pct">Категория</th>
<th class="w-35-pct text-align-center">Действие</th>
</tr>`;
// Перебор возвращаемого списка данных
$.each(data.records, (key, val) => {
// Создание новой строки таблицы для каждой записи
read_products_html +=
`<tr>
<td>` +
val.name +
`</td>
<td>$` +
val.price +
`</td>
<td>` +
val.category_name +
`</td>
<!-- Кнопки "действий" -->
<td class="text-align-center">
<!-- Кнопка для просмотра товара -->
<button class="btn btn-primary m-r-10px read-one-product-button" data-id="` +
val.id +
`">
<span class="glyphicon glyphicon-eye-open"></span> Просмотр
</button>
<!-- Кнопка для изменения товара -->
<button class="btn btn-info m-r-10px update-product-button" data-id="` +
val.id +
`">
<span class="glyphicon glyphicon-edit"></span> Редактировать
</button>
<!-- Кнопка для удаления товара -->
<button class="btn btn-danger delete-product-button" data-id="` +
val.id +
`">
<span class="glyphicon glyphicon-remove"></span> Удалить
</button>
</td>
</tr>`;
});
// Конец таблицы
read_products_html += `</table>`;
// Если есть пагинация
if (data.paging) {
read_products_html += `<ul class="pagination pull-left margin-zero padding-bottom-2em">`;
// Первая страница
if (data.paging.first != "") {
read_products_html += `<li><a data-page="${data.paging.first}">Первая страница</a></li>`;
}
// Перебор страниц
$.each(data.paging.pages, (key, val) => {
const active_page = val.current_page == "yes" ? "class='active'" : "";
read_products_html += `<li ${active_page}><a data-page="${val.url}">${val.page}</a></li>`;
});
// Последняя страница
if (data.paging.last != "") {
read_products_html += `<li><a data-page="${data.paging.last}">Последняя страница</a></li>`;
}
read_products_html += "</ul>";
}
// Добавим в «page-content» нашего приложения
$("#page-content").html(read_products_html);
}
read_products.js
jQuery(($) => {
// Показать список товаров при первой загрузке
showProducts();
// Когда была нажата кнопка «Все товары»
$(document).on("click", ".read-products-button", function () {
showProducts();
});
// Когда была нажата кнопка пагинации
$(document).on("click", ".pagination li", function () {
// Получаем JSON URL
const json_url = $(this).find("a").attr("data-page");
// Покажем список товаров с пагинацией
showProducts(json_url);
});
});
// Функция для отображения списка товаров
function showProducts(json_url = "api/product/read_paging.php")
{
// Получаем список товаров из API
$.getJSON(json_url, function (data) {
// HTML для перечисления товаров
readProductsTemplate(data, "");
// Изменим заголовок страницы
changePageTitle("Все товары");
});
}
Источник: Stack Overflow на русском