PHP: Какой лучший способ обработки данных формы?

#php #forms

#php #формы

Вопрос:

На моем веб-сайте у меня есть учетные записи пользователей, которые настраиваются с помощью форм, которые позволяют пользователям обновлять все, от имени и фамилии до настроек конфиденциальности. Я использую следующую функцию для обновления базы данных с помощью этого ввода. (Обратите внимание, что следующий код использует специфичные для WordPress функции.)

 function update_account() {
    global $current_user; get_currentuserinfo();
    require_once( ABSPATH . WPINC . '/registration.php' );

    $uid = $current_user->ID;

    // First Name
    if(isset($_POST['first_name']) amp;amp; $_POST['first_name'] <> $current_user->first_name) {
        wp_update_user( array( 
            'ID' => $uid, 'first_name' => esc_attr($_POST['first_name'])
        ));
    }

    // ...and so on 43 more times...

}
 

Это похоже на неправильный способ обработки форм. Также похоже, что это негативно скажется на производительности сервера при наличии нескольких пользователей и частых обновлениях, учитывая, что условия if-then-else для каждого поля, даже полей, отсутствующих на определенной странице, заставляют проверять каждое поле на ввод.

Более того, поскольку можно ожидать, что данные формы останутся относительно постоянными, я добавил оператор <>, чтобы функция не обновляла поля, в которых не было никаких изменений, но я подозреваю, что это также означает, что каждое поле по-прежнему оценивается на предмет изменений. Что еще хуже, добавление новых полей — всего их уже 44 — является громоздким процессом.

Какой лучший способ обработки данных формы?

Ответ №1:

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

 // All the fields you wish to process are in this array
$fields = array('first_name', 'last_name', 'others',...'others99');

// Loop over the array and process each field with the same block
foreach ($fields as $field) {
    if(isset($_POST[$field]) amp;amp; $_POST[$field] != $current_user->{$field}) {
        wp_update_user( array( 
            'ID' => $uid, $field => esc_attr($_POST[$field])
        ));
    }
}
 

Комментарии:

1. О, это интересно. Я мог бы даже сгенерировать массив из базы данных, чтобы не возиться с источником. Разве это не повторяется по каждому полю, даже по не относящимся к делу полям? Может ли большой массив оказать существенное влияние на процессор или память?

2. @fireundubh Он выполняет итерации только по полям, которые вы определили в массиве. Но если они не заданы $_POST , они будут пропущены в цикле, так же, как вы уже сделали с вашими 44 if() операторами. Я бы не стал беспокоиться о его производительности, пока вы действительно не обнаружите, что это проблематично, а затем настройте его.

3. Почему бы не отменить его и не проверить in_array($key) , с foreach ($_POST as $key => $val) помощью?

4. Я адаптировал ваше решение и извлек пары ключ-значение поля из базы данных. Необходимо решить некоторые проблемы SQL, связанные с безопасностью, но это другой вопрос. Спасибо.

Ответ №2:

В вашей реализации многого не хватает. Я не знаю, какими данными вы разрешаете пользователю манипулировать, но у большинства обычно есть какие-то приемлемые требования. Например, отсутствие определенных символов, отсутствие пробелов и т. Д. Я не вижу никакой проверки, так как же вы обрабатываете значения, которые могут быть нежелательными? И что происходит, когда вы получаете неверные данные? Как вы информируете пользователя о неверных данных и предлагаете им исправить это?

Если мы немного абстрагируемся от ситуации, мы можем прийти к обобщениям и реализовать соответствующее решение. В основном поля формы [могут] иметь значение по умолчанию, заданное пользователем значение [при просмотре формы], требования к проверке и ошибки проверки [с сообщениями]. Форма — это набор полей, которые при отправке формы должны быть проверены и, если они недействительны, повторно отображены пользователю с инструктивными подсказками для исправления.

Если мы создадим класс form, который инкапсулирует приведенную выше логику, мы сможем создать экземпляр и использовать его для передачи наших контроллеров / представлений. Упс, я просто предполагал, что вы используете фреймворк типа Model / View / Controller, и я не очень хорошо знаком с WordPress, поэтому я не знаю, применимо ли это в точности. Но принцип все еще применяется. На странице, где вы оба отображаете или обрабатываете форму, вот некоторая псевдологика, как это может выглядеть.

 function update_account()
{
    // initialize a new form class
    $form = new UserAccountInfoForm();
    // give the form to your view for rendering 
    $this->view->form = $form;
    // check if form was posted [however your framework provides this check]
    if(!Is_Post())
        return $this->render('accountform.phtml');
    // check if posted form data validates
    if(!$form->isValid($_POST))
    {
         // if the form didn't validate re-display the form
         // the view takes care of displaying errors, with the help of its
         // copy of the $form object
         return $this->render('accountform.phtml');
    }

    // form validated, so we can use the supplied values and update the db
    $values = $form->getValues(); // returns an array of ['fieldname'=>'value']
    // escape the values of the array
    EscapeArrayValues($values);
    // update db
    wp_update_user($values);
    // inform the user of successful update via flash message
    $this->flashMessage('Successfully updated profile');
    // go back to main profile page
    $this->redirect('/profile');
 

Это делает ваш контроллер относительно чистым и простым в работе. Представление получает некоторую любовь и заботу, используя значение $form для правильного отображения формы. Технически, вы можете реализовать метод в классе form, чтобы предоставить вам форму html, но для простоты я просто предположу, что ваш HTML-код формы вручную закодирован в accountform.phtml, и он просто использует $form для получения информации о поле

 <form action='post'>
<label>first name</label> <input class='<?=$this->form->getElement('first_name')->hasError() ? "invalid":""?>' type='text' name='first_name' value="<?=$this->form->getElement('first_name')->getValue()"/> <span class='errmsg'><?=$this->form->getElement('first_name')->getError()?></span><br/>

<label>last name</label> <input class='<?=$this->form->getElement('last_name')->hasError() ? "invalid":""?>' type='text' name='last_name' value="<?=$this->form->getElement('last_name')->getValue()"/> <span class='errmsg'><?=$this->form->getElement('last_name')->getError()?></span><br/>

<label>other</label> <input class='<?=$this->form->getElement('other')->hasError() ? "invalid":""?>' type='text' name='other' value="<?=$this->form->getElement('other')->getValue()"/> <span class='errmsg'><?=$this->form->getElement('other')->getError()?></span><br/>

<input type='submit' value='submit'/>
</form>
 

Здесь псевдокод основан на методе класса формы «getElement», который возвращает экземпляр класса field для указанного имени поля (который будет создан инициализированным в конструкторе вашего класса form). Затем в методах класса field «hasError» и «getError», чтобы проверить, правильно ли проверено поле. Если форма еще не отправлена, то они возвращают false и пустое значение, но если форма была опубликована и недействительна, то они будут соответствующим образом установлены в методе validate при его вызове. Также «GetValue» вернет либо значение, предоставленное пользователем при отправке формы, либо, если форма не была отправлена, значение по умолчанию, указанное при создании экземпляра и инициализации класса field.

Очевидно, что этот псевдокод использует много магии, которую вам придется реализовать, если вы создадите свое собственное решение — и это, безусловно, выполнимо. Однако на этом этапе я направлю вас к компонентам Zend Framework Zend_Form. Вы можете использовать компоненты zend Framework сами по себе без необходимости использовать всю структуру фреймворка и приложения. Вы также можете найти похожие решения для компонентов формы из других фреймворков, но я бы не знал о них (мы являемся магазином Zend Framework на моем рабочем месте).

Надеюсь, это не было слишком сложно, и вы знаете, что делать дальше. Конечно, просто спросите, нужны ли вам какие-либо разъяснения.