Переписывание URL-адресов с помощью PHP

У меня есть URL-адрес, который выглядит так:

url.com/picture.php?id=51

Как я могу конвертировать этот URL-адрес в:

picture.php/Some-text-goes-here/51

Я думаю, что WordPress делает то же самое.

Как мне сделать дружественные URL-адреса в PHP?

Ответ 1

Вы можете сделать это двумя способами:

Маршрут .htaccess с mod_rewrite

Добавьте в корневую папку файл с именем .htaccess и добавьте что-то вроде этого:

RewriteEngine on
RewriteRule ^/?Some-text-goes-here/([0-9]+)$ /picture.php?id=$1

Это скажет Apache, чтобы включить mod_rewrite для этой папки, и если ему будет задан URL-адрес, соответствующий регулярному выражению, он переписывает его внутри того, что вы хотите, без того, чтобы конечный пользователь его видел. Легко, но негибко, поэтому, если вам нужно больше энергии:

Маршрут PHP

Поместите вместо этого в свой .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 сделают все возможное.

Ответ 2

Если вы хотите изменить маршрут для 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

    Array
    (
        [0] => /picture/some text/51
        [text] => some text
        [1] => some text
        [id] => 51
        [2] => 51
    )

    picture.php?text=some+text&id=51

    Array
    (
        [text] => some 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' );

Ответ 3

это файл .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 или другому

Ответ 4

PHP не то, что вы ищете, посмотрите mod_rewrite

Ответ 5

Хотя уже ответили, и автор намерен создать приложение типа front controller, но я отправляю буквальное правило для заданной проблемы. если у кого-то проблема такая же.

RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([\d]+)$ $1?id=$3 [L]

Выше должно работать для url picture.php/Some-text-goes-here/51. без использования index.php в качестве приложения перенаправления.