Статьи

Упростите обработку форм на большом пути

Сэкономьте время, уменьшите затраты на обслуживание, упростите свой код и делайте все это, чувствуя себя чертовски гениальным! В этом руководстве вы узнаете, как использовать переменные переменные, массивы поиска и немного умного программирования, чтобы значительно упростить обработку форм.


Прежде чем мы сможем слишком глубоко использовать массив поиска, важно сначала понять концепцию переменных переменных.

Variable variable — это термин, который описывает использование переменной для объявления другой переменной.

В простейшей форме переменная переменная может выглядеть так:

1
2
3
$foo = ‘A value!’;
$bar = ‘foo’;
echo $$bar;

Когда вы смотрите на подтверждение концепции, как в предыдущем примере, использование переменных переменных, вероятно, выглядит довольно глупо и слишком сложно. Однако в некоторых случаях существуют веские практические причины их использования.

Массивы поиска могут легко упростить ваш код

Ответственное использование переменных переменных может значительно сократить объем кода, который необходимо повторить, скажем, путем преобразования ассоциативного массива в объект с очищенными значениями.

Пример без переменных переменных

1
2
3
4
5
6
$comment = new stdClass();
 
$comment->name = sanitize_value($array[‘name’]);
$comment->email = sanitize_values($array[’email’]);
$comment->url = sanitize_values($array[‘url’]);
$comment->comment_text = sanitize_values($array[‘comment_text’]);

Пример с переменными переменными

1
2
3
4
5
6
$comment = new stdClass();
 
foreach( $array as $key=>$val )
{
    $comment->$key = sanitize_values($val);
}

Видите, насколько это было проще? И вы можете представить, как будет выглядеть пример без переменных переменных, если в массиве будет что-то вроде 50 или 100 значений.

ПРИМЕЧАНИЕ: я знаю, что вы также можете использовать array_map () и явно привести массив как объект, чтобы выполнить то же самое. Не в этом дело. Мы иллюстрируем концепцию здесь. Подыгрывать.


Сделать обработку формы бризом.

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

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

Однако, после переоценки ваших привычек кодирования, вы потенциально можете сделать обработку формы проще простого.

Часто либо отдельный файл создается для каждой обрабатываемой формы, либо используется оператор switch. В этом разделе мы рассмотрим, как могут быть реализованы оба решения, а затем рассмотрим решение с использованием переменных переменных и как оно может улучшить ваши проекты.

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

Возьмем, к примеру, эти три формы, которые обновляют учетную запись пользователя новым именем, новым адресом электронной почты или обеими:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<form action=»assets/inc/ex1-form1.php»
      method=»post»
      id=»ex1-form1″>
    <div>
        <h4>Form 1</h4>
        <label>Name
            <input type=»text» name=»name» class=»input-text» />
        </label>
        <input type=»submit» class=»input-submit» value=»Submit» />
        <input type=»hidden» name=»token» value=»secret token goes here» />
    </div>
</form>
 
<form action=»assets/inc/ex1-form2.php»
      method=»post»
      id=»ex1-form2″>
    <div>
        <h4>Form 2</h4>
        <label>Email
            <input type=»text» name=»email» class=»input-text» />
        </label>
        <input type=»submit» class=»input-submit» value=»Submit» />
        <input type=»hidden» name=»token» value=»secret token goes here» />
    </div>
</form>
 
<form action=»assets/inc/ex1-form3.php»
      method=»post»
      id=»ex1-form3″>
    <div>
        <h4>Form 3</h4>
        <label>Name
            <input type=»text» name=»name» class=»input-text» />
        </label>
        <label>Email
            <input type=»text» name=»email» class=»input-text» />
        </label>
        <input type=»submit» class=»input-submit» value=»Submit» />
        <input type=»hidden» name=»token» value=»secret token goes here» />
    </div>
</form>

Каждая из этих форм указывает на отдельный файл обработки. Так как же выглядит каждый из этих файлов?

Обработка формы 1 (assets / inc / ex1-form1.php)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
 
// Turn on error reporting so we can see if anything is going wrong
error_reporting(E_ALL);
ini_set(‘display_errors’, 1);
 
// Make sure our faux-token was supplied
if( isset($_POST[‘token’]) && $_POST[‘token’]===’secret token goes here’ )
{
    // Require the necessary class
    require_once ‘class.copterlabs_account.inc.php’;
 
    // Create a new instance of the class
    $account_obj = new CopterLabs_Account();
 
    // Handle the form submission
    $output = $account_obj->save_name();
 
    // For this example, just output some data about the form submission
    echo «<pre>Processing File: «, $_SERVER[‘PHP_SELF’],
            «\n\n<strong>Method Output:</strong>\n», $output, «</pre>\n»,
            ‘<p><a href=»../../»>Go back</a></p>’;
}
else
{
    die( ‘Invalid form submission’ );
}

Обработка формы 2 (assets / inc / ex1-form2.php)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
 
// Turn on error reporting so we can see if anything is going wrong
error_reporting(E_ALL);
ini_set(‘display_errors’, 1);
 
// Make sure our faux-token was supplied
if( isset($_POST[‘token’]) && $_POST[‘token’]===’secret token goes here’ )
{
    // Require the necessary class
    require_once ‘class.copterlabs_account.inc.php’;
 
    // Create a new instance of the class
    $account_obj = new CopterLabs_Account();
 
    // Handle the form submission
    $output = $account_obj->save_email();
 
    // For this example, just output some data about the form submission
    echo «<pre>Processing File: «, $_SERVER[‘PHP_SELF’],
            «\n\n<strong>Method Output:</strong>\n», $output, «</pre>\n»,
            ‘<p><a href=»../../»>Go back</a></p>’;
}
else
{
    die( ‘Invalid form submission’ );
}

Обработка формы 3 (assets / inc / ex1-form3.php)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
 
// Turn on error reporting so we can see if anything is going wrong
error_reporting(E_ALL);
ini_set(‘display_errors’, 1);
 
// Make sure our faux-token was supplied
if( isset($_POST[‘token’]) && $_POST[‘token’]===’secret token goes here’ )
{
    // Require the necessary class
    require_once ‘class.copterlabs_account.inc.php’;
 
    // Create a new instance of the class
    $account_obj = new CopterLabs_Account();
 
    // Handle the form submission
    $output = $account_obj->save_both();
 
    // For this example, just output some data about the form submission
    echo «<pre>Processing File: «, $_SERVER[‘PHP_SELF’],
            «\n\n<strong>Method Output:</strong>\n», $output, «</pre>\n»,
            ‘<p><a href=»../../»>Go back</a></p>’;
}
else
{
    die( ‘Invalid form submission’ );
}

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

Как видите, файлы обработки создают экземпляр класса CopterLabs_Account. Это будет очень простой класс, который выводит информацию о отправке формы.

Вот код для класса (assets / inc / class.coperlabs_account.inc.php):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
 
/**
 * A simple class to test form submissions
 *
 * PHP version 5
 *
 * LICENSE: Dual licensed under the MIT or GPL licenses.
 *
 * @author Jason Lengstorf <[email protected]>
 * @copyright 2011 Copter Labs
 * @license http://www.opensource.org/licenses/mit-license.html
 * @license http://www.gnu.org/licenses/gpl-3.0.txt
 */
class CopterLabs_Account
{
 
    public $name = NULL,
           $email = NULL;
 
    public function save_name()
    {
        $this->name = htmlentities($_POST[‘name’], ENT_QUOTES);
 
        return «Method: » .
    }
 
    public function save_email()
    {
        $this->email = htmlentities($_POST[’email’], ENT_QUOTES);
 
        return «Method: » .
    }
 
    public function save_both()
    {
        $this->name = htmlentities($_POST[‘name’], ENT_QUOTES);
        $this->email = htmlentities($_POST[’email’], ENT_QUOTES);
 
        return «Method: » .
                .
    }
 
}

Вы можете попробовать этот код в Примере 1 на демонстрационной странице.

Другое популярное решение для обработки форм — объединить все сценарии обработки в один файл и определить, что делать с данными, с помощью оператора switch.

Подход переключателя обычно использует прием, в котором скрытый ввод добавляется в форму, содержащую действие, которое необходимо выполнить при представлении. Эта
Затем действие используется, чтобы определить, что делать с формой.

Вот те же три формы сверху с добавленными действиями, все они указывают на один файл обработки:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<form action=»assets/inc/ex2-switch.php»
      method=»post»
      id=»ex2-form1″>
    <div>
        <h4>Form 1</h4>
        <label>Name
            <input type=»text» name=»name» class=»input-text» />
        </label>
        <input type=»submit» class=»input-submit» value=»Submit» />
        <input type=»hidden» name=»action» value=»update-name» />
        <input type=»hidden» name=»token» value=»secret token goes here» />
    </div>
</form>
 
<form action=»assets/inc/ex2-switch.php»
      method=»post»
      id=»ex2-form2″>
    <div>
        <h4>Form 2</h4>
        <label>Email
            <input type=»text» name=»email» class=»input-text» />
        </label>
        <input type=»submit» class=»input-submit» value=»Submit» />
        <input type=»hidden» name=»action» value=»update-email» />
        <input type=»hidden» name=»token» value=»secret token goes here» />
    </div>
</form>
 
<form action=»assets/inc/ex2-switch.php»
      method=»post»
      id=»ex2-form3″>
    <div>
        <h4>Form 3</h4>
        <label>Name
            <input type=»text» name=»name» class=»input-text» />
        </label>
        <label>Email
            <input type=»text» name=»email» class=»input-text» />
        </label>
        <input type=»submit» class=»input-submit» value=»Submit» />
        <input type=»hidden» name=»action» value=»update-both» />
        <input type=»hidden» name=»token» value=»secret token goes here» />
    </div>
</form>

И новый файл обработки выглядит так: (assets / inc / ex2-switch.php)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
 
// Turn on error reporting so we can see if anything is going wrong
error_reporting(E_ALL);
ini_set(‘display_errors’, 1);
 
// Make sure our faux-token was supplied
if( isset($_POST[‘token’]) && $_POST[‘token’]===’secret token goes here’ )
{
    // Require the necessary class
    require_once ‘class.copterlabs_account.inc.php’;
 
    // Create a new instance of the class
    $account_obj = new CopterLabs_Account();
 
    // Sanitize the action
    $action = htmlentities($_POST[‘action’], ENT_QUOTES);
 
    // Use the new ‘action’ hidden input to determine what action to call
    switch( $action )
    {
        // Form 1 handling
        case ‘update-name’:
            $output = $account_obj->save_name();
            break;
 
        // Form 2 handling
        case ‘update-email’:
            $output = $account_obj->save_email();
            break;
 
        // Form 3 handling
        case ‘update-both’:
            $output = $account_obj->save_both();
            break;
 
        // If no valid action is found, something isn’t right
        default:
            die( ‘Unsupported action.’ );
    }
 
    // For this example, just output some data about the form submission
    echo «<pre>Processing File: «, $_SERVER[‘PHP_SELF’],
            «\nAction: «, htmlentities($_POST[‘action’], ENT_QUOTES),
            «\n\n<strong>Method Output:</strong>\n», $output, «</pre>\n»,
            ‘<p><a href=»../../#ex2″>Go back to example 2</a></p>’;
}
else
{
    die( ‘Invalid form submission’ );
}

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

Вдобавок ко всему, это мое личное предпочтение — избегать выражений переключателя, когда могу. Это связано с тем, что switch использует произвольные сравнения («строка» будет запускать регистр 0, потому что строка оценивается как 0, если вы преобразуете ее в целое число), и его очень легко превратить в код спагетти.


Как мы уже видели, оба вышеупомянутых решения имеют свои недостатки и требуют дублирования кода. Представьте, если на сайте было дюжина или больше форм — не очень.

Чтобы решить эту проблему, мы можем использовать концепцию, называемую массивом поиска , которая отображает действия, передаваемые из формы, в метод, вызываемый для объекта.

Да, вы можете установить действие в качестве имени метода, но это позволяет фиктивной отправке формы вызывать любой открытый метод. Создание массива пары ключ-значение — это небольшой шаг, чтобы добавить немного больше контроля без особой дополнительной работы.

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

Измените три формы, чтобы они указывали на новый файл контроллера:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<form action=»assets/inc/ex3-lookup-array.php»
      method=»post»
      id=»ex3-form1″>
    <div>
        <h4>Form 1</h4>
        <label>Name
            <input type=»text» name=»name» class=»input-text» />
        </label>
        <input type=»submit» class=»input-submit» value=»Submit» />
        <input type=»hidden» name=»action» value=»update-name» />
        <input type=»hidden» name=»token» value=»secret token goes here» />
    </div>
</form>
 
<form action=»assets/inc/ex3-lookup-array.php»
      method=»post»
      id=»ex3-form2″>
    <div>
        <h4>Form 2</h4>
        <label>Email
            <input type=»text» name=»email» class=»input-text» />
        </label>
        <input type=»submit» class=»input-submit» value=»Submit» />
        <input type=»hidden» name=»action» value=»update-email» />
        <input type=»hidden» name=»token» value=»secret token goes here» />
    </div>
</form>
 
<form action=»assets/inc/ex3-lookup-array.php»
      method=»post»
      id=»ex3-form3″>
    <div>
        <h4>Form 3</h4>
        <label>Name
            <input type=»text» name=»name» class=»input-text» />
        </label>
        <label>Email
            <input type=»text» name=»email» class=»input-text» />
        </label>
        <input type=»submit» class=»input-submit» value=»Submit» />
        <input type=»hidden» name=»action» value=»update-both» />
        <input type=»hidden» name=»token» value=»secret token goes here» />
    </div>
</form>

Затем соберите файл обработки, который будет обрабатывать отправку форм (assets / inc / ex3-lookup-array.php):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
 
// Turn on error reporting so we can see if anything is going wrong
error_reporting(E_ALL);
ini_set(‘display_errors’, 1);
 
// Make sure our faux-token was supplied
if( isset($_POST[‘token’]) && $_POST[‘token’]===’secret token goes here’ )
{
    // Require the necessary class
    require_once ‘class.copterlabs_account.inc.php’;
 
    // Create a new instance of the class
    $account_obj = new CopterLabs_Account();
 
    // Sanitize the action
    $action = htmlentities($_POST[‘action’], ENT_QUOTES);
 
    // Set up a lookup array to match actions to method names
    $lookup_array = array(
        ‘update-name’ => ‘save_name’,
        ‘update-email’ => ‘save_email’,
        ‘update-both’ => ‘save_both’
    );
 
    // Make sure the array key exists
    if( array_key_exists($action, $lookup_array) )
    {
        // Using variable variables, call the proper method and store the output
        $output = $account_obj->$lookup_array[$action]();
    }
    else
    {
        die( ‘Unsupported action.’ );
    }
 
    // For this example, just output some data about the form submission
    echo «<pre>Processing File: «, $_SERVER[‘PHP_SELF’],
            «\nAction: «, htmlentities($_POST[‘action’], ENT_QUOTES),
            «\n\n<strong>Method Output:</strong>\n», $output, «</pre>\n»,
            ‘<p><a href=»../../#ex3″>Go back to example 3</a></p>’;
}
else
{
    die( ‘Invalid form submission’ );
}

Проверьте это на демонстрационной странице, опробовав формы в Примере 3 .

Поскольку мы устанавливаем действие в качестве ключа в массиве, мы используем array_key_exists (), чтобы убедиться, что действие действительно. Затем мы используем значение, которое соответствует действию, в качестве имени метода. Обратите внимание, что мы добавили скобки после значения, чтобы убедиться, что оно выполняется как метод.

Добавление массива поиска делает код лаконичным, простым и понятным (как только вы освоитесь с переменными).


Ответственные массивы, используемые ответственно, могут значительно упростить обновление и поддержку ваших сценариев, когда вы объединяете их с переменными переменными.

Как, по вашему мнению, вы можете интегрировать массивы поиска и переменные в свои проекты, чтобы упростить обслуживание? Дай мне знать в комментариях!