ちょっとピコンときたので、WordPress 2.3から導入された機能「カノニカルURL」を使って、短縮urlを実現するプラグインを書いてみました。
まだまだβ段階もいいところなんですが、とりあえず公開しておきます。ご要望をお寄せください。
http://dl.getdropbox.com/u/110305/New/short-link-maker.zip
このプラグインを有効化すると、シングルページの <head> 内に <link rel="shortlink" href="https://dogmap.jp/〜" />
という META タグが吐き出されます。
また、この META タグの href に対してアクセスすると、正式なURLにリダイレクトされるようになります。
Twitter や、印刷した紙に短い URL を書きたいときなんかに使ってください。
ちなみに URL は、単純に post_ID を62進数に変換しただけのものなので、カテゴリ一覧やタグ一覧などでは使えません。
あくまでも post_ID を持っているページのみに対応しています。
さて、これを作る際に困ったのが redirect_canonical フィルタの使い方。
wp-includes/canonical.php
を見ると分かりますが、いつもどおり add_filter() で単純に使うだけだとハマりますので注意してください。
# つうか、限りなく仕様不備のような気もする。
カノニカルURL機能を実現しているのは redirect_canonical()
という関数です。
この関数の最後で $redirect_url = apply_filters('redirect_canonical', $redirect_url, $requested_url);
とやって、'redirect_canonical' というフィルターを使えるようにしてくれているので、このフィルターをフックしてやれば、リクエストがあったURLとは違うURLにリダイレクトしてやることができます。
が、この redirect_canonical() 関数、apply_filter() を呼んだ後で、そのリダイレクト先のURLが正しいかどうかをチェックするために、再度自分を呼んでる(293行目)のです。
if ( $redirect_url == $requested_url ) return false; // Note that you can use the "redirect_canonical" filter to cancel a canonical redirect for whatever reason by returning FALSE $redirect_url = apply_filters('redirect_canonical', $redirect_url, $requested_url); if ( !$redirect_url || $redirect_url == $requested_url ) // yes, again -- in case the filter aborted the request return false; if ( $do_redirect ) { // protect against chained redirects if ( !redirect_canonical($redirect_url, false) ) { wp_redirect($redirect_url, 301); exit(); } else { // Debug // die("1: $redirect_url<br />2: " . redirect_canonical( $redirect_url, false ) ); return false; } } else { return $redirect_url; }
WordPress のカノニカルURL機能では、実在しないURLをリクエストされた時、似たようなURLをサイト内から探して候補を出します。
例えば https://dogmap.jp/pU
という URL がリクエストされた場合、 WordPress は https://dogmap.jp/2007/09/05/put-scripts-at-the-bottom/
をリダイレクト先の候補にします。
しかし、本当は https://dogmap.jp/pU
という URL は、post ID 1606 の https://dogmap.jp/2008/03/12/wordpress-233-feed/
にリダイレクトさせたいのです。
そこで 'redirect_canonical' というフィルターをフックして https://dogmap.jp/pU
という URL がリクエストされた場合 https://dogmap.jp/2008/03/12/wordpress-233-feed/
をリダイレクト先に指定してやるのですが、2回目にフィルタを呼ばれたときに正常にフィルタ内の関数が動作しない…
というわけで、以下のような実装にしました。
function redirect_shortlink($redirect_url, $requested_url){ remove_filter('redirect_canonical', 'redirect_shortlink' ); if (empty($requested_url)) return $redirect_url; $siteurl = trailingslashit(get_option('siteurl')); $pattern = '/^' . preg_quote($siteurl, '/') . '([\da-zA-Z]+)$/'; if ( preg_match_all( $pattern, $requested_url, $matches ) ) { $link_id = $matches[1][0]; $post_id = n_to_dec($link_id, 62); if ( $post_id !== FALSE ) $redirect_url = get_permalink($post_id); if ( empty($redirect_url) ) $redirect_url = ( preg_match('/[\d]+/', $link_id) ? get_permalink($link_id) : get_permalink(hexdec($link_id)) ); add_filter('redirect_canonical', create_function( '', "return '$redirect_url';")); } unset($matches); return $redirect_url; } add_filter('redirect_canonical', 'redirect_shortlink', 10, 2 );
redirect_canonical() 関数が二回目に呼び出されたときには、一度目に取得したリダイレクトURLを返すようにフィルターを変更しています。
弊サイトで Simple Tweet とセットで使わせてもらっています。非常に重宝してます。感謝です!
もし可能であれば、以下のようにサブドメインも除去できればと思うのですが、出来るものでしょうか?
http://www.example.com/archives/1606 → http://example.com/Bb
Ai さん、はじめまして。
WordPress の機能を使って短縮URLからのリダイレクトを実装してるので、サブドメイン除去するのは、ムリです。
なるほど。残念ですが、そのような理由であれば仕方ないですね。
ありがとうございます。