
Структура сайта на PHP напрямую влияет на его поддержку, масштабируемость и безопасность. Даже простой проект должен иметь чёткое разделение по папкам и файлам. На старте достаточно выделить три ключевых директории: public (доступная из браузера), src (основная логика) и config (настройки окружения и маршруты).
Главная точка входа – index.php – должна находиться в папке public. Только она должна быть доступна из внешнего мира, всё остальное – закрыто. Через .htaccess файл стоит запретить доступ ко всем другим директориям. Это базовая мера безопасности.
В папке src удобно группировать код по задачам: Controllers для обработки запросов, Models для работы с базой данных, Views для отображения. Даже без использования фреймворков важно соблюдать это разделение: так проще тестировать и изменять код.
Файл конфигурации (config.php или .env) должен содержать параметры подключения к базе, пути, ключи API. Никогда не храните в нём пароли в открытом виде, особенно в публичных репозиториях. Для безопасной работы с настройками лучше использовать getenv() и переменные окружения.
Начинающему разработчику стоит изучить автозагрузку классов через Composer и настроить PSR-4 для правильной организации пространства имён. Это позволяет избежать лишнего include и упростить структуру проекта по мере его роста.
Назначение и структура файла index.php

Файл index.php выполняет роль точки входа в веб-приложение на PHP. Именно он обрабатывает начальный HTTP-запрос и управляет маршрутизацией, подключением конфигураций и запуском логики приложения. При обращении к корневой директории сайта веб-сервер по умолчанию обращается к этому файлу, если не указано иное в настройках.
Минимальная структура index.php включает подключение конфигураций, автозагрузку классов и запуск основного контроллера. Пример:
<?php
require_once __DIR__ . '/config/config.php';
require_once __DIR__ . '/vendor/autoload.php';
use App\Core\Router;
$router = new Router();
$router->dispatch($_SERVER['REQUEST_URI']);
На первом этапе подключается конфигурационный файл, содержащий настройки базы данных, пути и константы. Затем загружается автолоадер Composer, обеспечивающий автоматическое подключение классов по стандарту PSR-4. После этого создаётся экземпляр маршрутизатора, который на основе URI определяет, какой контроллер и метод следует запустить.
Файл index.php должен оставаться максимально легким. Логика, обработка данных и бизнес-правила выносятся в контроллеры и сервисы. Это упрощает поддержку и масштабирование кода. Запрещено размещать в index.php HTML-разметку или SQL-запросы – он должен исключительно инициализировать приложение.
Роль и организация папки includes

Папка includes предназначена для хранения вспомогательных PHP-файлов, которые подключаются в разных частях сайта. Это позволяет избежать дублирования кода и упрощает сопровождение проекта.
- Функции: вынесите часто используемые функции в файл
functions.php, чтобы подключать его черезrequire_onceпри инициализации. - Конфигурация: файл
config.phpдолжен содержать настройки подключения к базе данных, глобальные переменные и константы. Подключается до основного кода. - Шаблоны элементов: создавайте отдельные файлы для шапки (
header.php), подвала (footer.php), боковой панели (sidebar.php) и подключайте их черезincludeв нужных местах. - Маршруты или контроллеры: в небольших проектах допустимо хранить базовые контроллеры или маршруты в этой папке. Разграничивайте по логике и используйте имена вида
user-controller.php.
Рекомендуемая структура:
includes/config.phpincludes/functions.phpincludes/header.phpincludes/footer.phpincludes/sidebar.php
Подключение файлов должно выполняться строго через require_once или include_once, чтобы исключить повторное подключение и ошибки. Путь указывается относительно корня сайта или с использованием __DIR__:
require_once __DIR__ . '/includes/config.php';
Следите за тем, чтобы в папке includes не было скриптов, запускаемых напрямую. В начале каждого файла желательно вставлять проверку доступа:
defined('ACCESS') or die('Access denied');
Управление кодом через includes повышает читаемость и облегчает масштабирование сайта.
Как подключать и использовать конфигурационный файл config.php
Файл config.php должен содержать ключевые параметры, необходимые для работы сайта: настройки базы данных, пути, константы и режимы. Он размещается вне публичной директории (например, выше public_html), чтобы исключить прямой доступ из браузера.
- Создайте файл
config.phpв корне проекта или на уровень выше:
<?php
define('DB_HOST', 'localhost');
define('DB_NAME', 'my_database');
define('DB_USER', 'db_user');
define('DB_PASS', 'password');
define('BASE_URL', 'https://example.com/');
- Подключайте
config.phpв каждом скрипте черезrequire_once:
require_once __DIR__ . '/../config.php';
- Использование констант:
- Для подключения к базе данных:
$dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4';
$pdo = new PDO($dsn, DB_USER, DB_PASS);
- Для генерации абсолютных путей:
$link = BASE_URL . 'images/logo.png';
- Храните
config.phpв Git, но никогда не коммитьте реальные пароли. Используйтеconfig.sample.phpс пустыми значениями для шаблона. - Разделяйте настройки по средам (dev/prod), подключая разные конфиги в зависимости от переменных окружения:
if (getenv('APP_ENV') === 'production') {
require_once __DIR__ . '/../config.prod.php';
} else {
require_once __DIR__ . '/../config.dev.php';
}
- Не используйте переменные
$GLOBALSили суперглобальные массивы для хранения настроек – это снижает читаемость и безопасность.
Назначение и структура папки templates

В корне папки обычно размещаются базовые шаблоны: header.php, footer.php, layout.php. Файл layout.php может включать в себя общую структуру страницы с подключением других частей через include или require.
Для масштабируемости создаются подкаталоги по разделам: templates/posts/, templates/users/. В них размещаются шаблоны, связанные с определённой логикой. Например, post_item.php – разметка одного поста, user_profile.php – отображение профиля пользователя.
Рекомендуется соблюдать единый стиль именования файлов: строчные буквы, подчёркивания, без пробелов. Это упрощает навигацию и автоматизацию.
Разделение логики и отображения с использованием функций

Пример функции для обработки данных:
function getUserData($userId) {
// Здесь выполняется запрос к базе данных
$query = "SELECT * FROM users WHERE id = ?";
$stmt = $pdo->prepare($query);
$stmt->execute([$userId]);
return $stmt->fetch();
}
Эта функция извлекает данные пользователя, не задумываясь о том, как они будут отображены на странице. Логика работы с базой данных сосредоточена в одной функции, что упрощает тестирование и модификацию.
Пример функции для отображения данных:
function displayUserData($userData) {
echo "";
echo "Email: " . htmlspecialchars($userData['email']) . "
";
}
Важно также избегать использования переменных в функциях, которые напрямую зависят от внешнего контекста. Это помогает делать код более предсказуемым и безопасным. Все данные должны передаваться в функцию как параметры, что облегчает повторное использование и тестирование.
Когда логика и отображение четко разделены, становится проще следить за развитием проекта. Вы можете улучшать визуальную часть сайта, не затрагивая логику обработки данных, или наоборот – оптимизировать производительность, не изменяя внешний вид интерфейса.
Маршрутизация через .htaccess и index.php
Файл .htaccess в корне проекта используется для настройки веб-сервера Apache, позволяя управлять перенаправлениями, ограничениями и маршрутизацией. В PHP-приложении он часто используется для того, чтобы запросы на страницы обрабатывались через один главный скрипт – index.php.
Основная идея заключается в том, чтобы скрыть реальные пути к файлам и перенаправлять все запросы на index.php, который и будет отвечать за определение нужной страницы. В .htaccess настраивается правило, которое указывает серверу, что все запросы с несуществующими путями должны быть перенаправлены на index.php.
Пример конфигурации .htaccess:
RewriteEngine On RewriteBase / RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?page=$1 [QSA,L]
Здесь первое правило включит механизм модулей перезаписи URL (RewriteEngine), а следующее указывает, что запросы, содержащие буквы, цифры, дефисы и подчеркивания, будут перенаправлены на index.php с параметром page, содержащим значение пути. Например, запрос «example.com/about» будет передан в index.php как «index.php?page=about».
В файле index.php нужно обработать параметр page, который будет содержать название запрашиваемой страницы. Структура кода в index.php для обработки маршрутов выглядит так:
В этом примере переменная $page содержит значение из URL (например, «about»), и на основе этого значения выбирается нужный файл для подключения. Если значение не совпадает ни с одним из определённых маршрутов, по умолчанию будет загружен файл home.php.
Это решение упрощает структуру проекта, делая его более гибким и удобным для добавления новых маршрутов и страниц без необходимости изменения структуры URL или перенаправлений на уровне серверов.
Работа с базой данных через отдельный файл подключения
При разработке веб-приложений на PHP важно правильно организовать подключение к базе данных. Создание отдельного файла для подключения помогает избежать дублирования кода и упрощает обслуживание проекта. Рассмотрим, как это сделать эффективно.
Для начала создадим файл подключения, например, db.php. В нем будут храниться все параметры подключения, такие как хост, имя пользователя, пароль и название базы данных. Такой подход позволяет централизованно управлять настройками и менять их в одном месте, не затрагивая остальные части кода.
Пример файла db.php:
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo "Ошибка подключения: " . $e->getMessage();
exit;
}
?>
В этом примере используется PDO для подключения к базе данных MySQL. Метод setAttribute устанавливает режим обработки ошибок, что позволяет отлавливать исключения и удобно их обрабатывать.
Теперь, когда файл подключения создан, его можно подключать в других файлах проекта. Например, чтобы выполнить запрос к базе данных, нужно всего лишь включить файл db.php с помощью require_once или include_once. Это гарантирует, что файл подключится только один раз, предотвращая дублирование кода.
Пример использования файла подключения:
query($query);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['username'] . "
";
}
?>
Разделение кода на отдельные файлы для подключения к базе данных позволяет упростить поддержку и сделать код более читаемым. Такой подход также помогает улучшить безопасность, так как конфиденциальные данные (например, пароль к базе) можно скрыть в одном файле, который не будет загружаться на публичные страницы.
Важно помнить, что всегда следует проверять подключение к базе данных, обрабатывая возможные ошибки. Использование исключений в PDO упрощает этот процесс и позволяет быстро реагировать на проблемы с подключением.
Организация структуры URL с помощью GET-параметров
GET-параметры позволяют передавать данные в URL, облегчая маршрутизацию и обработку запросов. Они добавляются после знака вопроса и разделяются символом амперсанда. Пример: index.php?page=article&id=5.
Для обработки параметров используется суперглобальный массив $_GET. Доступ к значениям осуществляется по ключу: $_GET['page'], $_GET['id']. Обработка должна включать проверку существования ключей:
if (isset($_GET['page']) && $_GET['page'] === 'article') {
// Подключение статьи по ID
$id = (int)$_GET['id'];
include "pages/article.php";
}
Избегайте жёсткого связывания параметров и файлов. Вместо include $_GET['page'] . '.php' используйте whitelisting:
$allowed_pages = ['home', 'article', 'contact'];
$page = isset($_GET['page']) && in_array($_GET['page'], $allowed_pages)
? $_GET['page']
: 'home';
include "pages/{$page}.php";
Для читаемости и SEO лучше использовать понятные значения параметров. Вместо ?id=5 предпочтительнее ?id=produkt-5, где «produkt-5» – slug, а не числовой ID. Для сопоставления slug и ID используйте предварительно сформированный массив или запрос к базе данных.
Для тестирования корректности структуры URL можно использовать временную отладку:
echo '<pre>';
print_r($_GET);
echo '</pre>';
Безопасность: фильтруйте входящие параметры с помощью filter_input():
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
Не полагайтесь на GET-параметры для критически важных данных (например, прав доступа), так как они легко подделываются вручную.
