Как организовать точку входа в PHP: примеры index.php
Современный подход к index.php: фронт-контроллер
Наиболее эффективное решение для организации точки входа в PHP-приложение - использование фронт-контроллера с автозагрузкой через Composer и простой маршрутизацией. Такой index.php становится единой точкой обработки всех запросов, что упрощает поддержку и расширение кода.
<?php
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use App\Core\Router;
use App\Core\Request;
$request = new Request();
$router = new Router();
$response = $router->dispatch($request);
$response->send();
Пояснение: require подключает автозагрузку классов, определённых в composer.json. Классы Request и Router реализуют логику разбора URL и вызова соответствующего контроллера. Метод dispatch возвращает объект ответа, который отправляется клиенту.
Возможные проблемы: если пути к vendor указаны неверно, возникает фатальная ошибка. Решение - использовать константу __DIR__ и корректно организовать структуру папок. Типичная ошибка - забыть установить зависимости через composer install. Также стоит проверять наличие файла autoload.php.
Как сделать простой роутинг без фреймворка?
Вариант с прямым разбором URI через $_SERVER['REQUEST_URI'] и вызовом функций по условию.
<?php
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if ($uri === '/' || $uri === '') {
$controller = new HomeController();
$controller->index();
} elseif ($uri === '/about') {
$controller = new AboutController();
$controller->index();
} else {
http_response_code(404);
echo 'Страница не найдена';
}
Объяснение: переменная $uri получает путь без query-строки. С помощью условий выбирается нужный контроллер. Такой подход подходит для небольших проектов, но быстро разрастается.
Типичные ошибки: не учитываются параметры в URL (GET-запросы), забывают установить код ответа 404. Решение - добавить регулярные выражения или использовать библиотеку для маршрутизации.
Как подключить конфигурацию базы данных в index.php?
Решение - вынести параметры в отдельный файл и подключать его перед инициализацией приложения.
<?php
$config = require __DIR__ . '/config.php';
$db = new PDO(
"mysql:host={$config['host']};dbname={$config['dbname']}",
$config['user'],
$config['password']
);
Цель - изолировать настройки, не зашивать их в код.
Частая ошибка - пути к конфигурационному файлу не совпадают с рабочим каталогом. Рекомендуется использовать __DIR__ или абсолютные пути.
Как обработать ошибки и исключения на старте приложения?
Пример с установкой собственного обработчика исключений.
<?php
set_exception_handler(function (Throwable $e) {
http_response_code(500);
echo 'Внутренняя ошибка сервера: ' . $e->getMessage();
});
// остальной код
Такая конструкция перехватывает необработанные исключения и выводит понятное сообщение.
Если не использовать полное пространство имён (Throwable), код сломается в старых версиях PHP. Решение - проверить версию PHP и при необходимости использовать Exception.
Как запустить сессию в index.php для всех страниц?
Достаточно вызвать session_start() в самом начале файла.
<?php
session_start();
// далее логика приложения
Цель - обеспечить сохранение данных между запросами.
Ошибка: вызов session_start после вывода данных – приведёт к предупреждению. Необходимо размещать вызов до любого вывода (echo, HTML).
Расширенные примеры index.php
Пример 1: Интеграция с ORM (Doctrine)
<?php
require __DIR__ . '/vendor/autoload.php';
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
$paths = [__DIR__ . '/src/Entity'];
$isDevMode = true;
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
$connectionParams = [
'driver' => 'pdo_mysql',
'user' => 'root',
'password' => '',
'dbname' => 'test',
];
$entityManager = EntityManager::create($connectionParams, $config);
// Пример вызова репозитория
$users = $entityManager->getRepository(User::class)->findAll();
foreach ($users as $user) {
echo $user->getName() . PHP_EOL;
}
Иван Петр Мария
Пояснение: настройка Doctrine через index.php позволяет сразу получить доступ к EntityManager для всех контроллеров. Важно настроить пути к сущностям и параметры подключения.
Пример 2: Middleware цепочка для обработки запроса
<?php
require __DIR__ . '/vendor/autoload.php';
$middlewares = [
new AuthMiddleware(),
new CorsMiddleware(),
new LoggerMiddleware(),
];
$handler = function ($request) {
// финальный обработчик
return new Response(200, 'Hello World');
};
foreach ($middlewares as $middleware) {
$handler = $middleware->wrap($handler);
}
$request = Request::fromGlobals();
$response = $handler($request);
$response->send();
(нет вывода, просто успешная обработка)
Объяснение: каждый middleware добавляет свою логику (проверка токена, заголовки CORS, логирование). Результат - гибкая система фильтрации.
Пример 3: Простое REST API с ответом в JSON
<?php
header('Content-Type: application/json');
$method = $_SERVER['REQUEST_METHOD'];
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if ($method === 'GET' && $uri === '/api/items') {
$data = ['item1', 'item2', 'item3'];
echo json_encode($data);
} elseif ($method === 'POST' && $uri === '/api/items') {
$input = json_decode(file_get_contents('php://input'), true);
// сохранение...
echo json_encode(['status' => 'created']);
} else {
http_response_code(404);
echo json_encode(['error' => 'Not Found']);
}
При GET: ["item1","item2","item3"]
При POST: {"status":"created"}
Цель - продемонстрировать минимальное RESTful приложение на чистом PHP. Проблемы: отсутствие маршрутизации с параметрами, необходимость вручную обрабатывать методы.
Пример 4: Использование контейнера зависимостей (PHP-DI)
<?php
require __DIR__ . '/vendor/autoload.php';
use DI\ContainerBuilder;
use App\Service\UserService;
$builder = new ContainerBuilder();
$builder->addDefinitions([
UserService::class => function () {
return new UserService(new PDO('mysql:host=localhost;dbname=test', 'root', ''));
},
]);
$container = $builder->build();
$userService = $container->get(UserService::class);
$users = $userService->getAll();
(массив объектов User)
Объяснение: контейнер автоматически подставляет зависимости, упрощая тестирование и замену реализации.
Пример 5: Обработка загрузки файлов через index.php
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$uploadDir = __DIR__ . '/uploads/';
$filename = basename($_FILES['file']['name']);
$targetPath = $uploadDir . $filename;
if (move_uploaded_file($_FILES['file']['tmp_name'], $targetPath)) {
echo 'Файл загружен: ' . $filename;
} else {
echo 'Ошибка загрузки';
}
}
Файл загружен: example.pdf
Цель - приём файлов без дополнительных библиотек. Типичная ошибка: не создана папка uploads или не хватает прав на запись.
Пример 6: Кеширование вывода с помощью ob_start
<?php
ob_start();
echo 'Содержимое страницы';
$cacheKey = 'home_page';
file_put_contents(__DIR__ . '/cache/' . $cacheKey, ob_get_contents());
ob_end_flush();
Содержимое страницы
Пояснение: буферизация вывода и сохранение в файл. Следующий запрос может сначала проверить наличие кеша.
Пример 7: Загрузка .env переменных (vlucas/phpdotenv)
<?php
require __DIR__ . '/vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/..');
$dotenv->load();
$dbHost = $_ENV['DB_HOST'];
$dbUser = $_ENV['DB_USER'];
// ... дальнейшее использование
(нет вывода, переменные доступны через $_ENV)
Цель - безопасное хранение конфиденциальных данных вне кода.
Пример 8: Командная строка - CLI-скрипт на базе index.php
<?php
if (PHP_SAPI === 'cli') {
$options = getopt('', ['command:', 'param:']);
$command = $options['command'] ?? 'help';
switch ($command) {
case 'migrate':
echo 'Выполнение миграций...';
break;
default:
echo 'Доступные команды: migrate';
}
} else {
// веб-обработка...
}
$ php index.php --command migrate Выполнение миграций...
Объяснение: один файл может выступать как веб-точка и как консольная утилита при проверке константы PHP_SAPI.
Пример 9: Тестирование встроенным сервером PHP
# В терминале:
php -S localhost:8000 -t public/ public/index.php
(запуск сервера, все запросы направляются на index.php)
Цель - быстрая разработка без Apache/Nginx. Флаг -t указывает корневую папку, а последний аргумент - имя роутер-скрипта.