Добавление нового пользователя: пошаговое руководство на PHP

Раздел: Разработка на PHP -> Управление пользователями

Безопасное добавление пользователя через PDO

Цель: защитить приложение от SQL-инъекций при вставке данных нового пользователя. Используется в проектах, работающих с различными базами данных (MySQL, PostgreSQL и др.). Основное преимущество - поддержка именованных плейсхолдеров и автоматическое экранирование.


$dsn = 'mysql:host=localhost;dbname=test;charset=utf8mb4';
$pdo = new PDO($dsn, 'root', '', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
$stmt = $pdo->prepare('INSERT INTO users (username, email, password) VALUES (:username, :email, :password)');
$stmt->execute([
    'username' => $_POST['username'],
    'email' => $_POST['email'],
    'password' => password_hash($_POST['password'], PASSWORD_DEFAULT),
]);
echo 'Пользователь создан';

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

Типичные ошибки: неправильный DSN, забыли установить кодировку utf8mb4, не обработано исключение при duplicate entry, неверно указаны имена полей в таблице. Для устранения дубликатов email следует проверить существование перед вставкой или использовать ON DUPLICATE KEY UPDATE.

Как создать пользователя с помощью MySQLi?

Цель: использовать встроенное расширение MySQLi для работы с MySQL. Подходит для проектов, где нет возможности перейти на PDO или требуется специфичная функциональность MySQL. MySQLi поддерживает как процедурный, так и объектно-ориентированный стиль.


$mysqli = new mysqli('localhost', 'root', '', 'test');
if ($mysqli->connect_error) {
    die('Ошибка подключения: ' . $mysqli->connect_error);
}
$stmt = $mysqli->prepare('INSERT INTO users (username, email, password) VALUES (?, ?, ?)');
$stmt->bind_param('sss', $username, $email, $hashedPassword);
$username = $_POST['username'];
$email = $_POST['email'];
$hashedPassword = password_hash($_POST['password'], PASSWORD_DEFAULT);
if ($stmt->execute()) {
    echo 'Пользователь создан';
} else {
    echo 'Ошибка: ' . $stmt->error;
}
$stmt->close();
$mysqli->close();

Пояснение: после создания объекта mysqli проверяется подключение. Затем готовится запрос с вопросительными знаками. bind_param привязывает переменные с указанием типов ('s' - строка). Выполнение проверяется по возвращаемому значению.

Проблемы: неправильный порядок или количество параметров в bind_param, неверно указан тип данных (например, 'i' для целого, 'd' для double). Отсутствие проверки возврата prepare() может привести к ошибке. Также не забыть закрыть соединение.

Как реализовать регистрацию через Laravel Eloquent?

Цель: использовать встроенные механизмы Laravel для быстрого создания пользователей. Подходит для проектов на этом фреймворке, где уже настроена миграция и модель User.


use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;

public function register(Request $request) {
    $validated = $request->validate([
        'name' => 'required|max:255',
        'email' => 'required|email|unique:users',
        'password' => 'required|min:8|confirmed',
    ]);
    $user = User::create([
        'name' => $validated['name'],
        'email' => $validated['email'],
        'password' => Hash::make($validated['password']),
    ]);
    return response()->json(['message' => 'Пользователь создан', 'user' => $user], 201);
}

Пояснение: метод validate проверяет входные данные. User::create массово присваивает атрибуты (необходимо указать fillable в модели). Hash::make хеширует пароль. Возвращается JSON-ответ.

Типичные ошибки: не заполнено свойство $fillable в модели, забыт middleware для CSRF, не настроена миграция таблицы users, конфликт уникальности email при параллельных запросах (решается транзакцией или блокировкой).

Расширенные примеры с кодом и результатами

Пример 1: PDO с транзакцией и проверкой уникальности

Пример

try {
    $pdo->beginTransaction();
    // Проверка на дубликат email
    $stmtCheck = $pdo->prepare('SELECT COUNT(*) FROM users WHERE email = :email');
    $stmtCheck->execute(['email' => $_POST['email']]);
    if ($stmtCheck->fetchColumn() > 0) {
        throw new Exception('Email уже зарегистрирован');
    }
    // Вставка
    $stmtInsert = $pdo->prepare('INSERT INTO users (username, email, password) VALUES (:username, :email, :password)');
    $stmtInsert->execute([
        'username' => $_POST['username'],
        'email' => $_POST['email'],
        'password' => password_hash($_POST['password'], PASSWORD_DEFAULT),
    ]);
    $pdo->commit();
    echo 'Пользователь создан';
} catch (Exception $e) {
    $pdo->rollBack();
    echo 'Ошибка: ' . $e->getMessage();
}
Вывод при успехе: "Пользователь создан"
Вывод при дубликате: "Ошибка: Email уже зарегистрирован"

Пример 2: MySQLi с использованием хранимой процедуры

Пример

$mysqli = new mysqli('localhost', 'root', '', 'test');
// Предполагается, что хранимая процедура sp_create_user уже создана
$stmt = $mysqli->prepare('CALL sp_create_user(?, ?, ?)');
$stmt->bind_param('sss', $username, $email, $hashedPassword);
$username = $_POST['username'];
$email = $_POST['email'];
$hashedPassword = password_hash($_POST['password'], PASSWORD_DEFAULT);
if ($stmt->execute()) {
    $result = $stmt->get_result();
    $row = $result->fetch_assoc();
    echo 'Пользователь создан, ID: ' . $row['id'];
} else {
    echo 'Ошибка: ' . $stmt->error;
}
Вывод: "Пользователь создан, ID: 42"

Пример 3: Laravel регистрация с AJAX-запросом и валидацией

Пример

// routes/api.php
Route::post('/register', 'AuthController@register');

// AuthController
public function register(Request $request) {
    $validator = Validator::make($request->all(), [
        'name' => 'required|string|max:255',
        'email' => 'required|string|email|max:255|unique:users',
        'password' => 'required|string|min:8',
    ]);
    if ($validator->fails()) {
        return response()->json(['errors' => $validator->errors()], 422);
    }
    $user = User::create([
        'name' => $request->name,
        'email' => $request->email,
        'password' => Hash::make($request->password),
    ]);
    return response()->json(['message' => 'Пользователь создан', 'user' => $user], 201);
}

// Пример JavaScript (фрагмент)
/*
fetch('/api/register', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({name: 'Ivan', email: 'ivan@example.com', password: 'secret123'})
}).then(response => response.json()).then(data => console.log(data));
*/
Ответ JSON при успехе:
{"message":"Пользователь создан","user":{"id":1,"name":"Ivan","email":"ivan@example.com"}}
При ошибке валидации:
{"errors":{"email":["The email has already been taken."]}}

Новый пользователь в PHP - comments

En
User new php (php)