Собственный index.php в PHP: от простого к сложному

Раздел: PHP веб-разработка -> Основы PHP

Создание собственного index.php (custom index php)

Основное эффективное решение - использование единой точки входа (front controller) с автоматической загрузкой классов через Composer и маршрутизацию на основе компонента Symfony HttpFoundation или собственного роутера. Такой подход отделяет обработку запроса от логики приложения и облегчает тестирование.

<?php
// index.php - точка входа
require_once __DIR__ . '/../vendor/autoload.php';

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

$request = Request::createFromGlobals();
$uri = $request->getPathInfo();

// Пример простого роутера
$routes = [
    '/' => 'homepage',
    '/about' => 'aboutPage',
    '/contact' => 'contactPage',
];

$handler = $routes[$uri] ?? 'notFound';

switch ($handler) {
    case 'homepage':
        $response = new Response('<h1 class="fw-bold">Главная</h1>');
        break;
    case 'aboutPage':
        $response = new Response('<h1 class="fw-bold">О нас</h1>');
        break;
    case 'contactPage':
        $response = new Response('<h1 class="fw-bold">Контакты</h1>');
        break;
    default:
        $response = new Response('Страница не найдена', 404);
}

$response->send();

Php форматы данных (форматы данных в php (json, xml, serialize))

Этот код подходит для небольших проектов, где нужно быстро начать. Он использует автозагрузку Composer, объекты Request и Response, что делает код более структурированным. Проблемы: при росте числа маршрутов switch становится громоздким. Решение: вынести роутинг в отдельный класс или использовать готовый роутер (например, FastRoute).

Возможные ошибки и их решения:

  • Класс Request не найден - проверьте установку пакета symfony/http-foundation через Composer.
  • Путь к autoload.php неверен - укажите правильный путь относительно index.php.
  • Зацикливание при использовании mod_rewrite - настройте корректно .htaccess.

Как сделать index.php, который обрабатывает все запросы, включая статические файлы?

Для этого в корне проекта располагают файл .htaccess (для Apache) с правилами перезаписи:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

Php null false (null и false в php)

Как сделать простой index.php для статического сайта?

Когда сайт состоит только из HTML и CSS, index.php может просто подключать нужный контент:

<?php
$page = $_GET['page'] ?? 'home';
$allowed = ['home', 'about', 'contact'];
if (!in_array($page, $allowed)) $page = 'home';
include __DIR__ . "/pages/{$page}.html";

Php get started (начало работы с php)

Цель: быстрый старт для многостраничного сайта на PHP без базы данных. Проблемы: безопасность - прямое включение файлов по параметру может привести к path traversal. Решение: проверка в белом списке.

Ошибка: передача параметра page=../../etc/passwd. Решение: использовать только разрешенные значения.

Как реализовать маршрутизацию через switch в index.php без сторонних библиотек?

<?php
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
switch ($uri) {
    case '/':
        $content = '<h1>Главная</h1>';
        break;
    case '/users':
        $content = '<h1>Пользователи</h1>';
        break;
    default:
        http_response_code(404);
        $content = '<h1>404</h1>';
}
echo $content;

Custom index php (создание собственного index.php)

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

Как использовать Composer автозагрузку в index.php?

Установите Composer, создайте composer.json с автозагрузкой PSR-4:

{
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  }
}

Php структура данных (изучение структур данных в php)

После composer dump-autoload в index.php подключайте автозагрузку:

<?php
require __DIR__ . '/../vendor/autoload.php';
use App\Router;
$router = new Router();
$router->dispatch();

Php добавить переменную (добавление переменной php)

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

Как обрабатывать ошибки в index.php?

<?php
error_reporting(E_ALL);
ini_set('display_errors', 0);
set_error_handler(function($severity, $message, $file, $line) {
    throw new ErrorException($message, 0, $severity, $file, $line);
});
set_exception_handler(function($e) {
    http_response_code(500);
    echo '<h1>Внутренняя ошибка сервера</h1>';
    // логирование ошибки
    error_log($e->getMessage());
});
// остальной код

Default php file (файл по умолчанию в php)

Проблема: ошибки могут выводиться пользователю при display_errors=1. Решение: в production выключить вывод и использовать лог.

Как сделать index.php для REST API?

<?php
header('Content-Type: application/json');
$method = $_SERVER['REQUEST_METHOD'];
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$parts = explode('/', trim($uri, '/'));
if ($parts[0] === 'api' && $parts[1] === 'users') {
    $userId = $parts[2] ?? null;
    if ($method === 'GET' && $userId) {
        // получить одного пользователя
        echo json_encode(['id' => $userId, 'name' => 'John']);
    } elseif ($method === 'GET') {
        // список пользователей
        echo json_encode([['id' => 1, 'name' => 'John'], ['id' => 2, 'name' => 'Jane']]);
    } else {
        http_response_code(405);
        echo json_encode(['error' => 'Method not allowed']);
    }
} else {
    http_response_code(404);
    echo json_encode(['error' => 'Not found']);
}

Php return file (возврат файла из функции в php)

Цель: быстрый API без фреймворка. Ошибка: неверный HTTP-метод - нужно проверять.

Как организовать многосайтовость через index.php?

<?php
$domain = $_SERVER['HTTP_HOST'];
switch ($domain) {
    case 'site1.example.com':
        $config = require 'config_site1.php';
        break;
    case 'site2.example.com':
        $config = require 'config_site2.php';
        break;
    default:
        http_response_code(404);
        exit('Сайт не найден');
}
// Дальнейшая обработка с $config

Подходит для хостинга с несколькими доменами на одном аккаунте. Проблема: утечка конфигурации, если файл не защищен.

- Php название файла (правила именования файлов в php)
- Php file array (массив файлов в php)
- Php пример языка (примеры кода на php)

Расширенные примеры и редкие случаи использования index.php

Пример 1: index.php с middleware (цепочка обработчиков)

Реализация PSR-15 совместимого middleware вручную:

Пример
<?php
require 'vendor/autoload.php';

use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Laminas\Diactoros\Response;

class AuthMiddleware implements \Psr\Http\Server\MiddlewareInterface {
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): \Psr\Http\Message\ResponseInterface {
        if (!$request->hasHeader('Authorization')) {
            return new Response('Unauthorized', 401);
        }
        return $handler->handle($request);
    }
}

class RouterHandler implements RequestHandlerInterface {
    public function handle(ServerRequestInterface $request): \Psr\Http\Message\ResponseInterface {
        // ваша логика маршрутизации
        return new Response('Hello World', 200);
    }
}

$request = Laminas\Diactoros\ServerRequestFactory::fromGlobals();
$middleware = new AuthMiddleware();
$handler = new RouterHandler();
$response = $middleware->process($request, $handler);

// отправка ответа
(new Laminas\HttpHandlerRunner\Emitter\SapiEmitter())->emit($response);

Результат: при отсутствии заголовка Authorization вернёт 401, иначе выполнится роутер.

Пример 2: index.php с динамической загрузкой классов на основе анонимных функций (closure router)

Пример
<?php
$routes = [];
$routes['GET']['/'] = function() {
    return 'Главная';
};
$routes['GET']['/user/{id}'] = function($id) {
    return "Пользователь $id";
};

$method = $_SERVER['REQUEST_METHOD'];
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$matched = false;
foreach ($routes[$method] ?? [] as $pattern => $handler) {
    $regex = preg_replace('/\{([a-z]+)\}/', '(?P<$1>[^/]+)', $pattern);
    if (preg_match('#^' . $regex . '$#', $uri, $matches)) {
        $params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
        echo call_user_func_array($handler, $params);
        $matched = true;
        break;
    }
}
if (!$matched) {
    http_response_code(404);
    echo '404';
}

Результат: GET /user/42 выведет "Пользователь 42".

Пример 3: index.php, использующий Composer скрипты для генерации кэша маршрутов

В composer.json:

Пример
{
  "scripts": {
    "post-autoload-dump": [
      "php -r 'file_put_contents(\"routes_cache.php\", \"<?php return [\\\"home\\\" => function(){ return \\\"Cached home\\\"; }];\");'"
    ]
  }
}

После composer dump-autoload создаётся routes_cache.php. В index.php проверяем существование кэша и используем его:

Пример
<?php
if (file_exists('routes_cache.php')) {
    $routes = require 'routes_cache.php';
    if (isset($routes[$_GET['route'] ?? 'home'])) {
        echo $routes[$_GET['route']]();
    }
} else {
    // обычная загрузка маршрутов
}

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

Пример 4: Обработка ошибок с выводом подробного отчёта в dev-режиме

Пример
<?php
define('ENV', 'dev');

if (ENV === 'dev') {
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
} else {
    error_reporting(0);
    ini_set('display_errors', 0);
}

set_exception_handler(function($e) {
    if (ENV === 'dev') {
        echo '<pre>' . $e->getMessage() . '\n' . $e->getTraceAsString() . '</pre>';
    } else {
        http_response_code(500);
        echo '<h1>Произошла ошибка, повторите попытку позже</h1>';
        error_log($e->getMessage());
    }
});

throw new \Exception('Тестовая ошибка');

Результат: в dev-режиме увидим полный трейс, в production - стандартную заглушку.

Пример 5: index.php с поддержкой CORS для AJAX-запросов

Пример
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

// остальная обработка

Результат: браузер не блокирует кросс-доменные запросы.

Пример 6: index.php, который выполняет перенаправление на другой протокол (HTTP -> HTTPS)

Пример
<?php
if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
    $redirectUrl = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    header('Location: ' . $redirectUrl, true, 301);
    exit;
}
// дальнейшая обработка

Результат: все запросы перенаправляются на HTTPS.

Создание собственного index.php - comments

En
Custom index php (php)