Практические примеры создания PHP страниц

Раздел: Веб-разработка -> Примеры веб-разработки

Основной подход: динамическая страница с PDO и шаблонизацией

Как организовать вывод данных из базы MySQL с минимальным уровнем абстракции?

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

<?php
// config.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());
}
?>
<!DOCTYPE html>
<html>
<head><title>Пользователи</title></head>
<body>
<h2>Список пользователей</h2>
<?php
$stmt = $pdo->query('SELECT id, name, email FROM users');
echo '<ul>';
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    echo '<li>' . htmlspecialchars($row['name']) . ' (' . htmlspecialchars($row['email']) . ')</li>';
}
echo '</ul>';
?>
</body>
</html>

примеры php страниц (примеры php страниц)

Типичные проблемы: отсутствие обработки ошибок (блок try-catch), незакрытое соединение (закрывается автоматически при уничтожении объекта PDO), забытый htmlspecialchars для вывода данных (XSS-уязвимость). Решение - всегда использовать prepared statements для выборок с пользовательским вводом и экранировать вывод.

Цель данного варианта - быстрая реализация простой динамической страницы без использования сторонних библиотек. Подходит для прототипов или небольших проектов.

Вариант 1. Простая страница с условиями и циклами

Как вывести разное содержимое в зависимости от времени суток или других параметров?

<?php
$hour = date('H');
$greeting = ($hour < 12) ? 'Доброе утро' : (($hour < 18) ? 'Добрый день' : 'Добрый вечер');
?>
<!DOCTYPE html>
<html>
<body>
<p><?= $greeting ?>, гость!</p>
<p>Массив пользователей:</p>
<ul>
<?php
$users = ['Анна', 'Иван', 'Мария'];
foreach ($users as $user) {
    echo '<li>' . htmlspecialchars($user) . '</li>';
}
?>
</ul>
</body>
</html>

Проблемы: смешивание кода и разметки усложняет поддержку. Для небольших статичных страниц допустимо, но для масштабирования лучше использовать шаблонизаторы.

Вариант 2. Обработка формы (POST)

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

<?php
$name = $email = '';
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = trim($_POST['name'] ?? '');
    $email = trim($_POST['email'] ?? '');
    if (empty($name)) $errors[] = 'Имя обязательно';
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'Некорректный email';
    if (empty($errors)) {
        // сохранение в БД или отправка письма
        $success = 'Данные приняты: ' . htmlspecialchars($name) . ', ' . htmlspecialchars($email);
    }
}
?>
<!DOCTYPE html>
<html>
<body>
<?php if (!empty($errors)): ?>
    <ul style="color:red">
    <?php foreach ($errors as $error): ?>
        <li><?= htmlspecialchars($error) ?></li>
    <?php endforeach; ?>
    </ul>
<?php elseif (isset($success)): ?>
    <p style="color:green"><?= $success ?></p>
<?php endif; ?>
<form method="post">
    <p>Имя: <input type="text" name="name" value="<?= htmlspecialchars($name) ?>"/></p>
    <p>Email: <input type="text" name="email" value="<?= htmlspecialchars($email) ?>"/></p>
    <button type="submit">Отправить</button>
</form>
</body>
</html>

Ошибки: неправильное определение метода (использование $_GET вместо $_POST), отсутствие проверки CSRF-токена, недостаточная фильтрация. Решение - валидация на сервере с filter_var, использование htmlspecialchars при выводе.

Вариант 3. Авторизация через сессии

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

<?php
session_start();
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $login = $_POST['login'] ?? '';
    $password = $_POST['password'] ?? '';
    // проверка в реальном проекте - через БД и password_verify
    if ($login === 'admin' && $password === '123') {
        $_SESSION['user'] = $login;
        header('Location: /profile.php');
        exit;
    } else {
        $error = 'Неверные учетные данные';
    }
}
?>
<!DOCTYPE html>
<html>
<body>
<?php if ($error): ?>
    <p style="color:red"><?= htmlspecialchars($error) ?></p>
<?php endif; ?>
<form method="post">
    <p>Логин: <input type="text" name="login" /></p>
    <p>Пароль: <input type="password" name="password" /></p>
    <button type="submit">Войти</button>
</form>
</body>
</html>

Проблемы: пароль в открытом виде (в реальном проекте нужно использовать password_hash/password_verify), сессия не защищена (желательно использовать HTTPS, установка httponly и secure для cookie). Стартовать session до любого вывода.

Вариант 4. REST API на PHP (JSON)

Как создать страницу, которая возвращает данные в формате JSON для клиентского приложения?

<?php
header('Content-Type: application/json; charset=utf-8');
$method = $_SERVER['REQUEST_METHOD'];
$users = [
    ['id' => 1, 'name' => 'Анна'],
    ['id' => 2, 'name' => 'Иван'],
];
if ($method === 'GET') {
    echo json_encode($users, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
} elseif ($method === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true);
    if (!$input || empty($input['name'])) {
        http_response_code(400);
        echo json_encode(['error' => 'Необходимо поле name']);
        exit;
    }
    // добавление пользователя...
    echo json_encode(['id' => 3, 'name' => $input['name']]);
} else {
    http_response_code(405);
    echo json_encode(['error' => 'Метод не поддерживается']);
}

Ошибки: неверный Content-Type, отсутствие обработки метода OPTIONS для CORS, невалидный JSON во входных данных. Решение - проверка json_last_error(), установка заголовков CORS при необходимости.

Вариант 5. Использование шаблонизатора Twig

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

<?php
require_once 'vendor/autoload.php';
$loader = new \Twig\Loader\FilesystemLoader(__DIR__ . '/templates');
$twig = new \Twig\Environment($loader, ['cache' => false]);
echo $twig->render('users.html.twig', [
    'users' => [
        ['name' => 'Анна', 'email' => 'anna@example.com'],
        ['name' => 'Иван', 'email' => 'ivan@example.com']
    ]
]);
<!-- templates/users.html.twig -->
<!DOCTYPE html>
<html>
<body>
<h2>Пользователи</h2>
<ul>
{% for user in users %}
    <li>{{ user.name }} ({{ user.email }})</li>
{% endfor %}
</ul>
</body>
</html>

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

Расширенные примеры PHP страниц

1. Страница с CRUD операциями (создание, чтение, обновление, удаление)

Полноценное веб-приложение для управления статьями с одной таблицей. Используется PDO и простой шаблон.

Код:

Пример
<?php
// db.php
$pdo = new PDO('mysql:host=localhost;dbname=blog;charset=utf8', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// index.php
require 'db.php';
$action = $_GET['action'] ?? 'list';

if ($action === 'list') {
    $stmt = $pdo->query('SELECT id, title, created_at FROM articles ORDER BY created_at DESC');
    $articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
    ?>
    <!DOCTYPE html>
    <html>
    <body>
    <h2>Статьи</h2>
    <a href="?action=add">Добавить</a>
    <ul>
    <?php foreach ($articles as $article): ?>
        <li>
            <?= htmlspecialchars($article['title']) ?> 
            (<a href="?action=edit&id=<?= $article['id'] ?>">ред.</a> 
             <a href="?action=delete&id=<?= $article['id'] ?>" onclick="return confirm('Удалить?')">уд.</a>)
        </li>
    <?php endforeach; ?>
    </ul>
    </body>
    </html>
    <?php
} elseif ($action === 'add' || $action === 'edit') {
    $id = $_GET['id'] ?? 0;
    $title = $content = '';
    if ($id) {
        $stmt = $pdo->prepare('SELECT title, content FROM articles WHERE id = ?');
        $stmt->execute([$id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row) {
            $title = $row['title'];
            $content = $row['content'];
        }
    }
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $title = $_POST['title'] ?? '';
        $content = $_POST['content'] ?? '';
        if ($id) {
            $stmt = $pdo->prepare('UPDATE articles SET title=?, content=? WHERE id=?');
            $stmt->execute([$title, $content, $id]);
        } else {
            $stmt = $pdo->prepare('INSERT INTO articles (title, content) VALUES (?, ?)');
            $stmt->execute([$title, $content]);
        }
        header('Location: ?action=list');
        exit;
    }
    ?>
    <!DOCTYPE html>
    <html>
    <body>
    <h2><?= $id ? 'Редактировать' : 'Добавить' ?> статью</h2>
    <form method="post">
        <p>Заголовок: <input type="text" name="title" value="<?= htmlspecialchars($title) ?>"/></p>
        <p>Содержание: <textarea name="content"><?= htmlspecialchars($content) ?></textarea></p>
        <button type="submit">Сохранить</button>
    </form>
    </body>
    </html>
    <?php
} elseif ($action === 'delete') {
    $id = $_GET['id'] ?? 0;
    if ($id) {
        $stmt = $pdo->prepare('DELETE FROM articles WHERE id = ?');
        $stmt->execute([$id]);
    }
    header('Location: ?action=list');
    exit;
}

Результат: страница со списком статей, возможность добавления, редактирования и удаления.

2. Загрузка файла на сервер

Страница для загрузки изображений с проверкой типа и размера.

Пример
<?php
$uploadDir = __DIR__ . '/uploads/';
$message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
    $file = $_FILES['file'];
    $allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
    $maxSize = 2 * 1024 * 1024; // 2 MB
    if ($file['error'] !== UPLOAD_ERR_OK) {
        $message = 'Ошибка загрузки: ' . $file['error'];
    } elseif (!in_array($file['type'], $allowedTypes)) {
        $message = 'Разрешены только JPG, PNG, GIF';
    } elseif ($file['size'] > $maxSize) {
        $message = 'Файл слишком большой (макс. 2MB)';
    } else {
        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $newName = uniqid('img_', true) . '.' . $ext;
        if (move_uploaded_file($file['tmp_name'], $uploadDir . $newName)) {
            $message = 'Файл загружен: ' . htmlspecialchars($newName);
        } else {
            $message = 'Не удалось переместить файл';
        }
    }
}
?>
<!DOCTYPE html>
<html>
<body>
<?php if ($message): ?>
    <p><?= htmlspecialchars($message) ?></p>
<?php endif; ?>
<form method="post" enctype="multipart/form-data">
    <p>Выберите изображение: <input type="file" name="file" /></p>
    <button type="submit">Загрузить</button>
</form>
</body>
</html>

Результат: если файл прошел проверку, он сохраняется в папку uploads с уникальным именем, выводится сообщение об успехе.

3. Отправка email через PHP mail()

Страница с формой обратной связи, которая отправляет письмо.

Пример
<?php
$name = $email = $message = '';
$errors = [];
$sent = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = trim($_POST['name'] ?? '');
    $email = trim($_POST['email'] ?? '');
    $message = trim($_POST['message'] ?? '');
    if (empty($name)) $errors[] = 'Укажите имя';
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'Некорректный email';
    if (empty($message)) $errors[] = 'Напишите сообщение';
    if (empty($errors)) {
        $to = 'admin@example.com';
        $subject = 'Сообщение с сайта от ' . $name;
        $body = "Имя: $name\nEmail: $email\nСообщение:\n$message";
        $headers = 'From: ' . $email . "\r\n" . 'Reply-To: ' . $email;
        if (mail($to, $subject, $body, $headers)) {
            $sent = true;
            $name = $email = $message = '';
        } else {
            $errors[] = 'Ошибка отправки письма';
        }
    }
}
?>
<!DOCTYPE html>
<html>
<body>
<?php if ($sent): ?>
    <p style="color:green">Письмо отправлено!</p>
<?php endif; ?>
<?php if (!empty($errors)): ?>
    <ul style="color:red">
    <?php foreach ($errors as $error): ?>
        <li><?= htmlspecialchars($error) ?></li>
    <?php endforeach; ?>
    </ul>
<?php endif; ?>
<form method="post">
    <p>Имя: <input type="text" name="name" value="<?= htmlspecialchars($name) ?>"/></p>
    <p>Email: <input type="text" name="email" value="<?= htmlspecialchars($email) ?>"/></p>
    <p>Сообщение:<br/><textarea name="message"><?= htmlspecialchars($message) ?></textarea></p>
    <button type="submit">Отправить</button>
</form>
</body>
</html>

Результат: при успешной отправке появляется зеленое сообщение, при ошибках - список.

4. Получение данных из внешнего API через cURL

Страница, которая выводит текущий курс валют с сайта ЦБ РФ (пример).

Пример
<?php
$ch = curl_init('https://www.cbr-xml-daily.ru/daily_json.js');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // для теста, в продакшене включить!
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = [];
if ($httpCode === 200) {
    $data = json_decode($response, true);
}
?>
<!DOCTYPE html>
<html>
<body>
<h2>Курсы валют (ЦБ РФ)</h2>
<?php if (!empty($data['Valute'])): ?>
    <table border="1">
        <tr><th>Код</th><th>Название</th><th>Курс (руб.)</th></tr>
        <?php foreach ($data['Valute'] as $code => $valute): ?>
            <tr>
                <td><?= htmlspecialchars($code) ?></td>
                <td><?= htmlspecialchars($valute['Name']) ?></td>
                <td><?= number_format($valute['Value'], 2, ',', ' ') ?></td>
            </tr>
        <?php endforeach; ?>
    </table>
<?php else: ?>
    <p>Не удалось получить данные. HTTP-код: <?= $httpCode ?></p>
<?php endif; ?>
</body>
</html>

Результат: таблица с курсами валют (пример данных).

5. Работа с сессиями: корзина интернет-магазина

Страница, добавляющая товары в корзину через сессию и отображающая содержимое.

Пример
<?php
session_start();
if (!isset($_SESSION['cart'])) {
    $_SESSION['cart'] = [];
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['product_id'])) {
    $id = (int)$_POST['product_id'];
    if (isset($_SESSION['cart'][$id])) {
        $_SESSION['cart'][$id]['quantity']++;
    } else {
        $_SESSION['cart'][$id] = ['name' => htmlspecialchars($_POST['product_name']), 'price' => (float)$_POST['product_price'], 'quantity' => 1];
    }
}
?>
<!DOCTYPE html>
<html>
<body>
<h2>Товары</h2>
<form method="post">
    <label>Товар: <select name="product_id">
        <option value="1">Книга (500 руб.)</option>
        <option value="2">Ручка (100 руб.)</option>
    </select></label>
    <input type="hidden" name="product_name" id="product_name" value="" />
    <input type="hidden" name="product_price" id="product_price" value="" />
    <button type="submit">В корзину</button>
</form>
<h3>Корзина</h3>
<ul>
<?php $total = 0; ?>
<?php foreach ($_SESSION['cart'] as $id => $item): ?>
    <li><?= $item['name'] ?> - <?= $item['price'] ?> руб. x <?= $item['quantity'] ?> = <?= $item['price'] * $item['quantity'] ?> руб.</li>
    <?php $total += $item['price'] * $item['quantity']; ?>
<?php endforeach; ?>
</ul>
<p>Итого: <?= $total ?> руб.</p>
</body>
</html>

Результат: страница с выбором товара, корзина отображается с количеством и суммой.

6. Генерация PDF-файла (с использованием библиотеки FPDF)

Страница, которая создает PDF с таблицей данных.

Пример
<?php
// Установка FPDF (скачать с http://www.fpdf.org/)
require_once 'fpdf/fpdf.php';
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial', 'B', 16);
$pdf->Cell(40,10,'Пример таблицы');
$pdf->Ln(20);
$pdf->SetFont('Arial','',12);
$header = ['ID', 'Имя', 'Email'];
$data = [
    [1, 'Анна', 'anna@mail.com'],
    [2, 'Иван', 'ivan@mail.com']
];
// Шапка
foreach ($header as $col) {
    $pdf->Cell(40,10,$col,1);
}
$pdf->Ln();
// Данные
foreach ($data as $row) {
    foreach ($row as $cell) {
        $pdf->Cell(40,10,$cell,1);
    }
    $pdf->Ln();
}
$pdf->Output('D', 'example.pdf');
?>

Результат: браузер загружает PDF-файл с таблицей.

Примеры PHP страниц - comments

En
примеры php страниц (php)