Деловая неделя

Писать код HTML-формы и код принимающего данные скрипта руками - плохая идея. Нужно использовать какие-то общие принципы (или договорённости для конкретного сайта). Но основой для формы всегда будет структура MySQL-таблицы.

ЕЖЕНЕДЕЛЬНАЯ РЕКЛАМНАЯ ГАЗЕТА ДЛЯ ПРЕДПРИЯТИЙ «Деловая неделя» (Иркутск)

HTML-форма для WYSIWYG-редактора из MySQL-таблицы

Генерация HTML-формы в распространённых PHP-фреймворках напоминает анекдот советских времён: «Наш новый станок полностью настроен на автоматическую работу и выдаёт готовое изделие без всякого участия человека. Рабочему нужно только поднять с пола и положить на станину трёхтонную заготовку...». Почти все описания алгоритмов генерации формы выглядят именно так: «Вам достаточно просто перечислить наименования полей и последовательно подставить их в конструкцию вида $DB->make_field['моё_поле']». Но откуда программист (точнее, скрипт) должен брать эти наименования?

HTML код, из которого состоят страницы любого сайта, может появляться примерно из трёх источников:

  1. Через визуальные редакторы HTML, когда оператор (человек) самого кода не видит – он производит с текстом наглядные манипуляции, а программа (движок) WYSIWYG превращает эти действия в HTML-тэги.
  2. Непосредственное написание кода руками: программист сразу пишет что-то вроде <b>Моя первая страница</b>.
  3. Генерация HTML-кода с помощью скрипта (PHP, javascript, perl...). Пример: http://dn.ir2.ru/charcod1.html – на странице отображается таблица символов HTML с кодами, но внутри файла всего несколько строк вида document.write("<td><b> Basic Latin</b><br>"); for(i=1; i<=127 ; i++).

В хорошей HTML-форме не должно быть HTML-кода, написанного непосредственно, руками. Потому что написания вида <input name='text'> будут вынуждать программиста держать в памяти наименование поля формы ("text") – чтобы соотнести его потом с индексом массива POST, и далее – с наименованием поля MySQL-таблицы. Лучше в этой цепочке участие программиста свести к минимуму.

Форма – зеркало полей таблицы. Таблица – основа. Поэтому форму обязательно следует генерировать, примерно по такому алгоритму:

  1. Получить структуру (список полей) таблицы (например, запросом show create table ...).
  2. Превратить список полей таблицы в список полей формы.
  3. Добавить в форму управляющие поля, по максимуму предопределённые структурой MySQL-таблицы.
  4. Вывести форму в виде HTML-кода.

Произвольное вмешательство человека требуется здесь во втором пункте: не все поля MySQL-таблицы должны заполняться пользователем. Бывают, например, автоинкрементные поля или поля типа timestamp, которые генерирует сам MySQL-сервер. Бывают поля, которые (без участия пользователя) должен заполнять PHP (например, идентификатор авторизованного пользователя).

Для каждой таблицы должен быть список алгоритмов заполнения полей. Если таблиц несколько, такие списки можно, в свою очередь, хранить в ещё одной MySQL-таблице. Нам пока хватит обычного массива в PHP-скрипте. Но для начала надо создать самоё таблицу, что-нибудь вроде:

Это будет таблица, в которой хранятся тексты для страниц сайта. Именно в таких случаях чаще всего требуется визуальный редактор – в панели административного управления, где можно создавать и редактировать страницы. Берём предельно упрощённый вариант, когда поле time всегда заполняется без участия пользователя (его совсем не будем показывать в форме), поля url и title не должны содержать HTML-кода и будут заполняться через элементы input; большое поле maintext будет содержать HTML-код и должно быть доступно пользователю через элемент textarea.

Массив, управляющий наличием-отсутствием полей формы, мы в нашем случае можем спокойно совместить с массивом перевода:

Принцип управления простой: если поле MySQL-таблицы не упоминается в данном массиве, оно не будет выводиться в HTML-форме. Если мы захотим добавить новое поле в таблицу (обновляемое с участием пользователя), мы должны будем также добавить (руками) описание этого поля в массив.

В скрытых полях формы мы будем передавать также имя таблицы (что делает систему более универсальной) и список имён полей, которые следует обрабатывать на предмет чистки HTML-кода.

Когда приходит POST

Принимать данные формы будет файл editpost.php. На пути от пришедших данных до sql-запроса возникает много интересных проблем. Самая очевидная из них – как найти строку таблицы, которую следут обновить? Ясно, что через форму придётся передавать ещё и этот идентификатор. Неясно вото что: как в принимающем файле мы отличим поле-идентификатор от поля, в котором надо обновить текст? Простой ответ "мы это и так знаем, что мы, тупые что ли?" в данном случае сильно усложнит всю последующую работу. Лучше немного усложнить код и сделать дальнейшую работу удобной и приятной.

Разделить данные для частей SET и WHERE sql-запроса можно известным способом особого наименования полей формы (сложно сказать, кому здесь принадлежит приоритет, но я узнал об этом способе от Дмитрия Котерова): надо называть поле формы не просто "maintext" или "url", а "set[maintext]" и "where[url]", тогда структура массива POST будет не структура, а загляденье:

Но тут опять возникает вопрос: а как отправляющий скрипт узнает, какое поле запихать в SET, а какое в WHERE? И опять ответ "ну, мы-то это ведь знаем – возьмём и напишем в скрипт!" здесь неправильный. Нужен какой-то алгоритм, принцип, не зависящий от человека (точнее, зависящий как можно меньше). Мы выбрали проверку поля на свойство primary_key:

Если поле – первичный ключ MySQL, будем идентифицировать строку по нему. Заметим, что если первичный ключ состоит из нескольких полей, идентификация будет производиться по всем этим полям (...WHERE `id`=3 AND `user`='me'...). Массив SET формируется по остаточному принципу (все наименования полей MySQL-ресурса, НЕ попавшие в where).

Да, чуть не забыл: мы производим весь анализ полей не по отдельному запросу вида "SHOW CREATE TABLE", а по имеющемуся MySQL-ресурсу. То есть изначально скрипт-редактор edit.php получает команду пользователя через GET, в виде edit.php?url=main. По значению main скрипт всё равно должен извлечь из базы (таблицы site_texts) все данные текущей строки. При попытке такого извлечения создаётся MySQL-ресурс, из которого и можно получить всю необходимую информацию о полях таблицы. Ресурс может быть пустым (не вернуть ни одной записи), но информацию о полях мы всё равно получим.

С учётом намеченных направлений разделения труда и кооперации между функциями, а также с учётом найденных ранее принципов работы с sql-запросами (описанных в статье Несколько функций для работы с БД), весь код генерации HTML-формы и приёма её данных на сервере уместился в следующем архиве: http://ir2.ru/wysiwyg/build_html_form.zip.

Посмотреть, как всё это работает, можно на стр. http://ir2.ru/wysiwyg/edit.php?url=main

D.M., admin

Читать все комментарии (3)

231. Gaev

А откуда ваш принимающий скрипт знает, что надо искать в POST массив SET?

14.05.2011 14:22:27

232. D.M., admin

Gaev, на первый взгляд, может показаться, что принимающий скрипт узнаёт детали структуры запроса из головы программиста (то есть те же грабли). Отчасти вы правы. Вероятно, более высокой «идеализацией» было бы создать общий "config.php" для всех скриптов сайта (или текущего блока обработки запросов), в котором определить начальные «сущности», например, в виде массива $def_sql = array('set' => 'set', 'where' => 'where', ...).

Но, по сути, этот массив и так определён (как, в общем-то, видно из его содержания) – имплицитно. Я бы назвал это «естественной» логикой, опирающейся в данном случае на понятия MySQL "SET" и "WHERE".

В любом случае, это более высокий уровень «договорённости» – о целых классах понятий, а не об отдельных наименованиях полей.

15.05.2011 00:33:47

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

*Автор:
E-Mail:
*Текст: