Как заставить PHP реагировать на действия пользователя на странице

Честно говоря, об этом обязательно написано в любом нормальном учебнике по PHP, однако, общаясь на форуме сайта php.ru, постоянно приходится объяснять этот аспект начинающим. И чтобы можно было просто давать ссылку на материал, я решил написать эту статью. Итак, правильный ответ на этот вопрос — скрипт на php не может реагировать на действия пользователя на странице!

Да, это единственный правильный ответ. Причина очень проста — скрипты на PHP выполняются на сервере. Пользователь же взаимодействует со страницей у себя на компьютере, в браузере. Взаимодействие браузера пользователя и сервера очень простое. Браузер запрашивает у сервера страницу по какому-то адресу. Если по этому адресу находится файл, который сервер не считает исполняемым (html, zip, jpg и другие), то файл просто отдаётся браузеру, как есть. Если же запрошен адрес php-скрипта (про другие используемые в веб-программировании языки я умолчу), то сервер запускает этот файл в интерпретаторе PHP, и всё, что данный скрипт выведет в процессе работы, сервер отправляет браузеру.

Теперь внимание! Мы подошли к самому важному моменту — после того, как вывод страницы сформирован, скрипт на PHP прекращает свою работу! Об этой особенности даже существует расхожее выражение — «PHP рождён, чтобы умирать«. Т.е. к моменту, когда пользователь видит у себя в браузере аккуратненькую (или не очень) страничку, скрипт, её формировавший, давно уже отработал.

Как же тогда быть, если действительно нужно, чтоб по какому-то действию пользователя на уже загруженную страницу подгружался какой-нибудь контент? К примеру, рассмотрим распространённую задачу — есть выпадающий список стран и выпадающий список городов. И при выборе каждой страны, с сервера должны подгружаться города и заполнять собой список. Как нам это реализовать?

Здесь в игру вступает другой скриптовый язык, Java Script. Скрипты на Java Script выполняются уже не на сервере, а на компьютере пользователя. Их интерпретацией занимается сам браузер. (Сейчас существуют и серверные интерпретаторы этого языка, но в этой статье они не будут рассмотрены). Именно он позволяет задать определённую реакцию на действия пользователя, такие как выбор элемента в выпадающем списке или щелчок на кнопке. И в современном Java Script существует технология, позволяющая обратиться к серверу и получить от него какие-либо данные. Данная технология получила название AJAX.

Суть заключается в следующем. Браузер обращается к серверу не как обычно, т.е. в ответ на ввод пользователем URL, щелчок по гиперссылке или отправку формы, а по запросу скрипта на Java Script.  Важно понимать, что для серверного скрипта особой разницы между традиционным обращением к нему браузера и запросом AJAX нету. Его задача — по прежнему сформировать какой-то вывод, и передать его в браузер. Браузер же, получив ответ от сервера, позволит JavaScript обработать полученный ответ. И именно задача скрипта на JavaScript каким-то образом изменить содержимое страницы на основе ответа сервера. Ну что ж, присказка кончилась, начинается сказка 🙂

Давайте реализуем описанный пример — автоматическую подгрузку городов при выборе страны. Для начала создадим базу данных, и запишем в неё следующие таблицы с данными (можете вставить больше стран и городов, но для демонстрации данных хватит):

CREATE TABLE IF NOT EXISTS `country` (
   Designs  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO `country` (`id`, `name`) VALUES
(1, 'Россия'),
(2, 'Украина');

CREATE TABLE IF NOT EXISTS  ?  `city` (
  wholesale jerseys   `id` int(11) NOT NULL AUTO_INCREMENT,
  `country_id` int(11) NOT NULL,
  `name` varchar(20) CHARACTER SET utf8 NOT NULL,
  PRIMARY  wholesale nba jerseys  KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO `city` (`id`, `country_id`, `name`) VALUES
(1, 1, 'Москва'),
(2, 1, 'Санкт-Петербург'),
(3, 1, 'Нижний Новгород'),
(4, 2, 'Киев'),
(5, 2, 'Харьков'),
(6, 2, 'Днепропетровск');

Теперь сделаем код формирующий главную страницу. К примеру, по умолчанию будут выводиться российские города. (естественно, при использовании кода вы должны заменить мои URL, имена пользователя и базы данных и т.д. на свои. Для соединения с базой данных используется пользователь root, поскольку код тестировался только на локальном сервере).

<?php
$db = mysqli_connect("localhost", "root", "", "test");
mysqli_set_charset($db, "utf8");

$countries = array();
// Получаем из базы список стран
$res = mysqli_query($db, "select * from country");

// Заносим его в массив. Вообще, есть функция mysqli_fetch_all, делающая тоже самое,
// но ещё попадаются хостинги c php 5.2, в котором она была не доступна
while  Commercial  ($country = mysqli_fetch_assoc($res))
    $countries[] = $country;

mysqli_free_result($res);

$default_country = 1; // По умолчанию Россия

$cities = array ();
$res = mysqli_query($db, "select * from city where country_id=$default_country");

// Все города России заносим в массив. См. аналогичный комментарий по странам
while ($city = mysqli_fetch_assoc($res))
    $cities[] = $city;

mysqli_free_result($res);
mysqli_close($db);
// Теперь формируем html
?>
<!DOCTYPE html>
<html>
<head>
    <title>Пример AJAX-запроса</title>

    <!-- Зачем нам jQuery - объясню позже -->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

    <!-- Этот скрипт тоже будет рассмотрен далее в статье. Он будет выполнять всю работу -->
    <script src="js/ajax.js"></script>
</head>
<body>
<select id='country'>
    <?php foreach ($countries as $country) {
        $selected = $cooutry["id"] == $default_country ? " selected " : ""; // Текущая ли страна?
        echo "<option value='$country[id]'$selected>$country[name]</option>";
    }
    ?>
</select>
<br>
<select id='city'>
    <?php foreach ($cities as $city) {
        echo "<option value='$city[id]'>$city[name]</option>";
    }
    ?>
</select>
</body>
</html>

JavaScript-часть кода будет написана с использованием библиотеки jQuery, которая избавит нас от необходимости проверять версию браузера, а также упростит взаимодействие как с DOM, так и AJAX-запрос. Хотя этот код можно было написать и без библиотеки jQuery, но по мне, это немного муторно. Итак, давайте я сначала приведу непосредственно код (файл ajax.js):

// JavaScript Document
$(function () {
    $("#country").change(function () {
        // Запрашиваем у сервера города страны
        $.get("/tools/get_cities.php?country=" + this.value, function (data) {
            // Предполагается, что сервер нам вернёт готовый список <option>,
            // которым мы заменим те, что  постов,  есть сейчас в city
            $("#city").html(data);
        }, "html")
    });
});

Итак, здесь мы видим, что по событию change (изменение) для выпадающего списка country происходит вызов функции $.get() (подробнее о ней читайте в документации jQuery). Данная функция как раз произведёт вызов php-скрипта get_cities.php, передав ему в качестве параметра текущую выбранную страну. Безымянная функция, которая передаётся в качестве параметра в $.get(), будет вызвана, как только скрипт на сервере успешно отработает и вернёт контент, который эта функция получает в качестве параметра data. В данном случае контент — это просто html-код, готовый к подстановке вместо опций select. Давайте Кондакопшино рассмотрим код этого последнего модуля нашей небольшой системы, и подведём некоторые итоги.

<?php
$db = mysqli_connect("localhost", "root", "", "test");
mysqli_set_charset($db, "utf8");

$cities = array ();
$res = mysqli_query($db, "select * from city where country_id=" . (int) $_GET["country"]);

while ($city = mysqli_fetch_assoc($res))
    $cities[] = $city;

foreach ($cities as $city) {
    echo "<option value='$city[id]'>$city[name]</option>";
}
mysqli_free_result($res);
mysqli_close($db);

Итак, как можете наблюдать, если вы нигде не допустили ошибку, наша подгрузка городов стран успешно работает. Теперь я хочу отдельно остановиться вот на каком моменте. Если в адресную строку браузера ввести прямо урл скрипта get_cities.php (в моём случае cheap nba jerseys http://localhost/tools/get_cities.php?country=2), то города будут выведены в браузер. Это демонстрирует принцип, о котором я говорил в конце вступительной части: для серверного скрипта особой разницы между традиционным обращением к нему браузера и запросом AJAX нету. Есть способ, конечно, проверить, идёт прямой запрос из адресной строки, или ajax-запрос (к примеру, по заголовкам. Подробнее), но это не сильно меняет суть технологии.

Давайте ещё раз пройдёмся по порядку работы данного небольшого сайта. Итак, сначала формируется главная страница и отправляется в браузер. Первый из приведённых здесь скриптов на этом свою работу заканчивает. Дальше, когда посетитель переключает страну в выпадающем списке, код JavaScript обращается к другому скрипту на сервере, get_cities.php, который получает из базы города выбранной страны, и выводит их в виде списка <option>, опять же, заканчивая на этом свою работу. После того, как данные с сервера пришли клиенту, код javaScript (ожидаюший в фоне ответа сервера) заменяет старый список городов новым.

Добавить комментарий

Ваш e-mail не будет опубликован.