Quảng cáo
Url Rewriting giống WordPress
Chủ đề: PHP / MySQLBài trước|Bài tiếp
Mình thích wordpress nên khi viết code php mình muốn sử dụng hệ thống rewrite url của wordpress, sau một hồi loay hoay tìm kiếm trên google mình có bài viết này. Mọi điều hướng trong wordpress đều thông qua file index, nên khi viết code rewrite trong file config (htacess hoặc nginx) bạn sẽ không cần làm nhiều công đoạn nữa. Làm như sau:
Nội dung các file trong code
config.php
Ví dụ
<?php
include_once 'matches.php';
define("SITE_URL", "http://localhost/urlrewriting");
$rewrite = array();
function updateSlugForRewrite(&$items, $parentId = "0", $parentItem = array()) {
// Parent items control
$isParentItem = false;
foreach ($items as $item) {
if ($item['parent'] == $parentId) {
$isParentItem = true;
break;
}
}
// Prepare items
if ($isParentItem) {
foreach ($items as &$item) {
if ($item['parent'] == $parentId) {
$item['slug'] = isset($parentItem['slug']) ? ($parentItem['slug'] . "/" . $item['slug']) : $item['slug'];
updateSlugForRewrite($items, $item['id'], $item);
}
}
}
}
function updateRewriteRules($additional_rules = array(), $location = "bottom") {
$rewrite_rules = array();
//adding additional rules in array at the top
if (!empty($additional_rules) && $location == 'top') {
foreach ($additional_rules as $key => $value) {
$rewrite_rules[$key] = $value;
}
}
/* login, logout & register rewrites */
$rewrite_rules['login$'] = 'index.php?login=1';
$rewrite_rules['logout$'] = 'index.php?logout=1';
$rewrite_rules['register$'] = 'index.php?register=1';
/*
* categories rewrites
* categories will be fetched from database dynamically but for testing I am using fixed data
*/
$categories = array(
array('id' => "1", 'name' => "Java", 'slug' => "java", 'description' => "", 'parent' => "0"),
array('id' => "2", 'name' => "JavaFX", 'slug' => "javafx", 'description' => "", 'parent' => "0"),
array('id' => "3", 'name' => "Projects", 'slug' => "projects", 'description' => "", 'parent' => "0"),
array('id' => "4", 'name' => "Java Projects", 'slug' => "java-projects", 'description' => "", 'parent' => "3"),
array('id' => "5", 'name' => "PHP Projects", 'slug' => "php-projects", 'description' => "", 'parent' => "3"),
array('id' => "6", 'name' => "Uncategorized", 'slug' => "uncategorized", 'description' => "", 'parent' => "0")
);
updateSlugForRewrite($categories, 0);
foreach ($categories as $c) {
$rewrite_rules['(' . $c['slug'] . ')/page/?([0-9]{1,})/?$'] = 'index.php?category_name=$matches[1]&paged=$matches[2]';
$rewrite_rules['(' . $c['slug'] . ')/?$'] = 'index.php?category_name=$matches[1]';
}
/* tag rewrites */
$rewrite_rules['tag/([^/]+)/page/?([0-9]{1,})/?$'] = 'index.php?tag=$matches[1]&paged=$matches[2]';
$rewrite_rules['tag/([^/]+)/?$'] = 'index.php?tag=$matches[1]';
/* blogs paging */
$rewrite_rules['page/?([0-9]{1,})/?$'] = 'index.php?&paged=$matches[1]';
/* search rewrites */
$rewrite_rules['search/(.+)/page/?([0-9]{1,})/?$'] = 'index.php?s=$matches[1]&paged=$matches[2]';
$rewrite_rules['search/(.+)/?$'] = 'index.php?s=$matches[1]';
/* author rewrites */
$rewrite_rules['author/([^/]+)/page/?([0-9]{1,})/?$'] = 'index.php?author_name=$matches[1]&paged=$matches[2]';
$rewrite_rules['author/([^/]+)/?$'] = 'index.php?author_name=$matches[1]';
/* year month day wise posts */
$rewrite_rules['([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/page/?([0-9]{1,})/?$'] = 'index.php?year=$matches[1]&month=$matches[2]&day=$matches[3]&paged=$matches[4]';
$rewrite_rules['([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/?$'] = 'index.php?year=$matches[1]&month=$matches[2]&day=$matches[3]';
$rewrite_rules['([0-9]{4})/([0-9]{1,2})/page/?([0-9]{1,})/?$'] = 'index.php?year=$matches[1]&month=$matches[2]&paged=$matches[3]';
$rewrite_rules['([0-9]{4})/([0-9]{1,2})/?$'] = 'index.php?year=$matches[1]&month=$matches[2]';
$rewrite_rules['([0-9]{4})/page/?([0-9]{1,})/?$'] = 'index.php?year=$matches[1]&paged=$matches[2]';
$rewrite_rules['([0-9]{4})/?$'] = 'index.php?year=$matches[1]';
/**/
$rewrite_rules['(.?.+?)/page/?([0-9]{1,})/?$'] = 'index.php?pagename=$matches[1]&paged=$matches[2]';
$rewrite_rules['(.?.+?)(?:/([0-9]+))?/?$'] = 'index.php?pagename=$matches[1]&page=$matches[2]';
$rewrite_rules['([^/]+)/page/?([0-9]{1,})/?$'] = 'index.php?name=$matches[1]&paged=$matches[2]';
$rewrite_rules['([^/]+)(?:/([0-9]+))?/?$'] = 'index.php?name=$matches[1]&page=$matches[2]';
//adding additional rules in array in the bottom
if (!empty($additional_rules) && $location == 'bottom') {
foreach ($additional_rules as $key => $value) {
$rewrite_rules[$key] = $value;
}
}
/*
* Here rewrite rules I am storing in global variable named rewrite but
* this can be serialized and stored to database so that it can be accessed wherever needed just like
* I have called saveConfig in comment for real project to save rewrite rules in Database
*/
$GLOBALS['rewrite'] = $rewrite_rules;
//saveConfig('rewrite_rules', serialize($rewrite_rules));
}
function parse_request($extra_query_vars = '') {
$rewrite_index = "index.php";
// Process PATH_INFO, REQUEST_URI, and 404 for permalinks.
// Fetch the rewrite rules.
/*
* Here rewrite rules I am fetching from global variable named rewrite but
* this can be unserialize after fetching from database just like
* I have called getConfig function to fetch from database and unserialized in real project
*/
$rewrite = $GLOBALS['rewrite'];
//$rewrite = unserialize(getConfig("rewrite_rules"));
if (!empty($rewrite)) {
// If we match a rewrite rule, this will be cleared.
$error = '404';
$pathinfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
list( $pathinfo ) = explode('?', $pathinfo);
$pathinfo = str_replace('%', '%25', $pathinfo);
list( $req_uri ) = explode('?', $_SERVER['REQUEST_URI']);
$self = $_SERVER['PHP_SELF'];
$home_path = trim(parse_url(SITE_URL, PHP_URL_PATH), '/');
$home_path_regex = sprintf('|^%s|i', preg_quote($home_path, '|'));
// Trim path info from the end and the leading home path from the
// front. For path info requests, this leaves us with the requesting
// filename, if any. For 404 requests, this leaves us with the
// requested permalink.
$req_uri = str_replace($pathinfo, '', $req_uri);
$req_uri = trim($req_uri, '/');
$req_uri = preg_replace($home_path_regex, '', $req_uri);
$req_uri = trim($req_uri, '/');
$pathinfo = trim($pathinfo, '/');
$pathinfo = preg_replace($home_path_regex, '', $pathinfo);
$pathinfo = trim($pathinfo, '/');
$self = trim($self, '/');
$self = preg_replace($home_path_regex, '', $self);
$self = trim($self, '/');
// The requested permalink is in $pathinfo for path info requests and
// $req_uri for other requests.
if (!empty($pathinfo) && !preg_match('|^.*' . $rewrite_index . '$|', $pathinfo)) {
$requested_path = $pathinfo;
} else {
// If the request uri is the index, blank it out so that we don't try to match it against a rule.
if ($req_uri == $rewrite_index) {
$req_uri = '';
}
$requested_path = $req_uri;
}
$requested_file = $req_uri;
// Look for matches.
$request_match = $requested_path;
if (empty($request_match)) {
// An empty request could only match against ^$ regex
if (isset($rewrite['$'])) {
$query = $rewrite['$'];
$matches = array('');
}
} else {
foreach ((array) $rewrite as $match => $query) {
// If the requested file is the anchor of the match, prepend it to the path info.
if (!empty($requested_file) && strpos($match, $requested_file) === 0 && $requested_file != $requested_path) {
$request_match = $requested_file . '/' . $requested_path;
}
if (preg_match("#^$match#", $request_match, $matches) || preg_match("#^$match#", urldecode($request_match), $matches)) {
// Got a match.
$matched_rule = $match;
break;
}
}
}
if (isset($matched_rule)) {
// Trim the query of everything up to the '?'.
$query = preg_replace('!^.+\?!', '', $query);
// Substitute the substring matches into the query.
$matched_query = addslashes(MatchesMapRegex::apply($query, $matches));
// Parse the query.
parse_str($matched_query, $perma_query_vars);
// If we're processing a 404 request, clear the error var since we found something.
if ('404' == $error) {
unset($error, $_GET['error']);
}
}
// If req_uri is empty or if it is a request for ourself, unset error.
if (empty($requested_path) || $requested_file == $self) {
unset($error, $_GET['error']);
if (isset($perma_query_vars)) {
unset($perma_query_vars);
}
}
}
if (isset($perma_query_vars)) {
return $perma_query_vars;
}
return null;
}
matches.php
Ví dụ
<?php
/**
* Helper class to remove the need to use eval to replace $matches[] in query strings.
* Taken From Wordpress
*/
class MatchesMapRegex {
private $_matches;
public $output;
private $_subject;
public $_pattern = '(\$matches\[[1-9]+[0-9]*\])'; // magic number
public function __construct($subject, $matches) {
$this->_subject = $subject;
$this->_matches = $matches;
$this->output = $this->_map();
}
public static function apply($subject, $matches) {
$oSelf = new MatchesMapRegex($subject, $matches);
return $oSelf->output;
}
private function _map() {
$callback = array($this, 'callback');
return preg_replace_callback($this->_pattern, $callback, $this->_subject);
}
public function callback($matches) {
$index = intval(substr($matches[0], 9, -1));
return ( isset($this->_matches[$index]) ? urlencode($this->_matches[$index]) : '' );
}
}
index.php
Ví dụ
<?php
include_once 'config.php';
/*
* This function can be called where updatation of rewrite rules required
* and can be updated to database i.e while creating new Category or updating permalink, etc
*/
updateRewriteRules();
$request = parse_request();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<?php
if ($request == null || empty($request)) {
//Process home page
echo "include home page here"; //include('home.php');
} else if (isset($request['category_name'])) {
//Process category page
echo "inclue category page here"; //include('category.php');
} else if (isset($request['tag'])) {
//Process tag page
echo "include tag page here"; //include('tag.php');
} else if (isset($request['s'])) {
//Process search page
echo "include search page here"; //include('search.php');
} else if (isset($request['author_name'])) {
//Process author page
echo "include author page here"; //include('author.php');
} else if (isset($request['pagename'])) {
//Process page/post page
echo "page/post page here and show page or post according to post_type"; //include('post.php');
} else if (isset($request['year']) || isset($request['month']) || isset($request['day'])) {
//Process page/post page
echo "include posts page here"; //include('post.php');
} else if (isset($request['login'])) {
//Process product page
echo "include login page here"; //include('login.php');
} else if (isset($request['logout'])) {
//Process logout page
echo "logout code or logout page here"; //include('logout.php');
} else if (isset($request['register'])) {
//Process register page
echo "include registration page here"; //include('register.php');
} else {
//Process 404 page
echo "include Page not found template here"; //include('404.php');
}
?>
</body>
</html>
.htaccess
Ví dụ
# BEGIN
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /urlrewriting/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /urlrewriting/index.php [L]
</IfModule>
# END
Ghi chú: RewriteBasemình để làurlrewritingvì code mình để trong thư mụcurlrewriting, nếu bạn để ở thư mục root của website nhưwww, htdocshaypublic_htmlthì bạn thay bằng/nhé.
Chúc thành công
Câu hỏi liên quan
Dưới đây là một số câu hỏi thường gặp khác liên quan đến chủ đề này:
- Làm sao tạo trang 404 trong PHP?
- Lỗi cannot be part of FULLTEXT index
- Làm sao xuất XMLWriter thành tệp XML trong PHP?
- Kết quả kiểu trả về JSON từ PHP Script
- Cách xóa ký tự cuối cùng khỏi chuỗi trong PHP
Unknown Error
Unknown Error: [2] Undefined array key "PREV_PAGE"
File: /home/vzn.vn/public_html/config/vzn.template.php(491) : eval()'d code
Line: 1
File: /home/vzn.vn/public_html/config/vzn.template.php(491) : eval()'d code
Line: 1