Упрощаем обработку форм


В этом уроке вы узнаете, как использовать переменные переменных, поиск в массивах, для того, чтобы значительно упростить процесс обработки форм. Так же мы покажем вам, как сэкономить время и упростить ваш код, не теряя при этом в функциональности. Переменные переменных, методы и свойства Переменные переменных – это термин, который описывает механизм объявления переменной благодаря другой переменной. Вот небольшой пример: 1 $foo = 'A value!'; // Присваиваем значение переменной; 2 $bar = 'foo'; // Другой переменной присваиваем название первой переменной; 3 echo $$bar; // Вывод: 'A value!' Почему это важно? На первый взгляд, использование переменных переменных может показаться какой-то глупостью и усложнением жизни, однако существует целый набор ситуаций, где применение данной техники может сэкономить множество времени. Практический пример Разумное использование переменных переменных может значительно сократить объём кода. Например в случае когда нам нужно создать ассоциативный массив из некоторых значений. Пример без переменных переменных: 1 $comment = new stdClass(); // Создаём объект 2 3 $comment->name = sanitize_value($array['name']); 4 $comment->email = sanitize_values($array['email']); 5 $comment->url = sanitize_values($array['url']); 6 $comment->comment_text = sanitize_values($array['comment_text']); Пример с переменной переменных: 1 $comment = new stdClass(); // Создаём объект 2 3 foreach( $array as $key=>$val ) 4 { 5 $comment->$key = sanitize_values($val); 6 } Второй вариант намного нагляднее и проще. Если вас это не впечатлило представьте что объекту нужно присвоить 50 или 100 значений. Внимание: вы конечно же можете использовать array_map в своих целях, но не в этом дело. Я пытаюсь изложить саму концепцию данной техники, так что поехали дальше. Трудности обработки форм Теперь, когда вы знаете как работают переменные переменны мы можем перейти к самому интересному, точнее к самой сути данной статьи, а именно к обработке форм. Использование данной техники устранит надобность в лишних системах контроля, выражений switch, а так же дублирования кода. Для того чтобы наглядно продемонстрировать идею мы будем работать над обработкой формы. Все разработчики сталкивались с подобной задачей! Постарайтесь настроиться на другой лад. Сейчас вы переоцените ваш способ кодирования. Часто для обработки файла используются отдельные файлы или один файл. Мы рассмотрим оба случая, а затем пример с использованием переменных, чтобы увидеть все преимущества данного метода. Пример обработки формы в отдельном файле Самый распространённый способ обработки форм – это вынос всей функциональности в отдельный файл. Вашему вниманию представляю три формы, которые предназначены для изменения имени, email пользователя или всего сразу. 01 <form action="assets/inc/ex1-form1.php" 02 method="post" 03 id="ex1-form1"> 04 <div> 05 <h4>Форма 1</h4> 06 <label>Имя 07 <input type="text" name="name" class="input-text" /> 08 </label> 09 <input type="submit" class="input-submit" value="Submit" /> 10 <input type="hidden" name="token" value="секретное значение" /> 11 </div> 12 </form> 13 14 <form action="assets/inc/ex1-form2.php" 15 method="post" 16 id="ex1-form2"> 17 <div> 18 <h4>Форма 2</h4> 19 <label>Email 20 <input type="text" name="email" class="input-text" /> 21 </label> 22 <input type="submit" class="input-submit" value="Submit" /> 23 <input type="hidden" name="token" value="секретное значение " /> 24 </div> 25 </form> 26 27 <form action="assets/inc/ex1-form3.php" 28 method="post" 29 id="ex1-form3"> 30 <div> 31 <h4>Форма 3</h4> 32 <label>Имя 33 <input type="text" name="name" class="input-text" /> 34 </label> 35 <label>Email 36 <input type="text" name="email" class="input-text" /> 37 </label> 38 <input type="submit" class="input-submit" value="Submit" /> 39 <input type="hidden" name="token" value="секретное значение" /> 40 </div> 41 </form> Для обработки каждой из этих форм, создадим отдельный файл. Вот так они будут выглядеть: Обработка формы 1 (assets/inc/ex1-form1.php) 01 <?php 02 03 // Включаем полно отображение ошибок, нотайсов и ворнингов 04 error_reporting(E_ALL); 05 ini_set('display_errors', 1); 06 07 // Убеждаемся, что форма действительно была отправлена 08 if( isset($_POST['token']) && $_POST['token']===' секретное значение ' ) 09 { 10 // Подключаем класс 11 require_once 'class.copterlabs_account.inc.php'; 12 13 // Создаём объект класса 14 $account_obj = new CopterLabs_Account(); 15 16 // Сохраняем данные 17 $output = $account_obj->save_name(); 18 19 echo "<pre>Файл обработчик: ", $_SERVER['PHP_SELF'], 20 "\n\n<strong>Метод выдал:</strong>\n", $output, "</pre>\n", 21 '<p><a href="../../">Назад</a></p>'; 22 } 23 else { 24 die( 'Заполните все поля' ); 25 } Обработка формы 2 (assets/inc/ex1-form2.php) 01 <?php 02 03 error_reporting(E_ALL); 04 ini_set('display_errors', 1); 05 06 if( isset($_POST['token']) && $_POST['token']==='secret token goes here' ) 07 { 08 require_once 'class.copterlabs_account.inc.php'; 09 $account_obj = new CopterLabs_Account(); 10 11 $output = $account_obj->save_email(); 12 13 echo "<pre> Файл обработчик: ", $_SERVER['PHP_SELF'], 14 "\n\n<strong> Метод выдал:</strong>\n", $output, "</pre>\n", 15 '<p><a href="../../">Назад</a></p>'; 16 } 17 else { 18 die( ' Заполните все поля ' ); 19 } Обработка формы 3 (assets/inc/ex1-form3.php) 01 <?php 02 03 error_reporting(E_ALL); 04 ini_set('display_errors', 1); 05 06 if( isset($_POST['token']) && $_POST['token']==='secret token goes here' ) 07 { 08 require_once 'class.copterlabs_account.inc.php'; 09 10 $account_obj = new CopterLabs_Account(); 11 12 $output = $account_obj->save_both(); 13 14 echo "<pre> Файл обработчик: ", $_SERVER['PHP_SELF'], 15 "\n\n<strong> Метод выдал:</strong>\n", $output, "</pre>\n", 16 '<p><a href="../../">Назад</a></p>'; 17 } 18 else { 19 die( ' Заполните все поля ' ); 20 } Как вы уже могли заметить, в этих файлах присутствует дублирование кода. А что если таких файлов будет намного больше? Тогда это будет просто кошмар! Класс Account Вы наверное заметили, что в трёх предыдущих примерах используется класс CopterLabs_Account. Это очень простой класс, который выводит информацию, которую ввёл пользователь. Вот код данного класса (assets/inc/class.coperlabs_account.inc.php): 01 <?php 02 03 class CopterLabs_Account 04 { 05 06 public $name = NULL, 07 $email = NULL; 08 09 public function save_name() 10 { 11 $this->name = htmlentities($_POST['name'], ENT_QUOTES); 12 13 return "Method: " . __METHOD__ . "\nName: " . $this->name . "\n"; 14 } 15 16 public function save_email() 17 { 18 $this->email = htmlentities($_POST['email'], ENT_QUOTES); 19 20 return "Method: " . __METHOD__ . "\nEmail: " . $this->email . "\n"; 21 } 22 23 public function save_both() 24 { 25 $this->name = htmlentities($_POST['name'], ENT_QUOTES); 26 $this->email = htmlentities($_POST['email'], ENT_QUOTES); 27 28 return "Method: " . __METHOD__ . "\nName: " . $this->name . "\nEmail: " 29 . $this->email . "\n"; 30 } 31 32 } Думаю, тут вопросов нет. Пойдём дальше. Реализация подобного функционала в одном файле с применением switch Другой довольно-таки распространённый вариант обработки форм сводится к размещению всех проверок в одном файле. Тут главным помощником будет выражение switch, которая будет вызывать соответствующую обработку формы. Вот несколько обновлённый код наших форм: 01 <form action="assets/inc/ex2-switch.php" 02 method="post" 03 id="ex1-form1"> 04 <div> 05 <h4>Форма 1</h4> 06 <label>Имя 07 <input type="text" name="name" class="input-text" /> 08 </label> 09 <input type="submit" class="input-submit" value="Submit" /> 10 <input type="hidden" name="action" value="update-name" /> 11 <input type="hidden" name="token" value="секретное значение" /> 12 </div> 13 </form> 14 15 <form action="assets/inc/ex2-switch.php" 16 method="post" 17 id="ex1-form2"> 18 <div> 19 <h4>Форма 2</h4> 20 <label>Email 21 <input type="text" name="email" class="input-text" /> 22 </label> 23 <input type="submit" class="input-submit" value="Submit" /> 24 <input type="hidden" name="action" value="update-email" /> 25 <input type="hidden" name="token" value="секретное значение " /> 26 </div> 27 </form> 28 29 <form action="assets/inc/ex2-switch.php " 30 method="post" 31 id="ex1-form3"> 32 <div> 33 <h4>Форма 3</h4> 34 <label>Имя 35 <input type="text" name="name" class="input-text" /> 36 </label> 37 <label>Email 38 <input type="text" name="email" class="input-text" /> 39 </label> 40 <input type="submit" class="input-submit" value="Submit" /> 41 <input type="hidden" name="action" value="update-both" /> 42 <input type="hidden" name="token" value="секретное значение" /> 43 </div> 44 </form> Обработка выглядит следующим образом (assets/inc/ex2-switch.php): 01 <?php 02 03 error_reporting(E_ALL); 04 ini_set('display_errors', 1); 05 06 if( isset($_POST['token']) && $_POST['token']==='secret token goes here' ) 07 { 08 require_once 'class.copterlabs_account.inc.php'; 09 10 $account_obj = new CopterLabs_Account(); 11 12 // Фильтруем данные 13 $action = htmlentities($_POST['action'], ENT_QUOTES); 14 15 switch( $action ) 16 { 17 // Form 1 18 case 'update-name': 19 $output = $account_obj->save_name(); 20 break; 21 22 // Form 2 23 case 'update-email': 24 $output = $account_obj->save_email(); 25 break; 26 27 // Form 3 28 case 'update-both': 29 $output = $account_obj->save_both(); 30 break; 31 32 default: 33 die( 'Неизвестное действие.' ); 34 } 35 36 echo "<pre> Файл обработчик: ", $_SERVER['PHP_SELF'], 37 "\nДействие: ", htmlentities($_POST['action'], ENT_QUOTES), 38 "\n\n<strong> Метод выдал:</strong>\n", $output, "</pre>\n", 39 '<p><a href="../../#ex2">Вернуться</a></p>'; 40 } 41 else { 42 die( ' Заполните все поля ' ); 43 } Этот вариант значительно лучше предыдущего. Однако мы всё ещё дублируем код. Вообще использовать switch надо очень осторожно. Дело в том, что ‘string’ при конвертации в int даст 0, так что в определённых случаях может получиться некая каша, которую разгрести будет нелегко. Решаем проблему! Используем переменные переменных Как мы уже увидели, предыдущие методы имеют свои недостатки, касающиеся в основном дублирования кода. Сложно себе представить, что будет твориться, если форм будет намного больше. В качестве решения данной проблемы, я предлагаю использовать поиск в массиве, для нахождения необходимых нам значений и применения данных значений в качестве вызова методов. Рабочий пример Применим наши знания, касающиеся переменных переменных. Изменим немного наши формы: 01 <form action="assets/inc/ex3-lookup-array.php" 02 method="post" 03 id="ex1-form1"> 04 <div> 05 <h4>Форма 1</h4> 06 <label>Имя 07 <input type="text" name="name" class="input-text" /> 08 </label> 09 <input type="submit" class="input-submit" value="Submit" /> 10 <input type="hidden" name="action" value="update-name" /> 11 <input type="hidden" name="token" value="секретное значение" /> 12 </div> 13 </form> 14 15 <form action="assets/inc/ex3-lookup-array.php" 16 method="post" 17 id="ex1-form2"> 18 <div> 19 <h4>Форма 2</h4> 20 <label>Email 21 <input type="text" name="email" class="input-text" /> 22 </label> 23 <input type="submit" class="input-submit" value="Submit" /> 24 <input type="hidden" name="action" value="update-email" /> 25 <input type="hidden" name="token" value="секретное значение " /> 26 </div> 27 </form> 28 29 <form action="assets/inc/ex3-lookup-array.php" 30 method="post" 31 id="ex1-form3"> 32 <div> 33 <h4>Форма 3</h4> 34 <label>Имя 35 <input type="text" name="name" class="input-text" /> 36 </label> 37 <label>Email 38 <input type="text" name="email" class="input-text" /> 39 </label> 40 <input type="submit" class="input-submit" value="Submit" /> 41 <input type="hidden" name="action" value="update-both" /> 42 <input type="hidden" name="token" value="секретное значение" /> 43 </div> 44 </form> А теперь, обработаем всё это дело (assets/inc/ex3-lookup-array.php): 01 <?php 02 03 error_reporting(E_ALL); 04 ini_set('display_errors', 1); 05 06 if( isset($_POST['token']) && $_POST['token']==='secret token goes here' ) 07 { 08 require_once 'class.copterlabs_account.inc.php'; 09 10 $account_obj = new CopterLabs_Account(); 11 12 $action = htmlentities($_POST['action'], ENT_QUOTES); 13 14 // Создадим массив, который будет содержать названия методов 15 $lookup_array = array( 16 'update-name' => 'save_name', 17 'update-email' => 'save_email', 18 'update-both' => 'save_both' 19 ); 20 21 // Убедимся, что данные имеются в массиве 22 if( array_key_exists($action, $lookup_array) ) 23 { 24 // Используем переменные переменных, чтобы вызвать соответствующие методы класса 25 $output = $account_obj->$lookup_array[$action](); 26 } 27 else { 28 die( 'Неизвестное действие.' ); 29 } 30 31 echo "<pre> Файл обработчик: ", $_SERVER['PHP_SELF'], 32 "\nДействие: ", htmlentities($_POST['action'], ENT_QUOTES), 33 "\n\n<strong> Метод выдал:</strong>\n", $output, "</pre>\n", 34 '<p><a href="../../#ex3">Назад</a></p>'; 35 } 36 else { 37 die( 'Заполните все поля' ); 38 } Мы используем метод array_key_exists для того, чтобы определить валидность запрашиваемого действия. Затем мы используем проверяемое значение для вызова одноимённого метода. Заметьте, для этого мы приписали () Вот так вот мы решили данную задачу при помощи переменных переменных. Всё просто, чисто и понятно. Обобщим Использование массивов и их комбинирование с переменными переменных могут значительно облегчить процесс разработки ваших скриптов. Ждём комментариев!