| |||||||||||||
ЕЖЕНЕДЕЛЬНАЯ РЕКЛАМНАЯ ГАЗЕТА ДЛЯ ПРЕДПРИЯТИЙ «Деловая неделя» (Иркутск) | |||||||||||||
|
|||||||||||||
Идеальная визуализация БД (PHP, MySQL)Большинство PHP-программистов наизусть помнят некоторые часто встречающиеся на практике примеры работы с MySQL из Справочного руководства: while ($row = mysql_fetch_assoc($result)) { echo $row["userid"]; echo $row["fullname"]; ... } В практике работы по автоматизации офиса, однако, часто возникает необходимость вывести на экран фрагмент mysql-таблицы (или результатов запроса) «напрямую», «как есть», то есть именно в виде таблицы, примерно так, как она хранится в БД. Обычно это бывает нужно для отладки, но всё чаще требуется и для пользовательского интерфейса. И постепенно программист начинает подуставать от бесконечного рисования всех этих $row["userid"] руками. И тогда, порывшись в справочном руководстве или в чужих скриптах, программист начинает оптимизацию. Для начала надо вывести в заголовке таблицы названия полей. В отладочных целях нужны точные, латинские наименования, как в БД (как их превратить потом для пользователя в русские мы расскажем позже). Для этого есть функция mysql_field_name() – она может из результата запроса извлечь имя любого поля (колонки, столбца). Но нам надо не любого, а всех. Функция mysql_field_name() выдаёт наименования полей по их порядковому номеру. Мы не знаем этих порядковых номеров, да нам это и не надо, надо лишь знать общее количество полей, тогда мы можем просто перебрать все числа от 0 до общего количества в цикле. Общее количество полей запроса даёт функция mysql_num_fields(). Собрав всё вместе, получим нечто вроде: echo "<table><tr>"; $f=mysql_num_fields ($result); for ($i=0; $i<$f; $i++) { $name=mysql_field_name($r, $i); echo "<th>$name</th>"; } echo "</tr>"; Затем, воспользовавшись той же идеей и той же переменной $f, выведем в цикле все значения таблицы: while ($row = @mysql_fetch_array($r, MYSQL_NUM)) { echo "\n<tr>"; for ($i=0; $i<$f; $i++) { $value=$line[$i]; echo "<td>$value</td>"; } echo "</tr>"; } Такие конструкции часто встречаются если и не в справочных руководствах, то уж во многих популярных скриптах точно. Это довольно удобно: на входе текст запроса mysql, а на выходе – его результат в виде таблицы. Только в начале обработки обычно добавляют ещё стандартную проверку на существование строк в запросе (если строк нет, выводить ничего не надо): $sql="select * from `users`"; $result=mysql_query($sql); $n=mysql_num_rows($r); if (!$n) exit("В запросе \"$sql\" нет строк."); Посмотреть, что получилось, можно на странице http://dn.ir2.ru/mysql0.php (правда, там не совсем так, как в статье, – обработка вывода запроса на экран помещена в отдельную функцию sqlres). Там можно вставить в поле запроса фразу "show create table `img`" и потом экспериментировать сколько угодно. Впрочем, результат запроса "show..." выглядит не очень удобным для восприятия. Поэтому надо наш код немного подправить – добавить в место вывода значений на экран обработку концов строк: for ($i=0; $i<$f; $i++) { $value=preg_replace("/(\r?\n)+/i","<br>",$line[$i]); echo "<td>$value</td>"; } Результат (на странице http://dn.ir2.ru/mysql1.php) выглядит намного приличнее. Но чего-то всё-таки не хватает. Например, что делать, если нужен запрос на обновление? Ну, то есть понятно, что если вы сейчас его быстро-быстро запустите, просто-напросто получите ошибку "у пользователя dntest нет прав". Но на своём-то хостинге при работе с базой данных вы можете назначить любые права. И запрос выполнится, но количество затронутых им строк вы не узнаете (mysql_num_rows тут не поможет). Второй вопрос: как быть с группой запросов? Ведь часто надо перед выполнением основного запроса, например, выбрать базу данных. А PHP сам в функции mysql_query("...") не делит запрос на части, а всегда рассматривает его как один. Поэтому если вы введёте что-то вроде "show create table `img`; select * from img limit 0,1", получите ошибку. Кстати, о limit: если вы нечаянно запустите запрос "select * from img", то можете и не дождаться его окончательного вывода на экран – в таблице img иногда бывает до 10М картинок. Так что выражение "limit 0,30" надо обязательно добавлять в конце каждого запроса, если пользователь сам не указывает limit. Добавление же limit порождает ещё одну проблему – подсчёта строк запроса (общего количества, а не "отмеренного" пользователем с помощью limit). Далее, таблицы сайтов обычно содержат HTML-данные для страниц – как их выводить: как видит пользователь в браузере или в виде исходного кода? Ответ неочевиден, так как запросы бывают разного назначения: в случае приведённого выше "show create table `img`" как раз понадобился именно HTML (мы его сами добавили при выводе на экран). Следовательно, у пользователя должен быть выбор. То же и с разделителями запросов (пользователю бывает необходимо заменить стандартный ";" на что-то другое). Украшение функции вывода результатов на экранНо вначале надо доработать код, который уже есть. Украсить его – в смысле, не "приукрасить", а наоборот, сделать более красивым, убрать лишнее. Там есть один сомнительный момент – "рисование" шапки таблицы с помощью mysql_field_name. Ведь функция mysql_fetch_array возвращает массив, в котором могут содержаться наименования полей (если функцию использовать с константой MYSQL_ASSOC, а не MYSQL_NUM, как у нас). Сложность возникнет только со временем, последовательностью вывода на экран. Но её можно обойти, не выводя сразу все получаемые в цикле значения на экран, а помещая их в переменные (используя обыкновенную логику). Примерно так: $num=0; $head="<table><tr><th>N</th>"; while ($line = mysql_fetch_assoc($r)) { $num++; $str="<tr><td class=\"num\">$num</td>"; foreach ($line as $key=>$val) { $val=preg_replace("/(\r?\n)+/i","<br>",$val); $str.="<td>$val</td>"; if (1==$num) { $head.="<th>$key</th>"; } else $head=""; } $head.="$str</tr>\n"; print $head; } print "</table>"; Результат – на странице http://dn.ir2.ru/mysql2.php. Код стал короче и красивее. Правда, вы не сможете использовать эту страницу для тестирования, так как там значение переменной $sqlpost (стр.9) по умолчанию установлено в "1", а при таком значении (в любом из файлов примеров данной статьи) выводится код PHP, а не пользовательская страница (стр. 13-18 кода). Добавление некоторых удобствДля обработки нескольких запросов, присланных вместе, нужно сначала разделить эти запросы. Мы передаём из формы в качестве разделителя не символ, а его код (а то некоторые символы, например, табуляция, не видны на экране), по умолчанию – 59 (точка с запятой). Но мы учитываем для разделения запросов не один символ, а в сочетании с концом строки. Поэтому выражение для разделения запросов получается достаточно сложное: "/\;\s*(\r?\n)+/i". Для вычисления общего количества строк (без limit) в функцию добавлены две переменные (они инициализируются в файле configbase.php): $calc="SQL_CALC_FOUND_ROWS"; $foundrows="SELECT FOUND_ROWS()"; Всё остальное достаточно очевидно, да и в коде есть комментарии: http://dn.ir2.ru/mysql3.php. Для изучения работы разных типов запросов можно запускать этот скрипт на другом сайте – http://soft.infodisk.info/mysql3.php, там у пользователя mysql полные права на тестовую базу данных (только сайт infodisk.info не всегда доступен). Добавлена лишь одна неочевидная "оптимизация" – исключено использование mysql_num_rows, так как функция mysql_affected_rows более универсальна: она выдаёт количество затронутых строк для любых запросов – и на выборку, и на обновление (добавление, удаление). И последнее. Как заменить латинские наименования полей таблицы на русские, подходящие для пользователя (а не разработчика)? Тут, к сожалению, не могу сказать ничего утешительного: всё придётся делать руками. Сначала создать таблицу Mysql (посмотреть, как она выглядит, можно, запустив на странице mysql3.php запросы "show create table fields_ru" и "select * from fields_ru", не забудьте поставить галочку HTML). Вроде бы ничего сложного. Но надо добавить запись о каждом поле всех выводимых таблиц (это можно сделать и скриптом), а потом каждому латинскому (английскому) наименованию сделать подходящий с вашей точки зрения перевод. Когда таблица готова, нужно включить несколько дополнительных строк кода в файл конфигурации сайта: $fields_ru=array(); $r=mysql_query("select * from `fields_ru`"); $n=mysql_num_rows($r); if ($n) { while ($line = mysql_fetch_array($r, MYSQL_ASSOC)) { $f=$line["name"]; $fr=$line["ru"]; if (trim($fr)) $fields_ru["$f"]=$fr; } } После чего на каждой странице сайта будет доступен массив $fields_ru, и в коде наших примеров можно будет заменить латинские наименования на русские: строчку $head.="<th>$key</th>"; надо будет заменить на $head.="<th>{$fields_ru["$key"]}</th>"; Не забудьте также добавить в функцию sqlres строчку global $fields_ru. © 2009, «Деловая неделя», Михаил Гутентог 85. D.M., admin
Менее идеальный скриптНа странице http://dn.ir2.ru/mysql4.php добавлено одно излишество выбор языка для отображения названий полей, но зато там добавлена также одна очень необходимая вещь история sql-запросов. Можно выбрать из списка любой старый запрос и вставить его щелчком по кнопке ins в поле для отправки. Это порождает целую кучу технических проблем, решение которых надо описывать в отдельной статье. 12.10.2009 21:36:17 479. D.M., admin
Менее идеальный скриптНа странице http://dn.ir2.ru/mysql4.php добавлено одно излишество выбор языка для отображения названий полей, но зато там добавлена также одна очень необходимая вещь история sql-запросов. Можно выбрать из списка любой старый запрос и вставить его щелчком по кнопке ins в поле для отправки. Это порождает целую кучу технических проблем, решение которых надо описывать в отдельной статье. 12.10.2009 21:36:17 480. D.M., admin
Тот же скрипт доступен и на http://infodisk.info/mysql4.php там, как говорилось в статье, можно выполнять запросы на обновление. 12.10.2009 21:52:29 86. D.M., admin
Тот же скрипт доступен и на http://infodisk.info/mysql4.php там, как говорилось в статье, можно выполнять запросы на обновление. 12.10.2009 21:52:29 141. Alexander
Чудовишные примеры, понадергано, не тестировано, имена переменных как фишка ляжет. Точно не для чайников. 16.08.2010 16:11:40 142. D.M., admin
Alexander, ну, что делать. В чём-то вы правы. "Чудовищные" – возможно, не буду спорить. "Понадёргано" – неправда, всё только моё. "Не тестировано" – верно отчасти: вначале всё было хорошо, но потом какой-то недоброжелатель (более энергичный, чем вы)вставил мне в тестовую таблицу 2Г, после чего я запретил "insert", и теперь скрипты mysql4.php действительно не работают. Но главное - всё это вчерашний день. Я уже говорил, что через месяц-другой большинство моих скриптов (и идей) начинают казаться мне говнокодом. Ничего страшного в этом нет. Хуже, если вы любуетесь своими скриптами трёхлетней давности. Последняя идея по визуализации (и редактированию) БД - MySQL mini editor, описывать пока лень, но там есть небольшой help. P.S. Ну, и я с удовольствием перейду по вашей ссылке на страницу с описанием хорошего, красивого PHP-кода. И даже оставлю там комментарий, если код понравится. 17.08.2010 02:25:40 Добавить комментарий: |