Skip to content

Instantly share code, notes, and snippets.

@may-cat
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save may-cat/2a2b3e024a65ae8e4f5c to your computer and use it in GitHub Desktop.
Save may-cat/2a2b3e024a65ae8e4f5c to your computer and use it in GitHub Desktop.
Beautiful forms / All forms are equal
<?php
// Читаем данные об элементе, если это возможно
$arElement = getElement();
/**
* С помощью статичного класса Generator мы создаём объект "Форма" класса MyForm,
* которому скармливаем всё, что нам сейчас известно.
* Можно обойтись и без него, но только до тех пор, пока у вас одни поля формы не зависят от других.
* Если от выбора, например, пола пользователя, зависят надписи, а то и вовсе - вопросы, которые будут заданы -
* лучше использовать данный паттерн.
*/
$rsForm = Generator::generateForm($arElement, $_REQUEST);
if (isDataSubmitted())
{
// Если данные валидны - пробуем сохранить, если нет - зовём коллбэк и успокаиваемся
if ($arValidData = $rsForm->isValid()){
if (save($arValidData))
{
on_success();
} else {
on_fault();
}
}else{
on_invalid();
}
}else{
render_form(); // @notice: в шаблоне нужно сделать доступным объект $rsForm, чтобы вытаскивать информацию о
// структуре формы прямо из него. Ниже будет рассказано как это.
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Generator
{
static function generateForm($arData, $USER_INPUT)
{
// тут подготавливаем на основе пришедших данных некий массив $myFields, структура которого задаётся сугубо ожиданиями класса MyForm
$myFields = array();
if ($arData['OK'])
$myFields = array(
'FIELD1'=>array(
'TYPE'=>'INTEGER'
)
);
else
$myFields = array(
'FIELD2'=>array(
'TYPE'=>'STRING'
)
);
// И потом конструктор объекта сделает всю магию
return new MyForm($myFields);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class MyForm
{
/**
* Удобно в свойстве классе прописать сразу пример того, как заполняются поля
* @var array
*/
var $exampleField = array(
'TYPE'=>'STRING' // STRING | INTEGER | ARRAY
);
/**
* @param $fields array of $exampleField
*/
function __constructor($fields, $userInput)
{
$this->fields = $fields;
$this->userInput = $userInput;
}
/**
* находит по $fieldName поле в $this->fields и echo'ает его в соответствии с типом
* @param $fieldName
*/
function echoField($fieldName)
{}
/**
* Проверяет все данные в $userInput на валидность.
* Учитывая, что у нас есть список полей и их типы данных, а также любые другие данные, что мы только захотели
* прописать каждому полю в его описании - мы можем полностью автоматизировать процесс валидации.
*/
function isValid()
{}
/**
* Возвращает список имеющихся полей.
* Если вы захотите хранить в $this->fields вложенную структуру данных (например, объединяя поля в группы),
* то тут придётся повозиться, но результат стоит труда
* @return array
*/
function getFields()
{
return array_keys($this->fields);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Пример шаблона
//
?>
<form method="post">
<? foreach ($rsForm->getFields() as $fieldCode) { ?>
<div class="wrapper">
<? $rsForm->echoField($fieldCode) ?>
</div>
<? } ?>
</form>
<?
/**
* Обратите внимание, что объект формы ничего не знает о:
* - хранении данных об элементе (чтении, сохранении)
* - логике отправки и получении данных (где эти данные - в $_REQUEST или где-то ещё - её не должно волновать)
*
* Генератор знает всё о:
* - том, какие поля, в каких ситуациях надо выводить, а какие не надо
*
* Форма всё знает о:
* - списке полей
* - свойствах каждого из полей
* - том, какие данные можно пользователю вводить, какие - нельзя
* - том, как выглядят отдельные поля, но не тем, что их обрамляет и/или как это всё обрабатывается
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment