PHP роутинг для страниц производителя: от простого к сложному

Раздел: Веб-разработка на PHP -> Роутинг в PHP

Маршрутизация для страницы производителя в PHP

Наиболее эффективное решение: простой кастомный роутер с регулярными выражениями и внедрением зависимостей.

Для маршрута типа /manufacturer/{id} или /products/manufacturer/{slug} можно написать собственный класс Router, который разбирает URI, извлекает параметры и вызывает соответствующий контроллер. Такой подход даёт полный контроль без привязки к фреймворку, подходит для небольших проектов и учебных целей.


class Router {
    private array $routes = [];

    public function add(string $pattern, callable $handler): void {
        $this->routes[$pattern] = $handler;
    }

    public function resolve(string $uri): mixed {
        foreach ($this->routes as $pattern => $handler) {
            $regex = '/^' . str_replace('/', '\/', $pattern) . '$/';
            $regex = preg_replace('/\{([a-zA-Z_]+)\}/', '(?P<$1>[^/]+)', $regex);
            if (preg_match($regex, $uri, $matches)) {
                $params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
                return $handler($params);
            }
        }
        return null; // 404
    }
}

// Пример использования
$router = new Router();
$router->add('/manufacturer/{id}', function(array $params) {
    $id = (int)$params['id'];
    // Загрузка производителя из БД
    echo "Страница производителя с ID $id";
});

$router->resolve($_SERVER['REQUEST_URI']);
  

Ru index php route account order (маршрут заказа аккаунта (ru))

Типовые проблемы и их решения:

  • Конфликт маршрутов. Если несколько шаблонов совпадают, последний добавленный перезаписывает первый. Решение – проверять уникальность шаблона или использовать приоритеты.
  • Неэкранированные символы. Регулярное выражение может сломаться при наличии специальных символов в URI. Рекомендуется экранировать через preg_quote для статических частей.
  • Отсутствие обработки 404. Роутер возвращает null, что нужно обрабатывать в index.php.

Вариант 1: Как реализовать маршрут с использованием готового микрофреймворка (Slim 4)?

Микрофреймворк Slim предоставляет удобный синтаксис для определения маршрутов, поддерживает middleware и внедрение зависимостей. Подходит для проектов, где не нужен полный стек Laravel, но требуется структура.


use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

require __DIR__ . '/vendor/autoload.php';

$app = AppFactory::create();

$app->get('/manufacturer/{id}', function (Request $request, Response $response, array $args) {
    $id = $args['id'];
    $response->getBody()->write("Производитель $id");
    return $response;
});

$app->run();
  

Php route product manufacturer (маршрут php для продукта производителя)

Частая ошибка: Забывают указать use для классов PSR-7. Slim 4 требует явного импорта. Решение – добавить в начало файла все необходимые use-выражения.

Вариант 2: Как сделать маршрут с помощью .htaccess и простого switch?

Для самых простых сайтов можно обойтись без полноценного роутера, используя URL rewriting через Apache и разбор $_GET['route'] или $_SERVER['REQUEST_URI'] в index.php с конструкцией switch. Этот метод не рекомендуется для сложных проектов из-за отсутствия гибкости.


// .htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?route=$1 [QSA,L]

// index.php
$route = $_GET['route'] ?? '/';
$parts = explode('/', trim($route, '/'));
if ($parts[0] === 'manufacturer' && isset($parts[1])) {
    $id = (int)$parts[1];
    // обработка
} else {
    // 404
}
  

Class route php (класс маршрутизации в php)

Проблемы: Уязвимость к атакам через path traversal (например, manufacturer/../admin). Решение – всегда проверять входные данные и использовать basename или фильтрацию.

Вариант 3: Как организовать маршрутизацию через Laravel (группы маршрутов и именованные маршруты)?

В Laravel маршруты для производителя можно сгруппировать, добавить middleware и использовать модель Route Model Binding. Это самый мощный вариант для крупных приложений.


// routes/web.php
use App\Models\Manufacturer;
use App\Http\Controllers\ManufacturerController;

Route::prefix('manufacturer')->group(function () {
    Route::get('/{manufacturer:slug}', [ManufacturerController::class, 'show'])->name('manufacturer.show');
});

// Пример контроллера
class ManufacturerController extends Controller
{
    public function show(Manufacturer $manufacturer)
    {
        return view('manufacturer.show', compact('manufacturer'));
    }
}
  

Проблемы: Если slug отсутствует в БД, Laravel автоматически выкинет исключение ModelNotFoundException (404). Но может потребоваться кастомный ключ (id или slug). Решение – указать Route::get('/{manufacturer:slug}') или переопределить метод getRouteKeyName в модели.

Дополнительные расширенные примеры с пояснениями.

Пример 1: Роутер с поддержкой опциональных параметров и фильтров

Пример

class AdvancedRouter {
    private array $routes = [];

    public function add(string $method, string $pattern, callable $handler): void {
        $this->routes[] = [$method, $pattern, $handler];
    }

    public function dispatch(string $method, string $uri): mixed {
        foreach ($this->routes as [$routeMethod, $pattern, $handler]) {
            if ($routeMethod !== strtoupper($method)) continue;
            $regex = preg_replace('/\{([a-zA-Z_]+):([^}]+)\}/', '(?P<$1>$2)', $pattern);
            $regex = preg_replace('/\{([a-zA-Z_]+)\}/', '(?P<$1>[^/]+)', $regex);
            $regex = '/^' . str_replace('/', '\/', $regex) . '$/';
            if (preg_match($regex, $uri, $matches)) {
                $params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
                return $handler($params);
            }
        }
        return null;
    }
}

$router = new AdvancedRouter();
$router->add('GET', '/manufacturer/{id:\d+}', function($params) {
    // id - только цифры
    echo "Производитель #{$params['id']}";
});
$router->add('GET', '/manufacturer/{slug:[a-z0-9\-]+}', function($params) {
    echo "Производитель с slug {$params['slug']}";
});

$result = $router->dispatch('GET', '/manufacturer/42');
// Вывод: Производитель #42
Производитель #42

Пример 2: Генерация URL по имени маршрута (обратное роутинг)

Пример

class NamedRouter {
    private array $routes = [];

    public function add(string $name, string $pattern, callable $handler): void {
        $this->routes[$name] = ['pattern' => $pattern, 'handler' => $handler];
    }

    public function generate(string $name, array $params = []): string {
        $pattern = $this->routes[$name]['pattern'] ?? '';
        foreach ($params as $key => $value) {
            $pattern = str_replace("{$key}", $value, $pattern);
        }
        return $pattern;
    }
}

$router = new NamedRouter();
$router->add('manufacturer.show', '/manufacturer/{id}', fn($p) => null);
$url = $router->generate('manufacturer.show', ['id' => 123]);
echo $url; // /manufacturer/123
/manufacturer/123

Пример 3: Использование атрибутов PHP 8 для роутинга (экспериментальный подход)

Пример

#[Attribute(\Attribute::TARGET_METHOD)]
class Route {
    public function __construct(public string $path, public string $method = 'GET') {}
}

class ProductController {
    #[Route('/manufacturer/{id}', 'GET')]
    public function show(int $id): string {
        return "Manufacturer $id";
    }
}

// Рефлексия для регистрации маршрутов
$controller = new ProductController();
$reflection = new ReflectionClass($controller);
foreach ($reflection->getMethods() as $method) {
    $attributes = $method->getAttributes(Route::class);
    foreach ($attributes as $attribute) {
        $route = $attribute->newInstance();
        // регистрация в роутере
        echo "Зарегистрирован маршрут: {$route->method} {$route->path}\n";
    }
}
Зарегистрирован маршрут: GET /manufacturer/{id}

Пример 4: Middleware для проверки доступа к странице производителя

Пример

class AuthMiddleware {
    public function handle(callable $next, array $params): mixed {
        if (!isset($_SESSION['user'])) {
            header('HTTP/1.1 403 Forbidden');
            exit('Доступ запрещён');
        }
        return $next($params);
    }
}

// Использование с кастомным роутером
$router = new Router();
$auth = new AuthMiddleware();

$router->add('/manufacturer/{id}', function($params) use ($auth) {
    $auth->handle(function($params) {
        // безопасный вызов
        echo "Производитель {$params['id']}";
    }, $params);
});

Маршрут PHP для продукта производителя - comments

En
Php route product manufacturer (php)