У меня есть URL-адрес, который выглядит так:
url.com/picture.php?id=51
Как мне преобразовать этот URL в:
picture.php/Some-text-goes-here/51
Я думаю, что WordPress делает то же самое.
Как мне сделать удобные URL-адреса в PHP?
У меня есть URL-адрес, который выглядит так:
url.com/picture.php?id=51
Как мне преобразовать этот URL в:
picture.php/Some-text-goes-here/51
Я думаю, что WordPress делает то же самое.
Как мне сделать удобные URL-адреса в PHP?
mod_rewrite
это все, что вам нужно для этого, и здесь, на SO, есть много вопросов по этому поводу. И если вы «думаете», что wordpress делает то же самое, почему бы вам просто не поискать его ? ;)
Ответы:
Вы можете сделать это двумя способами:
Добавьте файл с именем .htaccess
в вашу корневую папку и добавьте что-то вроде этого:
RewriteEngine on
RewriteRule ^/?Some-text-goes-here/([0-9]+)$ /picture.php?id=$1
Это скажет Apache включить mod_rewrite для этой папки, и если он получит запрос на URL-адрес, соответствующий регулярному выражению, он внутренне переписывает его на то, что вы хотите, чтобы конечный пользователь этого не видел. Легко, но негибко, поэтому, если вам нужно больше мощности:
Вместо этого поместите в свой .htaccess следующее: (обратите внимание на ведущую косую черту)
FallbackResource /index.php
Это скажет ему запустить ваш index.php
для всех файлов, которые он обычно не может найти на вашем сайте. Там вы можете, например,:
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
if(empty($elements[0])) { // No path elements means home
ShowHomepage();
} else switch(array_shift($elements)) // Pop off first item and switch
{
case 'Some-text-goes-here':
ShowPicture($elements); // passes rest of parameters to internal function
break;
case 'more':
...
default:
header('HTTP/1.1 404 Not Found');
Show404Error();
}
Именно так это делают большие сайты и CMS-системы, потому что это дает гораздо большую гибкость в синтаксическом анализе URL-адресов, URL-адресов, зависящих от конфигурации и базы данных, и т. Д. Для спорадического использования жестко запрограммированные правила перезаписи подойдут .htaccess
.
picture.php/invalid-text/51
также приведет к перенаправлению в то же место. Вы также можете добавить проверку, чтобы убедиться, что строка верна, а если нет, перенаправить снова в правильное место. Вот как я сделал это на одном из своих сайтов с помощью htaccess.
/blog/25
так же, как /picture/51
и /download/684
. Кроме того, это считается очень плохой практикой (и вы будете наказаны за PR в Google!), Если не все случайно сгенерированные URL-адреса будут правильно возвращать 404.
FallbackResource /index.php
(обратите внимание на косую черту)
FallbackResource
срабатывает только для файлов, которых на самом деле не существует в файловой системе, отсюда и откат . Итак, если у вас есть файл /static/styles.css
и вы ссылаетесь на него, так как http://mydomain.tld/static/styles.css
код никогда не выполняется, он работает так, как ожидалось, и прозрачно.
if($elements[0] === NULL)
вместо этого, поскольку $elements
все равно будет возвращать счетчик, равный единице, даже если он пуст.
Если вы хотите изменить только маршрут, picture.php
тогда добавление правила перезаписи .htaccess
будет соответствовать вашим потребностям, но если вы хотите, чтобы URL-адрес переписывался, как в Wordpress, то подходящим вариантом является PHP. Вот простой пример для начала.
Структура папки
В корневой папке нужны два файла, .htaccess
и index.php
, а остальные .php
файлы было бы хорошо поместить в отдельную папку, например inc/
.
root/
inc/
.htaccess
index.php
.htaccess
RewriteEngine On
RewriteRule ^inc/.*$ index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
В этом файле четыре директивы:
RewriteEngine
- включить движок перезаписиRewriteRule
- запретить доступ ко всем файлам в inc/
папке, перенаправить любой вызов в эту папку наindex.php
RewriteCond
- разрешить прямой доступ ко всем другим файлам (например, изображениям, CSS или скриптам)RewriteRule
- перенаправить все остальное на index.php
index.php
Поскольку теперь все перенаправлено на index.php, будет определено, правильный ли URL-адрес, все параметры присутствуют и правильный ли тип параметров.
Чтобы проверить URL-адрес, нам нужен набор правил, и лучший инструмент для этого - регулярное выражение. Используя регулярные выражения, мы убьем двух мух одним ударом. URL-адрес для прохождения этого теста должен иметь все необходимые параметры, которые проверяются на разрешенные символы. Вот несколько примеров правил.
$rules = array(
'picture' => "/picture/(?'text'[^/]+)/(?'id'\d+)", // '/picture/some-text/51'
'album' => "/album/(?'album'[\w\-]+)", // '/album/album-slug'
'category' => "/category/(?'category'[\w\-]+)", // '/category/category-slug'
'page' => "/page/(?'page'about|contact)", // '/page/about', '/page/contact'
'post' => "/(?'post'[\w\-]+)", // '/post-slug'
'home' => "/" // '/'
);
Далее следует подготовить запрос uri.
$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );
Теперь, когда у нас есть URI запроса, последний шаг - проверить URI в правилах регулярных выражений.
foreach ( $rules as $action => $rule ) {
if ( preg_match( '~^'.$rule.'$~i', $uri, $params ) ) {
/* now you know the action and parameters so you can
* include appropriate template file ( or proceed in some other way )
*/
}
}
Успешное совпадение, поскольку мы используем именованные подшаблоны в регулярном выражении, заполнит $params
массив почти так же, как PHP заполняет $_GET
массив. Однако при использовании динамического URL-адреса $_GET
массив заполняется без каких-либо проверок параметров.
/ picture / some + text / 51 Массив ( [0] => / picture / some text / 51 [text] => какой-то текст [1] => какой-то текст [id] => 51 [2] => 51 ) picture.php? text = some + text & id = 51 Массив ( [text] => какой-то текст [id] => 51 )
Этих нескольких строк кода и базовых знаний о регулярных выражениях достаточно, чтобы начать построение надежной системы маршрутизации.
Полный источник
define( 'INCLUDE_DIR', dirname( __FILE__ ) . '/inc/' );
$rules = array(
'picture' => "/picture/(?'text'[^/]+)/(?'id'\d+)", // '/picture/some-text/51'
'album' => "/album/(?'album'[\w\-]+)", // '/album/album-slug'
'category' => "/category/(?'category'[\w\-]+)", // '/category/category-slug'
'page' => "/page/(?'page'about|contact)", // '/page/about', '/page/contact'
'post' => "/(?'post'[\w\-]+)", // '/post-slug'
'home' => "/" // '/'
);
$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );
foreach ( $rules as $action => $rule ) {
if ( preg_match( '~^'.$rule.'$~i', $uri, $params ) ) {
/* now you know the action and parameters so you can
* include appropriate template file ( or proceed in some other way )
*/
include( INCLUDE_DIR . $action . '.php' );
// exit to avoid the 404 message
exit();
}
}
// nothing is found so handle the 404 error
include( INCLUDE_DIR . '404.php' );
это файл .htaccess, который пересылает почти все на index.php
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_URI} !-l
RewriteCond %{REQUEST_FILENAME} !\.(ico|css|png|jpg|gif|js)$ [NC]
# otherwise forward it to index.php
RewriteRule . index.php
тогда вы должны проанализировать $ _SERVER ["REQUEST_URI"] и перенаправить на picture.php или что-то еще
FallbackResource
директиву несколько основных версий назад, которая сейчас является предпочтительным способом реализации этого поведения с меньшими затратами производительности, поскольку не требуется запускать весь механизм перезаписи. Документация здесь . Ваши правила также ошибочны, потому что вы не ссылаетесь на каталоги ( !-d
), а все фильтры расширений устарели - они -f
уже должны их отловить.
PHP - это не то, что вы ищете, проверьте mod_rewrite
Хотя уже ответил, и намерение автора состоит в том, чтобы создать приложение типа фронт-контроллера, но я публикую буквальное правило для заданной проблемы. если у кого-то возникла проблема.
RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([\d]+)$ $1?id=$3 [L]
Выше должно работать для URL-адреса picture.php/Some-text-goes-here/51
. без использования index.php в качестве приложения для перенаправления.