PHP разработка личной страницы пользователя

Раздел: Разработка сайтов -> Пользователи и профили

Создание страницы профиля пользователя на PHP

Основной подход: работа через PDO и сессии

Наиболее эффективное решение строится на использовании PDO для работы с базой данных (MySQL) и сессий для аутентификации. Это обеспечивает безопасность, гибкость и переносимость кода.

Структура проекта

  • config.php - настройки подключения к БД, константы
  • functions.php - вспомогательные функции (фильтрация, хеширование)
  • login.php - форма и обработка входа
  • register.php - регистрация нового пользователя
  • profile.php - страница профиля (основная)
  • logout.php - выход из системы

Ключевые шаги

  1. Создание базы данных и таблицы users (id, username, email, password_hash, avatar, created_at).
  2. Настройка PDO-соединения в config.php.
  3. Регистрация пользователя с хешированием пароля (password_hash()).
  4. Авторизация через проверку хеша (password_verify()) и запись в сессию.
  5. Вывод данных профиля только для авторизованных пользователей.
  6. Обработка ошибок с помощью исключений PDO.

Пример кода для config.php:


<?php
session_start();
const DB_HOST = 'localhost';
const DB_NAME = 'site_db';
const DB_USER = 'root';
const DB_PASS = '';

try {
    $pdo = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=utf8", DB_USER, DB_PASS);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die('Ошибка подключения: ' . $e->getMessage());
}
?>
  

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

  • Забыли вызвать session_start() - данные сессии не будут доступны.
  • Неправильный DSN или учётные данные - исключение PDO ловится, но иногда разработчики не обрабатывают ошибку.
  • Не указан charset - возникает проблема с кириллицей.
  • Использование устаревшего расширения mysql_* (оно удалено из PHP 7).

Как сделать страницу профиля без базы данных, используя файлы?

Для небольших проектов или прототипов можно хранить данные в JSON-файлах. Каждый пользователь - отдельный файл users/{id}.json. Авторизация через сессию, пароль хешируется. Минусы: нет параллельного доступа, медленно при большом количестве записей.

Пример создания пользователя в файле:


$userData = [
    'username' => $_POST['username'],
    'password' => password_hash($_POST['password'], PASSWORD_DEFAULT),
    'email' => $_POST['email']
];
$id = uniqid();
file_put_contents("users/$id.json", json_encode($userData));
  

Проблема

При одновременной записи двух скриптов возможна потеря данных. Решается блокировкой файла через flock(), но это снижает производительность.

Как интегрировать страницу профиля в фреймворк Laravel для быстрой разработки?

Laravel предоставляет готовую систему аутентификации (make:auth), Eloquent ORM и Blade-шаблоны. Достаточно выполнить php artisan make:auth и настроить маршруты. Личная страница пользователя может быть выведена через контроллер с middleware 'auth'. Пример контроллера:


class ProfileController extends Controller
{
    public function show()
    {
        $user = Auth::user();
        return view('profile.show', compact('user'));
    }
}
  

Ошибка новичков

Неверное указание middleware в маршруте приводит к тому, что страница доступна без авторизации. Правильно: Route::get('/profile', 'ProfileController@show')->middleware('auth');

Как использовать шаблонизатор Twig вместо встроенного PHP для профиля?

Twig позволяет разделить логику и представление. Пример шаблона profile.twig:


{% extends 'base.twig' %}
{% block content %}
  <h2>Профиль пользователя {{ user.username }}</h2>
  <p>Email: {{ user.email }}</p>
  <img src="{{ user.avatar }}" alt="Аватар">
{% endblock %}
  

Типичная проблема

Неэкранированный вывод через Twig по умолчанию безопасен, но если разработчик использует raw-фильтр без необходимости - появляется XSS-уязвимость.

Как реализовать профиль через mysqli, не используя PDO?

Mysqli также поддерживает подготовленные запросы. Код похож на PDO, но объектно-ориентированный синтаксис другой. Пример:


$mysqli = new mysqli('localhost', 'root', '', 'site_db');
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param('i', $_SESSION['user_id']);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
  

Распространённая ошибка

Забывают проверить количество строк: $result->num_rows. Если результат пуст, обращение к $user вызовет ошибку.

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

1. Полная регистрация с валидацией и обработкой ошибок

Пример

<?php
require_once 'config.php';

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

    if (strlen($username) < 3) $errors[] = 'Логин должен быть не менее 3 символов';
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'Некорректный email';
    if (strlen($password) < 6) $errors[] = 'Пароль должен быть не менее 6 символов';
    if ($password !== $passwordConfirm) $errors[] = 'Пароли не совпадают';

    // Проверка уникальности
    if (empty($errors)) {
        $stmt = $pdo->prepare("SELECT id FROM users WHERE username = ? OR email = ?");
        $stmt->execute([$username, $email]);
        if ($stmt->rowCount() > 0) $errors[] = 'Пользователь с таким логином или email уже существует';
    }

    if (empty($errors)) {
        $hash = password_hash($password, PASSWORD_DEFAULT);
        $stmt = $pdo->prepare("INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)");
        $stmt->execute([$username, $email, $hash]);
        $_SESSION['user_id'] = $pdo->lastInsertId();
        header('Location: profile.php');
        exit;
    }
}
?>
<form method="post">
  <!-- поля -->
</form>
<?php foreach ($errors as $error): ?>
  <p><?= htmlspecialchars($error) ?></p>
<?php endforeach; ?>

2. Безопасный вывод профиля с защитой от XSS

Пример

<?php
require_once 'config.php';

if (!isset($_SESSION['user_id'])) {
    header('Location: login.php');
    exit;
}

$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
?>
<h2>Профиль</h2>
<p>Имя: <?= htmlspecialchars($user['username']) ?></p>
<p>Email: <?= htmlspecialchars($user['email']) ?></p>
<p>Дата регистрации: <?= htmlspecialchars($user['created_at']) ?></p>

3. Обновление данных профиля (смена email)

Пример

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['new_email'])) {
    $newEmail = trim($_POST['new_email']);
    if (filter_var($newEmail, FILTER_VALIDATE_EMAIL)) {
        $stmt = $pdo->prepare("UPDATE users SET email = ? WHERE id = ?");
        $stmt->execute([$newEmail, $_SESSION['user_id']]);
        $success = 'Email обновлён';
    } else {
        $error = 'Некорректный email';
    }
}
?>

<?php if (isset($success)): ?>
  <p class="success"><?= $success ?></p>
<?php endif; ?>
<?php if (isset($error)): ?>
  <p class="error"><?= htmlspecialchars($error) ?></p>
<?php endif; ?>

4. Загрузка аватара с проверкой типа и размера

Пример

<?php
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
$maxSize = 2 * 1024 * 1024; // 2 MB

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['avatar'])) {
    $file = $_FILES['avatar'];
    if ($file['error'] !== UPLOAD_ERR_OK) {
        $error = 'Ошибка при загрузке файла';
    } elseif (!in_array($file['type'], $allowedTypes)) {
        $error = 'Допустимы только JPEG, PNG, GIF';
    } elseif ($file['size'] > $maxSize) {
        $error = 'Файл слишком большой (макс. 2 МБ)';
    } else {
        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $newName = $_SESSION['user_id'] . '_' . uniqid() . '.' . $ext;
        move_uploaded_file($file['tmp_name'], 'uploads/avatars/' . $newName);
        $stmt = $pdo->prepare("UPDATE users SET avatar = ? WHERE id = ?");
        $stmt->execute([$newName, $_SESSION['user_id']]);
        $success = 'Аватар обновлён';
    }
}
?>

5. Вывод списка пользователей (админ-панель)

Пример

<?php
$stmt = $pdo->query("SELECT id, username, email, created_at FROM users ORDER BY created_at DESC");
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<table>
  <tr><th>ID</th><th>Логин</th><th>Email</th><th>Дата</th></tr>
  <?php foreach ($users as $u): ?>
    <tr>
      <td><?= $u['id'] ?></td>
      <td><?= htmlspecialchars($u['username']) ?></td>
      <td><?= htmlspecialchars($u['email']) ?></td>
      <td><?= $u['created_at'] ?></td>
    </tr>
  <?php endforeach; ?>
</table>

Результат выполнения (пример для п.4 - загрузка аватара)

После успешной загрузки файла avatar_1_60f5a2b3c4d5e.jpg появляется в папке uploads/avatars/. В таблице users в поле avatar записывается имя файла. При выводе профиля используется <img src="uploads/avatars/<?= $user['avatar'] ?>">.

Страница пользователя на PHP - comments

En
User php page (php)