Lý do bạn cần cài Subdomain
Chắc trong số các bạn đọc blog này đều biết subdomain là gì rồi đúng không ? Subdomain là domain nhưng theo dạng: sub.example.com và sub chính là subdomain của example.com, ví dụ trực quan hơn là mỗi một địa chỉ blog trên WordPress.com sẽ là subdomain của WordPress.com.
Tiếp theo là subdomain để làm gì ? Khi bạn quản trị một website với số lượng lớn người dùng nhưng bạn không muốn mỗi người dùng thừa kế lại các giá trị của domain chính thì bạn cần phân tách ra thành các subdomain, tương ứng với mỗi người dùng riêng lẻ.
Nhắc lại chuyện http://hubpages.com nổi tiếng trước kia, Hubpages bị công cụ tìm kiếm lớn nhất thế giới là Google phạt do nội dung trong trang không chất lượng và có phần là Spam, sau vụ đó Hubpage đã phải sa thải một số nhân viên để bảo toàn, ngoài ra việc phải giữ lại các bài viết của người dùng nhưng làm sao cho không ảnh hưởng tới giá trị gốc của tên miền nên hubpage đã tách toàn bộ người dùng dưới dạng user.hubpages.com, và đó là bài học cho những ai xây dựng website giống như các trang xã hội.
Lý do thứ hai: bạn muốn các dự án độc lập với nhau nhưng lại trên cùng một tên miền nhằm tiết kiệm chi phí, hoặc bạn cần phải giữ lại thương hiệu sau các dự án phụ …
Lý do tiếp theo có thể là: bạn đang muốn tạo ra một trang mạng xã hội giống hubpages :) nhưng không muốn đi vào vết xe đổ của nó.
Dù bất cứ lý do gì đang tương ứng với trường hợp của bạn thì việc cài subdomain cho wordpress không phải là chuyện khó, bạn chỉ cần cài đặt theo hướng dẫn WordPress Multi User (WordPress MU).
Nhưng các bạn sẽ thấy WordPress MU có nhược điểm riêng mà nếu bạn làm dự án với < 10 subdomain thì được, còn hơn nữa sẽ rất khó, với mỗi một user sẽ sinh ra các bảng dữ liệu khác nhau kèm theo ID của người dùng, như vậy nếu > 10 subdomain hoặc bạn cho phép mọi người dùng dưới dạng subdomain thì bạn sẽ có số bảng = ( 10 bảng x số user ). Host của bạn có thể không chịu nổi hoặc bạn sẽ đối mặt với hàng triệu bảng cơ sở dữ liệu.
Làm sao để mỗi user sẽ vẫn có subdomain và không làm phình cơ sở dữ liệu của bạn ? Làm sao để WordPress vẫn giữ được các bảng cơ sở dữ liệu nhưng hệ thống lại chạy như WordPress MU? Làm sao cho cả một category của WordPress thành subdomain nữa ? Tất cả các câu hỏi này sẽ được trả lời nếu bạn đọc tiếp phần dưới.
Lý do bạn nên đọc kỹ bài viết này
Plugin của WordPress về subdomain hiếm như số ngón trên một bàn tay, hầu hết chúng là plugin ruồi, chuyên redirect theo dạng keyword.example.com về example.com/bài viết.html … Và mục đích chính là câu từ khóa làm SEO mà thôi.
Đáng kể nhất có Subdomains Plugin
Là Plugin chuyển toàn bộ category sang dạng subdomain nhưng đã ngừng phát triển từ 3.0 trở đi, nên phát sinh lỗi khi bài viết nằm trong category gốc dưới dạng:
- Sub.example.com/bài viết => 404
- Sub.example.com/subcategory/ => 200 OKEY
Ngoài ra có WP Subdomains Revisited, là plugin kế thừa Subdomains Plugin, có hỗ trợ 3.x nhưng phát sinh một số lỗi mà theo tôi là do tác giả “cố tình”. Trong khi đó plugin này hoạt động cồng kềnh gây chậm trang khi request tới subdomain.
Tôi không muốn liệt kê ra cách khắc phục các nhược điểm của plugin có sẵn mà muốn các bạn hiểu nhiều hơn về cách WordPress xử lý các chuỗi đường dẫn để các bạn có thể tự khắc phục nhược điểm của plugin hoặc viết một plugin đủ thông minh phục vụ chính dự án website của bạn.
Hiểu về .htaccess của WordPress
Đây là nội dung của file .htacess
[bash]
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ – [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
[/bash]
Qua đây bạn có thể thấy rằng WordPress xử lý mọi tình huống qua file index.php, kể cả bạn cài WordPress MU thì đoạn này cũng hầu như không đổi, vậy là subdomain của chúng ta cần phải can thiệp vào core.
Hiểu thêm về Class WP Rewrite
Các bạn có thể xem WordPress giải trình các hàm hay các chức năng, nói chung là mọi thông tin tại đây: http://codex.wordpress.org/Class_Reference/WP_Rewrite
Class Rewrite của WordPress tương đối phức tạp, nhưng chúng ta không bàn nhiều tới nó, tôi muốn giải thích cho các bạn là mọi đường dẫn trong WordPress, các quy tắc và ngay cả Subdomain đều phải hook vào các hàm trong Class Rewrite này.
Nếu bạn muốn hiểu thêm về class này hoặc đang muốn xem các quy định mặc định của WordPress hãy làm theo cách sau:
global $wp_rewrite;print ”;print_r( $wp_rewrite->rules );print ”;
Ví dụ nó sẽ in ra:
Array(‘(^.*)/(*).html’ => ‘index.php&name=$match[2]’);
Bạn thấy quen không ? Đây chính là đường dẫn mặc định của post theo dạng domain.con/category/postname.html
. Khi các bạn đọc kỹ phần sau các bạn sẽ thấy đây chính là điểm chính mà chúng ta sẽ sửa cho nó hiểu được subdomain …
Lưu ý thêm với các bạn là đây là một class cực kỳ quan trọng, nếu các bạn làm không đúng hướng dẫn hoặc để chúng xung với nhau sẽ luôn trả về mã 404 NOT FOUND. Vậy thì hãy đọc kỹ phần sau để rõ hơn nhé.
Chi tiết công việc
Trình duyệt đang yêu cầu subdomain nào ?
Bạn nên tìm hiểu biến toàn cục $_SERVER
, các bạn có thể var_dump( $_SERVER );
vào bất cứ nơi nào trong WordPress là nó sẽ in ra các thông tin cho bạn.
Để tìm xem trình duyệt đang gọi subdomain gì các bạn dùng giá trị của $_SERVER['HTTP_HOST'];
Kiểm tra subdomain
Tùy mục đích của các bạn mà chúng ta sẽ kiểm tra xem subdomain có tồn tại và hợp lệ hay không, tôi lấy ví dụ như sau:
// kiểm tra user
if ( get_user_by(‘login’, $subdomain) ) {
// hợp lệ
} else {
$wp_rewrite->is_404 = true;
// die();
}
// kiểm tra xem subdomain đó có phải là category không …
if ( get_term_by(‘slug’, $subdomain, ‘category’)) {
// đúng, hợp lệ
} else {
// không đúng, trả về 404 …
}
Làm cho WP_rewrite hiểu được truy vấn
Cũng là tùy vào nhu cầu dùng của bạn, bạn có thể đặt category là sub, hoặc User là sub, tôi lấy ví dụ như sau:
1. Tìm hook: author_rewrite_rules là một hook để viết lại đường dẫn cho USER … category_rewrite_rules là hook viết lại đường dẫn cho category…
2. Thêm quy tắc mới vào Class WP_rewrite
:
Ví dụ:
add_fillters(‘author_rewrite_rule’, ‘_rewrite_author_’);function _rewrite_author_( $rules ) {//$rules chứa các quy tắc mặc định của WordPress$field = ‘author_name’; // đây là giá trị để định quy tắc của WordPress$slug = $subcategory; // đây chính là đường dẫn mới kiểu slug.example.com$rules = array();$rules["feed/(feed|rdf|rss|rss2|atom)/?$"] = "index.php?" . $field . "=" . $slug . "&feed=$matches[1]";$rules["(feed|rdf|rss|rss2|atom)/?$"] = "index.php?" . $field . "=" . $slug . "&feed=$matches[1]";$rules["page/?([0-9]{1,})/?$"] = "index.php?" . $field . "=" . $slug . "&paged=$matches[1]";$rules["$"] = "index.php?" . $field . "=" . $slug;}
Chú ý: $rules
của WordPress luôn bắt đầu là 1 chứ không phải là 0 như trong PHP bạn thường thấy.
Đến đoạn này, các bạn đã có thể truy cập được dạng author.example.com nhưng đường dẫn thực chính là example.com/author/user.
Chỉnh lại đường dẫn trong trang
Bạn hãy tìm hàm liên quan tới đường dẫn của User hoặc Category tùy nhu cầu của bạn để chỉnh lại đường dẫn của đối tượng bạn muốn.
Ví dụ: hook author_link chứa đường dẫn của User dưới dạng example.com/author/User, chúng ta sẽ chỉnh lại:
add_filters(‘author_link’, ‘_rewrite_author_link’, 10, 2);function _rewrite_author_link( $link, $userid ) {
// có 2 cách để viết lại đường dẫn này. // cách 1: return preg_match_replace(‘/www.example.com/author/(.*)/’, ‘$1.example.com’, $link);
// cách 2: $userdata = get_user_by(‘id’, $userid); return ‘//’. $userdata->user_login . ‘.example.com’; }
Chỉnh lại đường dẫn phân trang
Plugin WP PageNavi phối hợp rất tốt với hook 'get_pagenum_link'
nên bạn hãy dùng plugin này để phân trang !
Đường dẫn phân trang sẽ vẫn là dạng cũ example.com/category/page/2/
Ngoài ra chúng ta cũng đã khai báo quy tắc mới bên trên cho core WordPress biết đường dẫn mới của phân trang:
$rules["page/?([0-9]{1,})/?$"] = "index.php?" . $field . "=" . $slug
Đến đoạn này core đã hiểu đường dẫn mới là subdomain.example.com/page/x nhưng hook get_pagenum_link vẫn trả về đường dẫn cũ nên bạn cần phải chỉnh lại đường dẫn, tôi lấy ví dụ như sau:
add_filters(‘get_pagenum_link’, ‘_rewrite_pagenum’);function _rewrite_pagenum( $url ) {// bạn cần phải làm sao trả về đường dẫn sub.example.com để plugin tự phân trang thêm page/x vào đường dẫn thôi …return $url;}
Hoàn thành công việc
Vì WordPress cache kết quả cho các quy tắc của mình nên bạn cần phải xóa cache thì mới có thể làm cho core nạp quy tắc mới, nhưng các bạn lưu ý là khi add_action và hook INIT hay WP thì cứ khi nào trang web được yêu cầu là hàm này sẽ được gọi, nghĩa là:
WORDPRESS RUN INT > UPDATE REWRITE > CALL REWRITE
Công việc này lặp đi lặp lại nên có thể làm cho cơ sở dữ liệu của bạn bận rộn, muốn tăng tốc công việc của Core bạn cần phải nghĩ ra cách để giảm thiểu việc này.
Vì sao phải UPDATE cache của quy tắc mỗi lần request tới ? Đơn giản thế này:
Cache sẽ lưu trữ kết quả của author.example.com nhưng khi bạn vào category.example.com thì kết quả trước sẽ trả về mã 404 ( không có người dùng tên là category ).
function rewrite_init () {
if (!is_admin()) {
if (function_exists(‘set_transient’)) {
set_transient(‘rewrite_rules’, "");
update_option(‘rewrite_rules’, "");
} else {
update_option(‘rewrite_rules’, "");
}
}
}
add_action(‘init’, ‘rewrite_init’);
Các hook để bạn tham khảo
- ‘rewrite_rules_array’
- ‘root_rewrite_rules’
- ‘post_rewrite_rules’
- ‘page_rewrite_rules’
- ‘date_rewrite_rules’
- ‘tag_rewrite_rules’
- ‘category_rewrite_rules’
- ‘author_rewrite_rules’
- ‘get_pages’
- ‘bloginfo_url’
- ‘bloginfo’
- ‘category_link’
- ‘post_link’
- ‘page_link’
- ‘author_link’
- ‘tag_link’
- ‘month_link’
- ‘get_pagenum_link’
Tổng kết
Tôi đã nghiên cứu WordPress từ rất lâu và hiểu rất sâu hệ thống code của WordPress, nhưng tôi thấy WordPress MU có nhiều nhược điểm trong khi không thấy ai viết bài hướng dẫn cho chúng ta tự viết plugin để phục vụ cho mục đích của mình, thứ nữa là các plugin đều giải quyết hoàn toàn không triệt để các vấn đề phát sinh, có thể do họ bỏ công sức mà sản phẩm lại là miễn phí nên có tâm lý dấu lại một ít, nên đã từ lâu tôi muốn viết một bài viết cho cộng đồng phát triển WordPress thêm thông tin để tham khảo.
Qua bài viết các bạn đã hiểu sơ qua và “đủ để” tạo ra một plugin quản lý subdomain cho mục đích của riêng mình, cũng như tôi cảnh báo ngay từ đầu là người đọc bài này cần phải có môt sự hiểu biết nhất định về WordPress hoặc phải có kiến thức lập trình mới có thể hiểu được, còn đoạn nào các bạn cần tôi giải trình thêm hãy comment bên dưới nhé !