Хочу изменить реализацию чпу у себя, но не знаю как будет лучше. Под спойлером описан мой способ. Хотелось-бы посмотреть как это реализуете вы без использования фреймворков
ЗаголовокЭто пишем в файле index.php после загрузки ядра и всех необходимых файлов
define('MAIN_URI', ($_SERVER['REQUEST_URI'] == '/' ? '/index.php' : $_SERVER['REQUEST_URI']) );
// грузим правила для ЧПУ
include 'incl/furl_patterns.php';
$res = preg_replace($patterns_keys, $patterns_values, MAIN_URI);
if ($res == MAIN_URI){
// если не совпало ни одно из правил, выводим ошибку 404 или редиректим...
}
// разбираем url и преопределяем суперглобальный массив _REQUEST
parse_str($res, $_REQUEST);
$module = $_REQUEST['module'];
// далее подгружаем нужный модуль - упрощенный вариант
// например modules/news/index.php
if(file_exists("modules/".$module."/index.php")) {
include "modules/".$module."/index.php";
} else {
//опять 404 или редирект
}
файл с правилами выглядит так:
$patterns_keys = array(
'#^/(id([0-9]*)/?)?$#i', //test.ru/id154 можно без слеша после ид, а можно и с ним
'#^/(user/?)(new/?)?$#i',
'#^/(user/?)(settings/?)?$#i',
'#^/(user/?)(settings/?)?((general|avatar|security|social)/?)$#i'
);
$patterns_values = array(
'module=account&id=$2',
'module=account&action=new',
'module=account&action=settings',
'module=account&action=settings&do=$4' //модулю можно передавать дополнительные параметры
);
Например для test.ru/user/new будет подключен файл modules/account/new_user.php,
для ссылки test.ru/user/settings — modules/account/settings.php и в зависимости от того какие настройки указаны — они и будут выведены(по дефолту general). Правда в таком случае модуль подключается иначе:
switch ($module) {
case 'account':
switch ($_REQUEST['action']) {
case 'new':
include 'modules/account/new_user.php';
break;
case 'settings':
include 'modules/account/settings.php';
break;
default:
include 'modules/account/profile.php';
}
break;
...
}
Можно конечно грузить файл modules/account/index.php и уже в нем определять действия, и так для каждого модуля — неудобно, поэтому решил: пусть все будет в одном месте(можно вынести в отдельный файл).
Файл htaccess выглядит просто
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?%{REQUEST_URI} [l]
Этот способ был написан давно и вполне нормально работает, и я так давно его использую что не могу придумать ничего нового.
Единственным плюсом является то, что можно указывать любые правила, например:
test.ru/
id15484
userid15484
15484
erth15484yryu
user/15484
user/id/15484
...
будет отображена страница профиля пользователя с id=15484
или просто логин пользователя, без указания его id
test.ru/artishok
test.ru/user/artishok
Минусов несколько. Кроме очевидных — нельзя передавать параметры через массив $_GET.
Если здесь поиск простой:
habrahabr.ru/search/?target_type=posts&q=text&orde...
то мне в таком случае надо писать дополнительные правила с учетом типа и сортировки, выглядеть будет примерно так:
'#^/(search/?)(([a-zA-Zа-яА-Я0-9%\+]*)/?)?((posts|comments|questions|users)/?)?((time|relevance)/?)?(page([0-9]*)/?)?$#i'
и
'module=search&text=$3&type=$5&sort=$7&page=$9',
test.ru/search/text/posts/time/page2 — не понятно что происходит, и если в ссылке тип и сортировку поменять местами — выдаст ошибку, также ошибку выдаст если убрать один из параметров…
ps: извините, если что-то мутно описано — залипаю уже