Как у вас реализовано чпу?

Хочу изменить реализацию чпу у себя, но не знаю как будет лучше. Под спойлером описан мой способ. Хотелось-бы посмотреть как это реализуете вы без использования фреймворков

ЗаголовокЭто пишем в файле 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: извините, если что-то мутно описано — залипаю уже
  • Вопрос задан
  • 11884 просмотра
Пригласить эксперта
Ответы на вопрос 7
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Вот зачем постоянно городить велосипеды… мильен их, и еще если поискать может чего интереснее будет. Такие вещи как раутинг, логирование и т.д. вообще желательно реюзать, а писать свои велосипеды — от этого пользы мало. Разве что обсучение.
github.com/chriso/klein.php
noodlehaus.github.io/dispatch/
Ответ написан
Mendel
@Mendel
PHP-developer
А зачем вообще ЧПУ?
ЧПУ это наследие стареньких движков.
Решение должно быть изначально в архитектуре.
т.е. ЧПУ как правило подразумевает, что у нас есть некая карта, а потом мы делаем ее более красивой…
Мы все равно будем делать те или иные запросы в базу, так почему бы и не искать эту информацию по ключу в виде полноценного пути?
Должная оптимизация с лихвой покроет издержки от того, что мы ищем по более длинному чем числовой индексу.
Теоретически и тут можно оптимизировать но на практике лично я до этого не дошел.
Была мысль использовать не сам путь а md5 от него, а если и это будет недостаточно быстро, то урезать его до bigint или даже до int ведь md5 это всего 16 байт, а при конфликте хэша мы просто получим две страницы вместо одной, и выберем перед выводом нужную…
Хотя при разумном количестве страниц конфликты маловероятны даже для обычного int.

Но на практике наши задержки или слишком малы, или таких запросов просто непомерно много, а если их много, то они у нас и так будут закрыты кэшем, так стоит ли о них беспокоиться?
Ответ написан
copist
@copist
Твой ВебМентор. Помогаю расти профессионально.
ЧПУ — это человеко-понимаемый УРЛ

не
h_ttp://example.com/post/121212

а
h_ttp://example.com/post/latest%20news

Чтобы человек читал и понимал, что это за ссылка
Ответ написан
Ну почему нельзя передавать ?)
Если сделать например так:
$route = preg_replace( '/(\?.*)?$/', '', $_SERVER["REQUEST_URI"] );
$route = preg_replace( '/%2F/' , '/' , urlencode( trim( $route , '/' ) ) );
define( 'MAIN_URI' , $route );


То можно реализовать так:
/search/search_request?type=posts&sort=time
Ответ написан
@mgkirs
у меня оно реализовано средствами apache
Вот 1 из примеров:
RewriteRule ^(.[^/]*)/([0-9]*)$ /index.php?a=$1&n=$2 [QSA]
Ответ написан
student_ivan
@student_ivan
Web-Developer, Front-End Engineer
В своё время в одном из своих треш-проектов делал компилируемый роутер, который компилировал статические маршруты для apache + mod rewrite и nginx, через командную строку. Выглядело это как-то так, а маршруты как-то так
Ответ написан
fear86
@fear86
Developer
Мне нравиться вариант хранить все ссылки в базе данных, есть ЧПУ и есть системный урл на который он ведет. Таким образом ссылки можно создавать программного, руками, можно сделать поддержку 301 редиректа для перемещенных/переименованных страниц, и тд. и не привязывать логику чпу к серверу.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы
СиСорт Барнаул
от 40 000 до 115 000 руб.
ULIGHT Москва
от 80 000 руб.
WebMoney Москва
от 110 000 руб.
20 янв. 2019, в 22:33
30000 руб./за проект
20 янв. 2019, в 22:03
1000 руб./за проект