Необычная работа с формами на PHP или как упростить себе жизнь

от автора

Всем привет! Хочу показать как можно работать с формами не прибегая к «фримворкам» в несколько килобайт кода.

Вступление

Как то раз пришлось мне создать небольшой проект портала с большим количеством форм как в «back» так и в «front» и тут возник вопрос что использовать? Сначала решил прикрутить что то на подобии Symfony. Но при разработке вышло такое количество строк кода что через некоторое время я сам начал путаться. И тут я решил изобрести велосипед.

Разработка

Для начала создал все таблицы в БД, вот например листинг одной:

CREATE TABLE IF NOT EXISTS `cms_articles` (   `id` int(11) NOT NULL AUTO_INCREMENT,   `title` varchar(255) DEFAULT NULL,   `article` text,   `author` varchar(255) DEFAULT NULL,   `edited` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,   `url` varchar(100) DEFAULT NULL,   `rating` int(10) NOT NULL DEFAULT '0',   `views` int(10) NOT NULL DEFAULT '0',   `comments` int(10) unsigned NOT NULL DEFAULT '0',   `parent` int(10) NOT NULL DEFAULT '0',   `key` text NOT NULL,   `desc` text NOT NULL,   `tags` varchar(250) NOT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB  DEFAULT CHARSET=utf8; 

Следующим этапом стало написание HTML кода для формы.
И тут начинается суть моего способа: название элементов в шаблоне должно соответствовать названиям полей таблицы.

<body> <font size='5px' class='title'>[page:name]</font> <span style="float: right; padding-top: 10px;">[page:path]</span>  [page:message]  <form class="form-list" action="" method="post" name="Form" enctype="multipart/form-data" accept-charset="UTF-8">  <div class="section"> <ul class="tabs"> 	<li class="current"><a href="#tab1">Основные параметри статьи</a></li> 	<li class=""><a href="#tab2">Текст статьи</a></li> </ul> 	 <div class="boxu visible"> 		 <div class="item"> 	<label>Заголовок</label><span class="required">*</span><br> 		<input type="text" class="big" value="" name="title"> 	<br> 	<label class="descript">Заголовок должен содержать смысл страницы</label>     </div>  <div class="item"> 	<label>Родитель</label><br>                       	 	<select class="big" name="parent" id=""> 		<option selected value="153">- без родителя -</option> 		[page:parent] 	</select><br> 	<label class="descript">Содержимое, к которому добавляется страница</label></div><div class="item "> 	 	<label>Адрес</label><br> 	<input type="text" class="medium" value="" name="url"> 	<br> 	<label class="descript">URL адрес страницы</label>     </div>  <div class="item"> 	<label>Автор</label><br> 		<input type="text" class="big" value="" name="author"> 	<br> 	<label class="descript">Автор статти ...</label>     </div>  <div class="item"> 	<label>Описание</label><br>                       	 	<textarea  class="" name="desc" rows="2"></textarea><br>   	<label class="descript">Краткое описание сайта. Используются поисковыми системами (Яндекс, Google...)</label> </div>  <div class="item"> 	<label>Ключевые слова</label><br>                       	 	<textarea name="key" rows="2"></textarea><br>  	<label class="descript">Ключевые слова через запятую. Используются поисковыми системами (Яндекс, Google...)</label> </div>  <table width="600px"> <tr><td>  <div class="item"> 	<label>Рейтинг</label><br> 		<input type="text" class="lbig" value="" name="rating"> 	<br> 	<label class="descript">Рейтинг статти ...</label>     </div>  </td><td>  <div class="item"> 	<label>Просмотры</label><br> 		<input type="text" class="lbig" value="" name="views"> 	<br> 	<label class="descript">Количество просмотров ...</label>     </div>  </td></tr> </table>  <div class="item"> 	<label>Разрешыть коментирование</label><br>   	<span><input name="comments" type="radio" value="1" checked>Да</span> 	<span><input name="comments" type="radio" value="0">Нет</span><br> 	Пользователи могут оставлять коментарии.<br> </div>  </div> 		 <div class="boxu">  <div class="item"> 	<label>Текст</label><br>                       	 	<textarea name="article" rows="28" id="article"></textarea><br>   	<label class="descript">Текст страницы. Разрешено использование HTML тегов</label> </div>  <div class="item"> 	<label>Теги</label><br> 		<input type="text" style="width: 200px;" value="" name="tags" id="tags"><br> 	<label class="descript">Теги к даному тексту (Вводить через кому).</label>     </div>  <div class="item-buttons"> 	<input type="submit" name="submit" id="submit" value="Сохранить"> </div>  </div> </div>		 </form> </body> 

Вот как выглядит форма (Орфографические ошибки на рисунке остались от заказчика я их не правил):

Далее сохранил шаблон в файл, под названием «article.tpl». И начал писать обработчик. Для его написание решил использовать DOM кто хочет пускай перепишет под «simpleDom».

Вот маленькая функция которая находит элемент по названию а не по ID.

	private function GetElementByName($_dom, $_name){ 		// Experimental search by name 		$xpath = new DOMXPath($_dom); 		return $xpath->query('//*[@name="'.$_name.'"]')->item(0); 	} 

Вот тут я написал функцию которая автоматически заполняет форму из таблицы. Учитывая тип элемента и его свойства.

	public function LoadShowFormAll($query, $template) { 	 	$page_encoding = 'UTF-8';      $dom = new DomDocument();     @$dom->loadHTML('<meta http-equiv="content-type" content="text/html; charset=' . $page_encoding . '">' .  file_get_contents(TMP_DIR.$template.".tpl"));      if ($result = $this->base->select($query)) { 	 	foreach ($result as $key => $value) {	         $obj = $this->GetElementByName($dom, $value['name']);  //$dom->getElementById($val->name); 		             switch ($obj->nodeName) {                 case "input":                     if ($obj->getAttribute('type') == 'radio') {                          $optionTags = $dom->getElementsByTagName('input');                         for ($i = 0; $i < $optionTags->length; $i++) {                              if ($optionTags->item($i)->getAttribute('name') == $value['name']) {                                 if ($optionTags->item($i)->getAttribute('value') == $value['param']) {                                      $optionTags->item($i)->SetAttribute('checked', 'checked');                                 }                             }                         }                          if ($value['param'] == 1) {                             $obj->SetAttribute('checked', 'checked');                         }                     } else                     if ($obj->getAttribute('type') == 'checkbox') {                          if ($value['param'] == 1) {                             $obj->SetAttribute('checked', 'checked');                         }                     } else {                         $obj->SetAttribute('value', $value['param']);                     }                     break;                  case "textarea":                     $obj->nodeValue = $value['param'];                     break;                  case "select":                     $optionTags = $obj->getElementsByTagName('option');                     for ($i = 0; $i < $optionTags->length; $i++) {                          if ($optionTags->item($i)->getAttribute('value') == $value['param']) {                             $optionTags->item($i)->SetAttribute('selected', 'selected');                         }                     }                     break;                  case "":                     break; 			} 		} 	}	 	preg_match_all("#<body>(.*)</body>#isUu", $dom->saveHTML(), $str);	 	return $str[1][0]; 	} 

Использовать следующим образом:

echo $Core->LoadShowForm('SELECT * FROM cms_articles WHERE id='.(int)($get_id), 'article'); 

После этого возникла необходимость сохранять значения в базу и изменять их для этих заданий я написал две простые функции.

	public function InsertNewValue($post, $table, $custom = null) {      $query = '';     $sep = false;     $tmp = array();      if ($result = $this->base->query("SELECT * FROM `$table` LIMIT 1")) {         $fields = $result->fetch_fields();     } else {         return false;         exit();     }      foreach ($post as $col => $val) {         $col = mysql_real_escape_string($col);         $val = mysql_real_escape_string($val);          $tmp[$col] = $val;     }      if ($custom != null) {          foreach ($custom as $col => $val) {             $col = mysql_real_escape_string($col);             $val = mysql_real_escape_string($val);              $tmp[$col] = $val;         }     }      foreach ($tmp as $column => $val) {          foreach ($fields as $fval) {             if ($column == $fval->name) {                  if ($sep == true) {                     $query .= ", `$column` = '$val'";                 } else {                     $query .= "`$column` = '$val'";                 }                 $sep = true;             }         }     }      return $this->base->query("INSERT INTO `$table` SET " . $query); 	}  	function UpdateValue($post, $table, $custom = null, $where) {      $query = '';     $sep = false;     $tmp = array();      if ($result = $this->base->query("SELECT * FROM `$table` LIMIT 1")) {         $fields = $result->fetch_fields();     } else {         return false;         exit();     }      foreach ($post as $col => $val) {         $col = mysql_real_escape_string($col);         $val = mysql_real_escape_string($val);          $tmp[$col] = $val;     }      if ($custom != null) {          foreach ($custom as $col => $val) {             $col = mysql_real_escape_string($col);             $val = mysql_real_escape_string($val);              $tmp[$col] = $val;         }     }      foreach ($tmp as $column => $val) {          foreach ($fields as $fval) {             if ($column == $fval->name) {                  if ($sep == true) {                     $query .= ", `$column` = '$val'";                 } else {                     $query .= "`$column` = '$val'";                 }                 $sep = true;             }         }     }      return $this->base->query("UPDATE `$table` SET " . $query . " WHERE " . $where); 	} 

Ну и остальная часть:

$Core->UpdateValue($_POST, 'cms_articles', null, ' id='.(int)($get_id));	// обновление $Core->InsertNewValue($_POST, 'cms_articles');  

Заключение

Лично мне очень понравилось работать таким образом с формами (При том что в проекте их было приблизительно: 250).
При необходимости добавления в форму элемента нужно прописать код в шаблоне и добавить значение в базе и все.

Большое спасибо!

ссылка на оригинал статьи http://habrahabr.ru/post/214085/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *