PHP로 URL 재 작성


139

다음과 같은 URL이 있습니다.

url.com/picture.php?id=51

해당 URL을 다음으로 변환하는 방법은 무엇입니까?

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

워드 프레스도 마찬가지라고 생각합니다.

PHP에서 친숙한 URL을 만들려면 어떻게해야합니까?


1
Apache 파일의 구성을 많이 조정해야합니다 ... 실제로 필요한 것의 예를 들어보십시오. 이 텍스트를 어떻게 삽입합니까? 사전 정의되었거나 동적으로 작성 되었습니까? 정답을 얻으려면 최대한 많은 정보를 제공하십시오 ... 그리고 url은 좀 더 설명이 될 수 있습니다. :)
user123_456

1
왜 PHP인가? 아파치 mod_rewrite가 이것에 필요한 전부이며 여기에 관한 많은 질문이 있습니다. 그리고 그 워드 프레스가 똑같이하는 것을 "생각"한다면, 간단하게 찾아 보지 않겠습니까? ;)
nietonfir 2016

읽기 mod_rewrite

왜 이런 짓을하는? URL을 다시 쓰는 것이 목표입니까? 그렇다면 .htaccess 또는 이와 유사한 것을 사용하십시오. 목표가 단순히 문자열을 변경하는 것이라면 $ _GET은 querystring 만 가져옵니다.
adeneo

텍스트는 이미지의 제목이고 슬래시 다음의 id가 될 것입니다. 너무 어렵지
않기를 바랍니다

답변:


194

기본적으로이 두 가지 방법으로 수행 할 수 있습니다.

mod_rewrite를 사용한 .htaccess 경로

.htaccess루트 폴더에 있는 파일을 추가하고 다음과 같이 추가하십시오.

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

이것은 아파치에게이 폴더에 대해 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();
}

URL, 구성 및 데이터베이스 종속 URL 등을 구문 분석하는 데 훨씬 더 많은 유연성을 허용하기 때문에 이것이 큰 사이트와 CMS 시스템에서 수행하는 방식 .htaccess입니다.


하드 코딩하는 대신 정규식을 사용하여 문자열을 완전히 무시할 수 있습니다. 다시 말해, 중요한 부분은 ID 부분입니다. 에가는 것은 picture.php/invalid-text/51같은 위치로 리디렉션합니다. 문자열이 올바른지 확인하고 그렇지 않은 경우 올바른 위치로 다시 리디렉션 할 수도 있습니다. htaccess를 사용하여 내 사이트 중 하나에서 수행 한 방법입니다.
Mike

7
당신은 구문 분석해야하는 경우 정말 실용적인 소규모 사이트에 대한 편리한 있지만 /blog/25뿐만 아니라 /picture/51/download/684. 또한, (구글 PR 처벌과를 얻을!) 아주 나쁜 연습 간주 모든 무작위로 생성 된 URL이 제대로 (404) 반환하지 않을 경우
닐스 Keurentjes

5
내 시스템에서 그것은 적어도 FallbackResource /index.php(슬래시를 주목하십시오)
Jack James

4
@olli : 잘못된 연습 설명은 구체적으로 "존재하지 않는 URL에 대해 404를 반환하지 않음"을 의미하며, 답변 자체의 솔루션으로 해결됩니다. 첫 번째 질문에 관해서는 FallbackResource실제로 파일 시스템에 존재하지 않는 파일에 대해서만 발생하므로 대체 입니다. 따라서 파일이 /static/styles.css있고 http://mydomain.tld/static/styles.css코드가 실행되지 않았 으므로 파일 을 참조하면 예상대로 투명하게 작동합니다.
Niels Keurentjes

비어있는 경우에도 여전히 1을 반환 하므로 if($elements[0] === NULL)대신 사용해야합니다 $elements.
fireinspace

57

경로를 변경하려는 경우 picture.php다시 쓰기 규칙을 추가하면 .htaccess요구 사항을 충족시킬 수 있지만 Wordpress에서와 같이 URL을 다시 작성하려면 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]

이 파일에는 네 가지 지시문이 있습니다.

  1. RewriteEngine -재 작성 엔진 사용
  2. RewriteRule- inc/폴더의 모든 파일에 대한 액세스를 거부 하고 해당 폴더에 대한 호출을index.php
  3. RewriteCond -이미지, CSS 또는 스크립트와 같은 다른 모든 파일에 직접 액세스 할 수 있습니다.
  4. RewriteRule -다른 것을 리디렉션 index.php

index.php

모든 것이 이제 index.php로 재 지정되므로, 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 / 일부 텍스트 / 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' );

2
매개 변수를 어떻게 읽습니까? $ post_id = htmlentities ($ _ GET [ 'post'])와 작동하지 않습니다.
andrebruton

@Danijel 완전한 소스 코드를 가질 수 있습니까? 위의 코드를 시도했지만 텍스트 만 출력되었지만 CSS는 효과가 없었습니다. 감사합니다.
4 덮개를 남겨주세요

6

이것은 거의 모든 것을 index.php로 전달하는 .htaccess 파일입니다.

# 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 또는 무엇이든 라우팅하십시오.


8
Apache FallbackResource는 몇 가지 주요 버전 이전에이 지시문을 도입했으며 , 이제 전체 재 작성 엔진을 시작할 필요가 없기 때문에 더 낮은 성능 비용으로이 동작을 구현하는 데 선호되는 방법입니다. 여기에 설명서가 있습니다 . 디렉토리 ( !-d)를 참조하지 않고 모든 확장 필터가 더 이상 사용되지 않으므로 규칙에 결함이 -f있습니다.
Niels Keurentjes


2

이미 대답했지만 저자의 의도는 프론트 컨트롤러 유형 앱을 만드는 것이지만 문제가있는 문제에 대한 리터럴 규칙을 게시하고 있습니다. 누군가가 같은 문제를 겪고 있다면.

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

위의 url 작동합니다 picture.php/Some-text-goes-here/51. index.php를 리디렉션 앱으로 사용하지 않습니다.


href에 어떤 URL을 작성해야하는지 알아야합니까? 404를 받고 있기 때문에
questionbank 5
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.