PHP: ответ при наведении, база в 130000 вопросов и Как Выполнить Большой Запрос
Показанный ниже небольшой сервис напоминает разного рода "Фразы дня" и "Случайные анекдоты", часто попадающиеся на популярных ресурсах. Случайная строка представляет собой вопрос вроде тех, что распространены в онлайн-викторинах, а ответ появляется при наведении курсора мыши на вопрос (то есть, он "зашит" в HTML-атрибут title
вопроса). Строка с вопросом выбирается из базы данных MySQL, при большом количестве записей это несравнимо лучше, чем использовать текстовые файлы. Для простоты генерация выполняется за 2 запроса - первый узнаёт общее количество записей, второй выбирает случайную запись.
Проверил на базе примерно в 150000 записей - никакого "торможения" не заметил (база показанного ниже "примера в работе" - всего 100 записей, нечего место на хостинге занимать :)
Вот полный исходник класса сервиса и пример его вызова:
<!DOCTYPE html> <html lang="ru"> <head> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> <meta charset="utf-8"> <title>Title Tool Tip</title> </head> <body bgcolor="#EEEEEE" text="#111111"> <?php class TitleToolTipSelector { private $DB_HOST, $DB_LOGIN, $DB_PASS, $DB_NAME, $DB_TABLE, $DB_CODEPAGE; public function __construct ($DB_HOST='localhost', $DB_LOGIN='root', $DB_PASS='root', $DB_NAME='test', $DB_TABLE='data', $DB_CODEPAGE='utf8') { $this->DB_HOST = $DB_HOST; $this->DB_LOGIN = $DB_LOGIN; $this->DB_PASS = $DB_PASS; $this->DB_NAME = $DB_NAME; $this->DB_TABLE = $DB_TABLE; $this->DB_CODEPAGE = $DB_CODEPAGE; $this->conid=0; $this->get_conid(); } public function __destruct () { mysqli_close($this->get_conid()); } private function get_conid () { static $conid=0; if ($conid===0) { $conid=mysqli_connect ($this->DB_HOST, $this->DB_LOGIN, $this->DB_PASS); if ($conid!==false) { mysqli_select_db ($conid, $this->DB_NAME); mysqli_set_charset ($conid, $this->DB_CODEPAGE); } } return $conid; } public function show () { $count=mysqli_fetch_array(mysqli_query($this->get_conid(),'select count(q) from '.$this->DB_TABLE)); $number= rand(0,$count[0]-1); $data=mysqli_fetch_assoc(mysqli_query($this->get_conid(),'select q,a from '.$this->DB_TABLE.' limit '.$number.',1')); echo '<div align="center"><span title="'.$data['a'].'">'.$data['q'].'</span> <br><font size=-1>(поднесите курсор к вопросу и узнаете ответ)</font></div>'; } } $t=new TitleToolTipSelector(); $t->show(); //Пример вызова класса echo '<div align="center"><a href="'.$_SERVER['PHP_SELF'].'">ещё...</a></div>'; //Просто для удобства - ссылка "Обновить" echo '<div align="center"><a href="http://blog.kislenko.net/show.php?id=986">что за скрипт?</a></div>'; ?> </body></html>
Скрипт в работе онлайн (всего 100 записей)
На реальном хостинге просто вызовите конструктор класса new TitleToolTipSelector()
с нужными параметрами (имя_хоста, логин_к_SQL, пароль_к_SQL, имя_базы, имя_таблицы, кодировка)
, в примере я вызвал его без параметров, потому что все их значения приняты на локалхосте по умолчанию.
Структура таблицы, требуемой скрипту, самая простая, вот запрос, создающий базу test
и таблицу data
"с нуля" (на реальном хостинге может понадобиться только последний оператор MySQL):
DROP DATABASE IF EXISTS test; CREATE DATABASE test; USE test; DROP TABLE IF EXISTS data; CREATE TABLE data ( q varchar(512), a varchar(64) );
Наконец, самым полезным в этой заметке может оказаться база вопросов и ответов в формате MySQL, более 130000 записей, структура запроса соответствует показанной выше структуре БД.
Скачать базу данных SQL вопросов и ответов в архиве ZIP с Яндекс.Диска (~3.3 Мб)
Импортировать это можно стандартными средствами -
выбрать в phpMyAdmin базу, потом Импорт,
кодировка файла utf-8 (Юникод), формат SQL. Предполагается, что база называется test
, а таблица - data
, если это не так, замените в первой строке распакованного файла название базы, и во всём файле - строку INSERT INTO data
на INSERT INTO ВАШЕ_ИМЯ_ТАБЛИЦЫ
.
Для удобства данные добавляются "порциями" по 10000 записей в одном запросе. Тем не менее, если
в Вашей системе такие большие запросы не выполняются, например, соединение завершается с "загадочной ошибкой" #2006 - MySQL server has gone away
, помочь может рецепт, который я применил у себя на локалхосте:
Находим файл конфигурации MySQL, у него имя my.ini
, а находится он в рабочей папке службы, у меня это была C:\Program Files\MySQL\MySQL Server 5.5\
Открываем любым текстовым редактором, находим в файле секцию
[mysqld]
и в ней добавляем запись
max_allowed_packet = 64M
(или ставим новую, если переменной max_allowed_packet
вообще не было).
После этого в Windows идём Администрирование - Службы, остановить и снова запустить службу MySQL.
После импортирования лучше закомментировать добавленное значение max_allowed_packet
(первым символом #
в строке) и снова перезапустить службу, чтобы зря память не жрала :)
P.S. Начиная с версии PHP 5.5 следует поменять код, работающий с MySQL, на код с MySQLi, это нетрудно (уже сделано в показанном выше листинге).
23.05.2013, 22:10 [12403 просмотра]