Массивы $_POST и $_GET в PHP. Обработка форм
Формы — это часть языка HTML. Формы нужны для передачи данных от клиента на сервер. Чаще всего формы используются для регистрации пользователей, заполнения анкет, оформления заказа в интернет магазине, и так далее.
Через формы можно отправлять как простую текстовую информацию, так и файлы.
Большую часть времени программирования на PHP вы будете так или иначе работать с формами и данными из них.
HTML описывает то, из каких элементов состоит форма, и как она выглядит. Но без принимающей стороны, то есть сервера, который принимает эти данные и обрабатывает их нужным образом, создавать формы нет никакого смысла.
PHP содержит множество средств для работы с формами. Это позволяет очень просто решать типичные задачи, которые часто возникают в веб-программировании:
- Регистрация и аутентификация пользователя;
- Отправка комментариев на форумах и социальных сетях;
- Оформление заказов.
Практически любой современный сайт содержит как минимум несколько разных HTML-форм.
Отправка формы
Рассмотрим один типичный пример — форма обратной связи. Для связи пользователей с авторами сайта, как правило, используются формы обратной связи, где человек указывает имя, почту для обратной связи и текст своего сообщения.
Такая форма в HTML может выглядеть следующим образом:
Это очень простая форма, состоящая из трёх полей и одной кнопки отправки.
Почти весь приведённый код описывает внешний вид и содержание формы, но следует обратить внимание на два атрибута тега , которые нужны для указания на способ обработки данных:
method — этот атрибут используется для определения метода HTTP, который будет использован для передачи данных на сервер. Вы уже знакомы с HTTP-методом GET, предписывающим серверу просто вернуть определённый документ.
Метод POST сообщает о намерении передать на сервер некоторую информацию, что, впрочем, не отменяет последующее получение контента.
action — содержит адрес PHP-скрипта, который должен обработать эту форму.
После нажатия на кнопку «отправить», браузер выполняет POST запрос со введёнными данными на адрес, указанный в атрибуте action.
Обработка формы
После отправки формы управление передаётся PHP-скрипту, который должен получить переданные данные, выполнить с ними какие-либо действия (например, сохранить в базе данных) и показать результат.
Результатом может быть какое-нибудь сообщение об успешном завершении операции, например, «ваши данные успешно отправлены».
Поэтому требуется в первую очередь научиться получать данные из формы в сценарии.
В PHP это делается легко — все данные из формы находятся в глобальном ассоциативном массиве $_POST . Этот массив всегда будет неявно присутствовать в сценарии, если он был загружен по методу POST.
Каждое поле из формы будет находиться в массиве, где ключом будет значение атрибута name, а значением содержимое поля. Например, чтобы вывести из формы всю информацию на экран, можно написать такой сценарий:
Email: " . $_POST['email']); print("
Сообщение: " . $_POST['message']); > ?>
Функция isset служит для определения, существует ли переданная ей переменная. Так мы проверяем, что сценарий загружен методом POST, то есть была отправлена форма.
Как правило, после обработки формы в PHP, сценарий должен переадресовать пользователя на другую страницу. Это связано с тем, что если форма была отправлена через метод POST, то после обновления страницы данные будут отправлены ещё раз, а это, в большинстве случаев, нежелательное поведение.
Отправка файлов
Кроме текстовой информации, существует возможность отправлять на сервер файлы любых типов. Пример формы для загрузки файла:
Тут есть два важных отличия от первого примера:
- Добавился новый атрибут enctype, который всегда должен иметь значение multipart/form-data . Если его не будет, то файл не отправится.
- Сам файл загружается при помощи поля с типом file.
В PHP загруженный файл будет доступен в другом специальном массиве — $_FILES .
PHP автоматически сохраняет все загруженные файлы во временную папку на сервере. Но хранить там файлы нельзя, потому что эта директория периодически очищается, и ссылку на такой файл нельзя дать на сайте. Решение здесь только одно — переместить загруженный файл в другую папку. Перемещение файла всегда выполняют сразу после загрузки.
Для начала нужно убедиться, что в рабочей директории проекта существует папка для хранения загруженных файлов. Пусть она называется uploads .
Перемещение загруженного файла
Для перемещения файла нужно знать, где он находится сейчас, и адрес папки, в которую он будет переноситься.
С текущим адресом всё крайне просто — он уже находится в массиве $_FILES . Новый адрес файла, в свою очередь, состоит из пути к папке и имени файла. Так как папка uploads находится там же, где и текущий сценарий, получить путь к ней можно так: dirname(__FILE__ )`.
Код для перемещения файла в новую папку:
Функция move_uploaded_file() выполняет два действия:
- Проверяет, что файл действительно загружен через форму.
- Перемещает загруженный файл по новому адресу.
Валидация формы
Валидация формы — это проверка содержимого её полей. Задача такой проверки — убедиться, что необходимые поля заполнены, а значения в них соответствуют ожидаемому формату.
Так, например, при регистрации пользователя на сайте, он должен заполнить поля с адресом электронной почты и придумать себе пароль. Оба поля обязательны к заполнению, но значение из поля email также должно быть корректным email-адресом.
Помимо текстовых значений формы, можно проверять формат и размер загружаемых файлов.
Общий подход к валидации
При выполнения валидации любой формы порядок действий будет всегда одним:
- Сформировать массив с именами полей, обязательных к заполнению.
- Сформировать массив с правилами для валидации формата полей.
- Получить значения всех полей.
Дополнительные материалы:
«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.
Php isset input type file
I think the way an array of attachments works is kind of cumbersome. Usually the PHP guys are right on the money, but this is just counter-intuitive. It should have been more like:
Array
(
[0] => Array
(
[name] => facepalm.jpg
[type] => image/jpeg
[tmp_name] => /tmp/phpn3FmFr
[error] => 0
[size] => 15476
)
Anyways, here is a fuller example than the sparce one in the documentation above:
foreach ( $_FILES [ «attachment» ][ «error» ] as $key => $error )
$tmp_name = $_FILES [ «attachment» ][ «tmp_name» ][ $key ];
if (! $tmp_name ) continue;
$name = basename ( $_FILES [ «attachment» ][ «name» ][ $key ]);
if ( $error == UPLOAD_ERR_OK )
if ( move_uploaded_file ( $tmp_name , «/tmp/» . $name ) )
$uploaded_array [] .= «Uploaded file ‘» . $name . «‘.
\n» ;
else
$errormsg .= «Could not move uploaded file ‘» . $tmp_name . «‘ to ‘» . $name . «‘
\n» ;
>
else $errormsg .= «Upload error. [» . $error . «] on file ‘» . $name . «‘
\n» ;
>
?>
Do not use Coreywelch or Daevid’s way, because their methods can handle only within two-dimensional structure. $_FILES can consist of any hierarchy, such as 3d or 4d structure.
The following example form breaks their codes:
As the solution, you should use PSR-7 based zendframework/zend-diactoros.
use Psr \ Http \ Message \ UploadedFileInterface ;
use Zend \ Diactoros \ ServerRequestFactory ;
$request = ServerRequestFactory :: fromGlobals ();
if ( $request -> getMethod () !== ‘POST’ ) http_response_code ( 405 );
exit( ‘Use POST method.’ );
>
$uploaded_files = $request -> getUploadedFiles ();
if (
!isset( $uploaded_files [ ‘files’ ][ ‘x’ ][ ‘y’ ][ ‘z’ ]) ||
! $uploaded_files [ ‘files’ ][ ‘x’ ][ ‘y’ ][ ‘z’ ] instanceof UploadedFileInterface
) http_response_code ( 400 );
exit( ‘Invalid request body.’ );
>
$file = $uploaded_files [ ‘files’ ][ ‘x’ ][ ‘y’ ][ ‘z’ ];
if ( $file -> getError () !== UPLOAD_ERR_OK ) http_response_code ( 400 );
exit( ‘File uploading failed.’ );
>
$file -> moveTo ( ‘/path/to/new/file’ );
The documentation doesn’t have any details about how the HTML array feature formats the $_FILES array.
Array
(
[document] => Array
(
[name] => sample-file.doc
[type] => application/msword
[tmp_name] => /tmp/path/phpVGCDAJ
[error] => 0
[size] => 0
)
)
Multi-files with HTML array feature —
Array
(
[documents] => Array
(
[name] => Array
(
[0] => sample-file.doc
[1] => sample-file.doc
)
(
[0] => application/msword
[1] => application/msword
) [tmp_name] => Array
(
[0] => /tmp/path/phpVGCDAJ
[1] => /tmp/path/phpVGCDAJ
)
The problem occurs when you have a form that uses both single file and HTML array feature. The array isn’t normalized and tends to make coding for it really sloppy. I have included a nice method to normalize the $_FILES array.
function normalize_files_array ( $files = [])
foreach( $files as $index => $file )
if (! is_array ( $file [ ‘name’ ])) $normalized_array [ $index ][] = $file ;
continue;
>
foreach( $file [ ‘name’ ] as $idx => $name ) $normalized_array [ $index ][ $idx ] = [
‘name’ => $name ,
‘type’ => $file [ ‘type’ ][ $idx ],
‘tmp_name’ => $file [ ‘tmp_name’ ][ $idx ],
‘error’ => $file [ ‘error’ ][ $idx ],
‘size’ => $file [ ‘size’ ][ $idx ]
];
>
?>
The following is the output from the above method.
Array
(
[document] => Array
(
[0] => Array
(
[name] => sample-file.doc
[type] => application/msword
[tmp_name] => /tmp/path/phpVGCDAJ
[error] => 0
[size] => 0
)
(
[0] => Array
(
[name] => sample-file.doc
[type] => application/msword
[tmp_name] => /tmp/path/phpVGCDAJ
[error] => 0
[size] => 0
) [1] => Array
(
[name] => sample-file.doc
[type] => application/msword
[tmp_name] => /tmp/path/phpVGCDAJ
[error] => 0
[size] => 0
)