PHP скрипты: от отправки формы до регистрации пользователей

Раздел: Программирование на PHP -> Написание скриптов

Основные методы обработки форм в PHP

Как реализовать безопасную регистрацию пользователя с хранением пароля?

Наиболее эффективный подход использует расширение PDO и функцию password_hash для защиты учетных данных. Этот вариант универсален, совместим с разными базами данных и предотвращает SQL-инъекции.


<?php
// Файл register.php
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8';
$user = 'root';
$pass = '';

try {
    $pdo = new PDO($dsn, $user, $pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die('Ошибка подключения: ' . $e->getMessage());
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username']);
    $email = trim($_POST['email']);
    $password = $_POST['password'];

    // Валидация
    $errors = [];
    if (strlen($username) < 3) $errors[] = 'Имя должно содержать минимум 3 символа';
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'Некорректный email';
    if (strlen($password) < 6) $errors[] = 'Пароль должен быть длиннее 6 символов';

    if (empty($errors)) {
        $hash = password_hash($password, PASSWORD_DEFAULT);
        $stmt = $pdo->prepare('INSERT INTO users (username, email, password) VALUES (:username, :email, :password)');
        $stmt->execute([
            ':username' => $username,
            ':email' => $email,
            ':password' => $hash
        ]);
        echo 'Регистрация успешна';
    } else {
        foreach ($errors as $error) {
            echo '<p>' . htmlspecialchars($error) . '</p>';
        }
    }
}
?>

Php scripts (php скрипты)

Пояснение шагов: Создается подключение через PDO с обработкой исключений. После отправки формы выполняется валидация длины имени, формата email и длины пароля. Пароль хешируется, после чего данные вставляются подготовленным запросом, что защищает от инъекций. Вывод ошибок экранируется через htmlspecialchars.

Возможные проблемы и их решения:

  • Ошибка подключения: Неверные параметры DSN, имя пользователя или пароль. Проверьте настройки в файле конфигурации.
  • Дубликат email: Установите уникальный индекс на поле email в БД и обработайте исключение PDO с кодом 23000.
  • Неверный хеш при входе: Используйте password_verify для проверки пароля.

Как выполнить регистрацию с помощью mysqli?

Если расширение PDO недоступно, можно использовать mysqli. Однако требуется ручное экранирование и код становится более громоздким.


<?php
$mysqli = new mysqli('localhost', 'root', '', 'test');
if ($mysqli->connect_error) {
    die('Ошибка: ' . $mysqli->connect_error);
}
$mysqli->set_charset('utf8');

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $mysqli->real_escape_string(trim($_POST['username']));
    $email = $mysqli->real_escape_string(trim($_POST['email']));
    $password = $_POST['password'];
    $hash = password_hash($password, PASSWORD_DEFAULT);

    $query = "INSERT INTO users (username, email, password) VALUES ('$username', '$email', '$hash')";
    if ($mysqli->query($query)) {
        echo 'Регистрация успешна';
    } else {
        echo 'Ошибка: ' . $mysqli->error;
    }
}
?>

Пояснение: real_escape_string экранирует специальные символы, но не защищает от всех видов атак (например, числовые поля). Подготовленные запросы в mysqli существуют, но требуют отдельного синтаксиса.

Типичные ошибки:

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

Как отправить содержимое формы на почту без базы данных?

Для простых контактных форм достаточно функции mail(). Этот вариант не требует БД и подходит для сбора обращений.


<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = htmlspecialchars($_POST['name']);
    $email = htmlspecialchars($_POST['email']);
    $message = htmlspecialchars($_POST['message']);

    $to = 'admin@example.com';
    $subject = 'Сообщение с сайта от ' . $name;
    $body = "Имя: $name\nEmail: $email\nСообщение: $message";
    $headers = "From: $email\r\nReply-To: $email\r\nContent-Type: text/plain; charset=utf-8";

    if (mail($to, $subject, $body, $headers)) {
        echo 'Письмо отправлено';
    } else {
        echo 'Ошибка отправки';
    }
}
?>

Пояснение: Функция htmlspecialchars предотвращает XSS-атаки. Заголовок Content-Type задает кодировку письма. Для продакшена рекомендуется использовать библиотеки (PHPMailer, SwiftMailer) для надежной отправки.

Проблемы:

  • Функция mail() может не работать без локального почтового сервера.
  • Письма часто попадают в спам из-за отсутствия SPF/DKIM записей.

Как проверить корректность email и других полей формы?

Для фильтрации входных данных PHP предоставляет функции filter_var с константами FILTER_VALIDATE_EMAIL, FILTER_VALIDATE_URL и другие.


<?php
$email = 'user@example.com';
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo 'Email корректен';
} else {
    echo 'Email некорректен';
}

$url = 'https://example.com';
if (filter_var($url, FILTER_VALIDATE_URL)) {
    echo 'URL корректен';
}

// Фильтрация целого числа
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 120]]);
?>

Пояснение: filter_var возвращает отфильтрованное значение или false. Функция filter_input позволяет фильтровать данные прямо из суперглобальных массивов, что удобно.

Ошибки:

  • FILTER_VALIDATE_EMAIL не проверяет существование домена, только формат.
  • При использовании filter_input с несуществующим индексом возвращается null.

Расширенные примеры PHP скриптов

1. Скрипт отправки формы с вложением через MIME

Для отправки файлов на почту необходимо сформировать многочастное (multipart) письмо. Ниже приведен пример с использованием mail() и ручной сборки MIME.

Пример

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
    $to = 'admin@example.com';
    $subject = 'Форма с файлом';
    
    $boundary = md5(uniqid(time()));
    $headers = "From: sender@example.com\r\n";
    $headers .= "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n";
    
    // Текстовое содержимое
    $body = "--$boundary\r\n";
    $body .= "Content-Type: text/plain; charset=utf-8\r\n\r\n";
    $body .= "Имя: " . $_POST['name'] . "\r\n";
    $body .= "Email: " . $_POST['email'] . "\r\n";
    
    // Вложение
    $file = $_FILES['file'];
    if ($file['error'] === UPLOAD_ERR_OK) {
        $fp = fopen($file['tmp_name'], 'rb');
        $data = fread($fp, filesize($file['tmp_name']));
        fclose($fp);
        $data = chunk_split(base64_encode($data));
        $body .= "--$boundary\r\n";
        $body .= "Content-Type: application/octet-stream; name=\"{$file['name']}\"\r\n";
        $body .= "Content-Disposition: attachment; filename=\"{$file['name']}\"\r\n";
        $body .= "Content-Transfer-Encoding: base64\r\n\r\n";
        $body .= $data . "\r\n";
    }
    $body .= "--$boundary--";
    
    if (mail($to, $subject, $body, $headers)) {
        echo 'Письмо отправлено с вложением';
    } else {
        echo 'Ошибка отправки';
    }
}
?>
После успешной отправки на почтовый ящик admin@example.com придет письмо с текстом и прикрепленным файлом. В случае ошибки отобразится сообщение об ошибке.

2. Асинхронная обработка формы через AJAX (JSON ответ)

Пример обработки формы без перезагрузки страницы с использованием jQuery (файл server.php).

Пример

<?php
// server.php
header('Content-Type: application/json; charset=utf-8');

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = trim($_POST['name']);
    $email = trim($_POST['email']);
    
    $errors = [];
    if (empty($name)) $errors[] = 'Имя обязательно';
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'Email некорректен';
    
    if (empty($errors)) {
        // Логика сохранения или отправки
        $response = ['success' => true, 'message' => 'Данные приняты'];
    } else {
        $response = ['success' => false, 'errors' => $errors];
    }
    echo json_encode($response);
}
?>
При правильном заполнении формы сервер вернет: {"success":true,"message":"Данные приняты"}
При ошибке: {"success":false,"errors":["Имя обязательно"]}

3. Работа с сессиями: хранение корзины покупок

Простой скрипт для добавления товаров в корзину через сессию.

Пример

<?php
session_start();

// Добавление товара
if (isset($_GET['add']) && is_numeric($_GET['add'])) {
    $item_id = (int)$_GET['add'];
    if (!isset($_SESSION['cart'])) {
        $_SESSION['cart'] = [];
    }
    $_SESSION['cart'][] = $item_id;
}

// Вывод корзины
if (isset($_SESSION['cart'])) {
    echo 'Товары в корзине: ' . implode(', ', $_SESSION['cart']);
} else {
    echo 'Корзина пуста';
}
?>
После добавления товара с id=5 и id=3 скрипт выведет: Товары в корзине: 5, 3
При первом запуске (без сессии) выводится: Корзина пуста

Пояснение: session_start() инициирует сессию. Массив $_SESSION хранит данные между запросами. В реальных проектах корзина должна храниться в структурированном виде (например, с количеством товаров).

PHP скрипты - comments

En
Php scripts (php)