#php #oop #form-processing
#php #ооп #обработка формы
Вопрос:
Я создал класс элемента формы. Класс способен
- Создайте элементы HTML-формы и
- Подтвердите, была ли отправлена форма, и если да, загрузите отправленное значение для указанного элемента формы в объект, с которым выполняется работа на странице.
Я попытался сделать это как можно более общим, чтобы сделать его многоразовым, но поскольку я новичок в отношении ООП, было бы очень здорово, если бы кто-нибудь мог это проверить и сообщить мне, хорошо ли это ООП, а также, если это хорошее решение для того, чего я пытаюсь достичь.
Вот основная часть class_FormControl()
class FormControl{
var $finalcontrol;
var $class = "form-control";
var $form_error;
protected function StartFormatting($name, $label){
if (isset($_POST[$name]) AND $_POST[$name] != "") {
return false;
}
$this->finalcontrol = "<label for='$name' >$label</label>";
return true;
}
public function get_control(){
return $this->finalcontrol;
}
}
class TextBox extends FormControl{
public function CreateControl($obj, $name, $label, $placeholder, $value = ""){
if($this->StartFormatting($name, $label)){
$this->finalcontrol .= "<input type='text' class='$this->class' id='$name' name='$name' placeholder='$placeholder'";
if ($value != "") {
$this->finalcontrol .= " value='$value' ";
}
$this->finalcontrol .= ">";
return true;
}
$func = "set_" . $name;
$obj->$func($_POST[$name]);
return false;
}
}
И вот как я использую класс на странице формы:
$r1 = New Recipe();
$tbx = new TextBox();
$ctrl1 = $tbx->CreateControl($r1, "Name", "Nombre", "Nombre", $r1->get_Name());
Теперь, если значение $ctrl1 равно true, я продолжаю и сохраняю объект в базе данных.
Если $ ctrl1 равно false, я продолжаю и
echo $tbx->get_control();
в нужном месте на странице.
/ Спасибо!
Комментарии:
1. Это слишком много кода для отображения текстового поля…
2. @PeeHaa — Да, конечно, для отображения одного текстового поля это перебор. Но я думал, что наличие сотен полей на всех подстраницах, включая сохранение значений для объекта внутри класса, хотя в долгосрочной перспективе это окупится… Тогда, я думаю, ваш комментарий — это ответ «Нет» на вопрос 2. Отмечено.
3. Я не вижу преимуществ в использовании функции, чем стандартный HTML. Если вам нужна тысяча текстовых полей, вы можете использовать цикл.
4. И, не хочу показаться обескураживающим, но ваш ООП не опирается ни на какой объектный принцип, несмотря на то, что у вас есть базовый и дочерний классы, все это в значительной степени функциональное программирование. Кроме того, в PHP5 свойства также имеют уровни доступа, также в соответствии с соглашением о сообществе PHP методы должны быть
camelCase
.5. Совсем не обескураживает 🙂 Я очень благодарен за ваш отзыв и, потратив всего несколько минут на чтение, понимаю, что вы имеете в виду. Я вернусь к изучению, прежде чем продолжить. Спасибо!
Ответ №1:
Примечание: Это не единственный способ сделать это; это один из многих, и это моя личная интерпретация проблемы за 10 минут во время обеденного перерыва. Пожалуйста, имейте в виду, что это будет моя реализация с небольшим количеством информации, которую мне дали бы. В реальном мире я бы узнал больше о домене, но я бы все равно придерживался принципа единой ответственности в своих объектах и поддерживал бы все слабо связанным. Это основные моменты, которые следует убрать из этого поста.
ООП
Прежде всего, вам нужно думать в терминах объектов. У каждого объекта есть своя отдельная ответственность запись в Википедии:
В объектно-ориентированном программировании принцип единой ответственности гласит, что каждый контекст (класс, функция, переменная и т.д.) Должен иметь единую ответственность, и эта ответственность должна быть полностью инкапсулирована контекстом. Все его службы должны быть строго согласованы с этой ответственностью. [выделение мое собственное].
То, что вы делаете, это помещаете процедурный код в методы класса. Это не делает его объектно-ориентированным! Вам нужно изменить свое мышление!
Объекты
Вы создаете конструктор форм. Форма состоит из элементов. Мгновенно я думаю о:
- Объект
Form
- Объект
FormElement
Вышеуказанные объекты являются конкретными представлениями сущности или ValueObject. Дизайн, управляемый доменом.
FormElement
может быть интерфейсом, которому должны соответствовать все элементы формы (например, поля ввода, кнопки и т. Д.).
class Form
{
/**
* @var FormElement[]
*/
protected $elements;
/**
* Add a FormElement to the form
*
* @param FormElement $element
*/
public function addFormElement(FormElement $element)
{
$this->elements[] = $element;
}
}
interface FormElement
{
/**
* @return The generated html for the given form element
*/
public function getHtml();
}
Теперь все, что вам нужно сделать, это убедиться, что каждый из ваших объектов, которые реализуют, FormElement
возвращает именно то, что вы хотите в FormElement::getHtml()
методе, и все это будет по-прежнему отлично работать, когда вы добавляете новые элементы в Form
, потому что это будет то Form
, что вызывается getHtml()
в цикле для каждого из FormElement
объектов, прежде чем добавлять это к немусобственный HTML-код и его вывод.
Вот пример TextBoxFormElement
, который я бы использовал:
class TextBoxFormElement implements FormElement
{
/**
* @constructor
*
* This is where I am declaring that, for this to be a VALID object, it MUST have
* the following properties passed in
*
* @param string $name
* @param string $label
* @param string $placeholder
* @param string $value
*/
public function __construct($id, $class, $name, $label, $placeholder, $value)
{
$this->id = $id;
$this->class = $class;
$this->name = $name;
$this->label = $label;
$this->placeholder = $placeholder;
$this->value = $value;
}
/**
* Generate the html of this element
*
* @return string
*/
public function getHtml()
{
return sprintf(
"<input type='text' id='%s' class='%s' name='%s' label='%s' placeholder='%s' value='%s'>",
$this->id, $this->class, $this->name, $this->label, $this->placeholder, $this->value
);
}
}
Суперглобальные
Вы используете $_POST
и $_GET
в этих классах. Вы не должны этого делать. Вы должны выполнить следующее:
Для каждого объекта, который вы пишете, общедоступные методы этих объектов определяют их API. Вы пишете API для использования этих объектов. [Моя собственная цитата]
Фактически, наличие любого типа $_POST
или $_GET
связывает эти объекты с состоянием этих суперглобалов. Как вы собираетесь их тестировать? Вам придется имитировать (или подделывать) содержимое этих суперглобальных файлов каждый раз, когда вы хотите их протестировать.
Нет. Что вам следует сделать, так это на мгновение забыть о своем собственном приложении и закодировать эти объекты, чтобы вы могли использовать их в любом приложении. Затем вы передаете значения в конструктор объектов или методы. Не используйте $_POST
or $_GET
непосредственно в этом классе.
Заключение
Вы не пишете OO-код. Но я не собираюсь писать это для вас. Я, однако, напишу методы, которые, как я ожидаю, будут вызываться при использовании вашей библиотеки в надежде, что вы сможете сами определить свою собственную реализацию. Держите все отдельно, используйте единую ответственность за каждый объект (это не перебор, это объектно-ориентированное программирование) и продолжайте учиться:
// Sanitize and validate input data obviously you would have a RequestValidator used before you even get to this point, making sure exactly what you want can be used by the library
$name = $_POST['name'];
/** Create our form **/
$form = new Form;
/** TextBoxFormElement implements FormElement **/
$textBox1 = new TextBoxFormElement($name, 'Label', 'Placeholder' /** etc **/);
/** Add our FormElement **/
$form->addFormElement($textBox1);
/** Generate our html - the form generates it's own HTML as well as calling getHTML() on the FormElement objects in a loop **/
echo $form->getHtml();
Вот и ВСЕ. Это объектный API, который вы должны создать. Это должно быть так просто. Теперь идите вперед с этим волшебным знанием и учитесь.
Дополнительная информация: альтернативой является взглянуть на шаблон посетителя. По сути, вы отделяете то, что генерирует выходные данные, от того, что содержит данные. Вот больше информации по теме, если вы хотите взглянуть на это.
Всегда помните, что ваш код должен быть читабельным и простым для понимания, и если это поможет — вам следует создать несколько стандартных UML-диаграмм, которые будут сопровождать ваш код.
Комментарии:
1. хорошее объяснение поиска точного содержимого 🙂
2. Это лучший пример, с которым я столкнулся, для использования интерфейсов.