PHP веб-разработка: примеры и практические инструкции
Основные подходы к созданию PHP сайта
В этом разделе рассмотрены практические варианты построения веб-сайта на PHP: от простого файлового подхода до структурированных решений с базами данных и шаблонизаторами. Каждый вариант сопровождается вопросом, на который он отвечает, а также описанием целей использования.
Как создать динамический сайт с роутингом и подключением к MySQL?
Основное решение - процедурный PHP с единой точкой входа (front controller). Такой подход подходит для небольших проектов, где нужно быстро развернуть сайт с несколькими страницами и базой данных.
<?php
// index.php - единая точка входа
$uri = $_SERVER['REQUEST_URI'];
$uri = parse_url($uri, PHP_URL_PATH);
switch ($uri) {
case '/':
require 'home.php';
break;
case '/about':
require 'about.php';
break;
case '/contact':
require 'contact.php';
break;
default:
http_response_code(404);
require '404.php';
break;
}
?>
Подключение к базе данных выполняется с помощью PDO:
<?php
$host = 'localhost';
$db = 'mysite';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
die('Ошибка подключения: ' . $e->getMessage());
}
?>
В каждом файле-обработчике можно использовать переменную $pdo для запросов. Цель данного решения - минимальная настройка и быстрый старт, но при росте проекта управление становится сложным.
Как сделать статический сайт с переиспользуемыми блоками через include?
Подходит для сайтов-визиток без динамического контента. Все страницы - это HTML с вставками PHP для header/footer.
<!DOCTYPE html>
<html>
<head>
<title>Главная</title>
</head>
<body>
<?php include 'header.php'; ?>
<h1>Добро пожаловать</h1>
<p>Это статический сайт на PHP.</p>
<?php include 'footer.php'; ?>
</body>
</html>
Проблема: при изменении структуры нужно редактировать каждую страницу. Решение - использовать единый шаблон с переменными содержимого.
Типичная ошибка - неправильные пути при подключении файлов (использовать __DIR__ или задать корневую константу).
Как организовать сайт с шаблонизатором Twig?
Вариант с Twig отделяет логику от представления. Устанавливается через Composer.
composer require twig/twig
Создание шаблона templates/index.html.twig:
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ heading }}</h1>
<p>{{ content }}</p>
</body>
</html>
PHP код для рендеринга:
<?php
require_once 'vendor/autoload.php';
$loader = new \Twig\Loader\FilesystemLoader('templates');
$twig = new \Twig\Environment($loader);
echo $twig->render('index.html.twig', [
'title' => 'Мой сайт',
'heading' => 'Привет!',
'content' => 'Это контент, переданный из PHP.',
]);
?>
Цель использования - упрощение поддержки HTML и возможность наследования шаблонов.
Ошибка: отсутствие расширения mbstring может вызвать проблемы с кодировкой. Рекомендуется проверять настройки PHP.
Как написать самописный MVC для учебного проекта?
Реализация собственного MVC помогает понять принципы фреймворков. Пример структуры:
app/
controllers/
HomeController.php
models/
User.php
views/
home.php
public/
index.php
Файл public/index.php - точка входа с роутингом на контроллеры:
<?php
$controllerName = $_GET['controller'] ?? 'home';
$actionName = $_GET['action'] ?? 'index';
$controllerClass = ucfirst($controllerName) . 'Controller';
if (class_exists($controllerClass)) {
$controller = new $controllerClass();
if (method_exists($controller, $actionName)) {
$controller->$actionName();
} else {
http_response_code(404);
echo 'Action not found';
}
} else {
http_response_code(404);
echo 'Controller not found';
}
?>
Контроллер HomeController:
<?php
class HomeController {
public function index() {
$data = ['title' => 'Главная'];
include '../app/views/home.php';
}
}
?>
Подходит для обучения и небольших проектов без внешних зависимостей.
Проблема: отсутствие автозагрузки классов - нужно либо использовать spl_autoload_register, либо подключать файлы вручную. Типичная ошибка - неправильные пути к файлам видов.
Общие проблемы и их решения
- Ошибки подключения к MySQL: проверьте имя базы, пользователя и пароль. Используйте try-catch с PDO.
- Безопасность: всегда экранируйте данные через подготовленные запросы (PDO или MySQLi).
- Настройка веб-сервера: для ЧПУ используйте .htaccess с RewriteEngine On.
- Кэширование: для Twig включите кэш в production для ускорения.
Расширенные примеры PHP кода
1. Конфигурация .htaccess для ЧПУ
Позволяет маршрутизировать все запросы через index.php без указания имени файла в URL.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
Результат: URL /about обрабатывается index.php с параметром url=about.
$_GET['url'] = 'about'
2. Безопасный класс для работы с БД (PDO обёртка)
Пример класса Database с методом query и prepared statements. Защита от SQL-инъекций.
<?php
class Database {
private $pdo;
public function __construct($config) {
$dsn = "mysql:host={$config['host']};dbname={$config['db']};charset={$config['charset']}";
$this->pdo = new PDO($dsn, $config['user'], $config['pass'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
public function query($sql, $params = []) {
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
}
$config = [
'host' => 'localhost',
'db' => 'test',
'user' => 'root',
'pass' => '',
'charset' => 'utf8mb4',
];
$db = new Database($config);
$users = $db->query('SELECT * FROM users WHERE status = ?', ['active']);
print_r($users);
?>
Array
(
[0] => Array
(
[id] => 1
[name] => Иван
[status] => active
)
)
3. Простой REST API на PHP (GET/POST)
Реализация базового API для работы с ресурсом 'tasks'. Используется JSON.
<?php
header('Content-Type: application/json');
$method = $_SERVER['REQUEST_METHOD'];
switch ($method) {
case 'GET':
$tasks = [
['id' => 1, 'title' => 'Купить молоко'],
['id' => 2, 'title' => 'Позвонить другу'],
];
echo json_encode($tasks);
break;
case 'POST':
$input = json_decode(file_get_contents('php://input'), true);
$newTask = [
'id' => 3,
'title' => $input['title'] ?? 'Новая задача',
];
echo json_encode($newTask);
break;
default:
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
}
?>
Результат при GET запросе:
[{"id":1,"title":"Купить молоко"},{"id":2,"title":"Позвонить другу"}]
4. Авторизация через сессии и пароль (bcrypt)
Хеширование пароля и проверка при входе. Пример использует password_hash и password_verify.
<?php
session_start();
// Регистрация
$password = 'secret';
$hash = password_hash($password, PASSWORD_BCRYPT);
// сохраняем $hash в базу
// Вход
$inputPassword = 'secret';
if (password_verify($inputPassword, $hash)) {
$_SESSION['user_id'] = 1;
echo 'Вход выполнен';
} else {
echo 'Неверный пароль';
}
?>
Результат успешного входа:
Вход выполнен