JQuery: как обратиться из Javascript к базе данных
Нечто подобное уже есть вот тут, но сейчас я хочу сделать AJAX-запрос покороче, с использованием именно базы MySQL, да ещё и дописать уже существующую сборку "шахматной решалки", "закрыв" в ней упомянутые по ссылке "строки 41 и 56".
Сначала совсем простой пример, проще которого я придумать не смогу. На локальном сервере есть папка, допустим, с именем ptest
, в ней - обычный файл HTML с именем index.html
:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> </head> <body> <script type="text/javascript"> var num = 5; var str = 'Hello, world!'; $.post("./script.php", {num: num, str: str}); </script> </body></html>
Но файл этот не совсем простой:
- во-первых, он подключает библиотеку JQuery с сайта Гугля;
- во-вторых, с помощью JQuery он делает из клиентского кода на Javascript запрос к серверному скрипту на PHP.
В этой же папке лежит и файл script.php
, приём данных в нём ничем не отличается от случая, когда данные были переданы из формы HTML или от другого PHP-скрипта:
<?php $num = 0; if (isset($_POST['num'])) $num = intval(strip_tags(trim($_POST['num']))); $str = ''; if (isset($_POST['str'])) $str = mysql_real_escape_string(strip_tags(trim($_POST['str']))); file_put_contents ("data.txt","$num\t$str"); ?>
Наш скрипт просто записал полученные данные в текстовый файл, отделив число от строки символом табуляции \t
. А
на самом деле script.php
мог делать с данными, полученными от клиента, что угодно, например, писать их в базу MySQL, как-то обрабатывать и т.д.
Мы можем проверить этот код в работе, но только правильно, не щёлкая по html-файлу, а
по протоколу http через браузер, скажем, разместив папку ptest
с двумя файлами в корневой папке Denwer
или другого локального сервера, а затем набрав в браузере адрес http://localhost/ptest/
Сделаем пример пожизненней, например, ответим на вопрос, как решалка шахматных задач, написанная на яваскрипте и выполняющаяся на стороне клиента, может сохранять информацию о рейтингах пользователей в базе данных сервера.
Пусть к "корневому" документу HTML или скрипту PHP подключён скрипт:
<script src="js/puzzle.js"></script>
Неважно, что скрипт лежит во вложенной папке js
, всё равно вызывать серверные php-скрипты он будет из той же папки, где находится "корневой" документ, да иной подход и чреват проблемами.
Например, ajax-запросы на ресурсы с доменами, поддоменами и протоколами, отличными от текущего, как правило, запрещены. То есть, из клиентского файла domain.com/script.js
нельзя обратиться к серверному anotherdomain.com/script.php
. А если бы было можно, любой дятел смог бы бомбить со своего компьютера любую форму в интернете. Разумеется, можно написать браузер или обёртку, где кроссдоменные ajax-запросы разрешены,
но ведь порвут :)
Наш клиентский puzzle.js
, пользуясь тем, что в нём подключён JQuery, хочет иногда вызывать серверные скрипты plus.php
и minus.php
- для увеличения и уменьшения рейтинга юзверька в зависимости от того, правильно ли тот решает задачи:
$.post("./minus.php", {balM: puzzle.balM, move: correct_move}); // Отправка данных на обработку рейтинга (-) //... $.post("./plus.php", {balP: puzzle.balP, move: correct_move}); // Отправка данных на обработку рейтинга (+)
Это опять образец короткого вызова метода $.ajax
для отправки данных на сервер методом POST
.
Здесь первым параметром, с именем balM
и balP
, передаётся число (на сколько уменьшить или увеличить рейтинг), а вторым параметром, с именем move
, передаётся строка (запись хода).
Скрипты minus.php
и plus.php
будут очень похожи, только первый из них не будет повторно "минусовать" неверные ходы пользователя, во втором такая проверка не нужна, так как он вызывается только после решения задачи:
<?php require_once 'functions.php'; $balM = intval(strip_tags(trim($_POST['balM']))); $mov = mysql_real_escape_string(strip_tags(trim($_POST['move']))); $ip = get_ip(); $result = dbquery('select * from '.DB_TABLE.' where ip="'.$ip.'" limit 0,1'); if ($result and dbrows($result)) { $note = dbfetcha($result); $note['cnt'] -= $balM; if ($note['mov']!=$mov) { //не минусовать повторно за неверные $result = dbquery('update '.DB_TABLE.' set cnt = "'.$note['cnt'].'", mov = "'.$mov.'" where ip = "'.$ip.'"'); if (!$result) die ('Invalid query 1: ' . mysql_error()); } } else { $result = dbquery('insert into '.DB_TABLE.' (ip, cnt) values ("'.$ip.'", "'.(0-$balM).'")'); if (!$result) die ('Invalid query 2: ' . mysql_error()); } ?>
<?php require_once 'functions.php'; $balP = intval(strip_tags(trim($_POST['balP']))); $ip = get_ip(); $result = dbquery('select * from '.DB_TABLE.' where ip="'.$ip.'" limit 0,1'); if ($result and dbrows($result)) { $note = dbfetcha($result); $note['cnt'] += $balP; $result = dbquery('update '.DB_TABLE.' set cnt = "'.$note['cnt'].'" where ip = "'.$ip.'"'); if (!$result) die ('Invalid query 1: ' . mysql_error()); } else { $result = dbquery('insert into '.DB_TABLE.' (ip, cnt) values ("'.$ip.'", "'.(0+$balP).'")'); if (!$result) die ('Invalid query 2: ' . mysql_error()); } ?>
Скрипты пользуются файлом functions.php
, содержащим несложную "обёртку" для операций с базой, а также более-менее адекватную функцию определения IP-адреса пользователя:
<?php require_once('config.php'); if (!isset($conid)) { function dbconnect() { $mysql=mysql_connect(DB_HOST, DB_USER, DB_PASS); //хост, логин, пароль mysql_select_db(DB_NAME); //имя базы данных return $mysql; } function dbquery ($sql) { return mysql_query($sql,get_conid()); } function dbrows ($result) { return mysql_num_rows($result); } function dbfree ($result) { mysql_free_result($result); } function dbclose ($conid) { mysql_close(get_conid()); } function dbfetcha ($result) { if ($row=mysql_fetch_assoc ($result)) return $row; else return false; } function dbfetch ($result){ if ($row=mysql_fetch_array($result)) return $row; else return false; } function get_conid () { static $conid=0; if ($conid==0) { $conid=dbconnect(); mysql_set_charset (DB_ENCODING,$conid); } return $conid; } get_conid (); } function get_ip () { if( getenv('HTTP_X_FORWARDED_FOR') != '' ) { $client_ip = ( !empty($_SERVER['REMOTE_ADDR']) ) ? $_SERVER['REMOTE_ADDR'] : ( ( !empty($_ENV['REMOTE_ADDR']) ) ? $_ENV['REMOTE_ADDR'] : $REMOTE_ADDR ); $entries = explode(',', getenv('HTTP_X_FORWARDED_FOR')); reset($entries); while (list(, $entry) = each($entries)) { $entry = trim($entry); if ( preg_match("/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/", $entry, $ip_list) ) { $private_ip = array('/^0\./', '/^127\.0\.0\.1/', '/^192\.168\..*/', '/^172\.((1[6-9])|(2[0-9])|(3[0-1]))\..*/', '/^10\..*/', '/^224\..*/', '/^240\..*/'); $found_ip = preg_replace($private_ip, $client_ip, $ip_list[1]); if ($client_ip != $found_ip) { $client_ip = $found_ip; break; } } } } else { $client_ip = ( !empty($_SERVER['REMOTE_ADDR']) ) ? $_SERVER['REMOTE_ADDR'] : ( ( !empty($_ENV['REMOTE_ADDR']) ) ? $_ENV['REMOTE_ADDR'] : $REMOTE_ADDR ); } return $client_ip; } ?>
Примечание. Адекватна функция get_ip
будет только в случае "классического" ipv4 и PHP5. Для ipv6 и PHP7 лучше поискать другое решение (см. комментарии здесь).
В свою очередь, functions.php
подключает config.php
, содержащий обычные настройки для коннекта, у меня на локалхосте требуется вот такой config.php
, на реальном хосте настройки придётся изменить:
<?php define('DB_HOST', 'localhost'); //Хост, на котором размещен сервер MySQL define('DB_USER', 'root'); //Имя пользователя MySQL define('DB_PASS', 'root'); //Пароль пользователя MySQL define('DB_NAME', 'my'); //Имя базы данных define('DB_TABLE', 'chesspuzzles'); //Имя таблицы define('DB_ENCODING', 'cp1251'); //Кодировка базы данных ?>
Перед тем, как запустить скрипты, я создал на локальном сервере таблицу chesspuzzles
для хранения данных. Для этого достаточно выбрать в phpMyAdmin (в Denwer он вызывается из браузера адресом http://localhost/tools/phpmyadmin/
) нужную базу данных (у меня с именем my
) и выполнить к ней такой SQL-запрос:
DROP TABLE IF EXISTS chesspuzzles; CREATE TABLE IF NOT EXISTS chesspuzzles ( ip varchar(15), mov varchar(8), cnt int );
В той же папке, где остальной PHP-код и главный файл, можно поместить скрипт list.php
, который покажет текущую статистику по IP-адресам пользователей скрипта и их баллам:
<html><head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title>Решалка: весь рейтинг</title> </head> <body bgcolor="white"> <?php require_once 'functions.php'; $result = dbquery('select * from '.DB_TABLE.' order by cnt desc'); echo '<table align="center" width="90%" border="1" cellpadding="4" cellspacing="0">'; if ($result and dbrows($result)) { while ($note = dbfetcha($result)) { echo '<tr><td width="50%">'.$note['ip'].'</td><td>'.$note['cnt'].'</td></tr>'; } } else { echo '<tr><td>Нет данных</td></tr>'; } echo '</table><div align="center"><a href="list.php">Обновить</a></div>'; ?> </body></html>
Что вышло - можно посмотреть вот тут, заодно и шахматные задачки порешать, ничего не скачивая.
P.S. Для PHP версий 5.5 и выше нужно перевести код работы с базой с MySQL на MySQLi, как сделано здесь.
18.11.2015, 01:01 [29460 просмотров]