9月にはてなブログがリリースしたブログカード、かっこいいですよね。
こんなやつ。
WordPressでも、はてなブログoEmbed APIというのを使っていて、以下の方法でブログカードを表示できます。
はてなブログの「ブログカード」をWordPressのoEmbedに対応させる方法
で、常々「はてなのブログカードみたいなのをWordpressの記事に対しても使えないかな?」と思っていたところ、Simplicityのフォーラムにブログカード機能リクエストをいただきました。良い機会なので、Wordpressでもブログカードが使えるようになるコードを書いてみました。
そしたら、何とか形にはなったので、その方法の紹介です。
目次
作成したWordpressブログカード
今回作成したブログカードは、以下のような表示になります。(追記:はてブ数やサイトリンクは、後に機能追加されたもので以下の方法では表示されません。)
サムネイルを左側にした以外は、はてなみたいな感じにしてみました。
これは、単に以下のようにエディターで書いたのみです。
実際のブログカードは、以下のようになります。 https://nelog.jp/mf-cloud https://nelog.jp/amazon-prime サムネイルを左側にした以外は、はてなみたいな感じにしてみました。
WordPressブログカードの仕様
今回試しにカスタマイズしてみたブログカードの仕様は以下のようになっています。
- 本文記事の1行にサイト内URLのみが記載されていたらブログカード化する
- 1行にURL以外も記載されているとブログカード化しない
- カード化されるのは「投稿ページ」「固定ページ」のみ
- あくまで自サイトURLのみで他サイトのURLではカード化されない
WordPressエディターなどで編集していて、その本文中の1行を「サイト内URL」のみで使用していれば、URLがブログカードに置き換わるという仕様です。
WordPressデフォルトにあるテーマのTwenty Fourteenで動作確認もしました。
WordPressサイト内ブログカードの実装方法
このブログカードの実装方法を説明します。
とは言っても、実装はコードのコピペを2回するだけなので、それほど難しくはないと思います。
NO IMAGE画像の準備
まずは、記事にサムネイルがなかった場合の、画像の準備をします。
以下のような画像を、テーマフォルダの「images」フォルダ内にコピーをしてください。
functions.phpの編集
functions.phpは、編集を誤るとエラーが出てサイト表示されなくなるので、必ず編集前にバックアップを取っておいてください。
functions.phpには、以下のコードを追記します。(子テーマのfunctions.phpでもOK)
//100×100pxのサムネイルを作成 add_image_size('thumb100', 100, 100, true); //サイトドメインを取得 function get_this_site_domain(){ //ドメイン情報を$results[1]に取得する preg_match( '/https?:\/\/(.+?)\//i', admin_url(), $results ); return $results[1]; } //本文抜粋を取得する関数(綺麗な抜粋文を作成するため) //使用方法:https://nelog.jp/get_the_custom_excerpt function get_the_custom_excerpt($content, $length) { $length = ($length ? $length : 70);//デフォルトの長さを指定する $content = preg_replace('/<!--more-->.+/is',"",$content); //moreタグ以降削除 $content = strip_shortcodes($content);//ショートコード削除 $content = strip_tags($content);//タグの除去 $content = str_replace(" ","",$content);//特殊文字の削除(今回はスペースのみ) $content = mb_substr($content,0,$length);//文字列を指定した長さで切り取る return $content; } //本文中のURLをブログカードタグに変更する function url_to_blog_card($the_content) { if ( is_singular() ) {//投稿ページもしくは固定ページのとき //1行にURLのみが期待されている行(URL)を全て$mに取得 $res = preg_match_all('/^(<p>)?(<a.+?>)?https?:\/\/'.preg_quote(get_this_site_domain()).'\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+(<\/a>)?(<\/p>)?(<br ? \/>)?$/im', $the_content,$m); //マッチしたURL一つ一つをループしてカードを作成 foreach ($m[0] as $match) { $url = strip_tags($match);//URL $id = url_to_postid( $url );//IDを取得(URLから投稿ID変換) if ( !$id ) continue;//IDを取得できない場合はループを飛ばす $post = get_post($id);//IDから投稿情報の取得 $title = $post->post_title;//タイトルの取得 $date = mysql2date('Y-m-d H:i', $post->post_date);//投稿日の取得 $excerpt = get_the_custom_excerpt($post->post_content, 90);//抜粋の取得 $thumbnail = get_the_post_thumbnail($id, 'thumb100', array('style' => 'width:100px;height:100px;', 'class' => 'blog-card-thumb-image'));//サムネイルの取得(要100×100のサムネイル設定) if ( !$thumbnail ) {//サムネイルが存在しない場合 $thumbnail = '<img src="'.get_template_directory_uri().'/images/no-image.png" style="width:100px;height:100px;" />'; } //取得した情報からブログカードのHTMLタグを作成 $tag = '<div class="blog-card"><div class="blog-card-thumbnail"><a href="'.$url.'" class="blog-card-thumbnail-link">'.$thumbnail.'</a></div><div class="blog-card-content"><div class="blog-card-title"><a href="'.$url.'" class="blog-card-title-link">'.$title.'</a></div><div class="blog-card-excerpt">'.$excerpt.'</div></div><div class="blog-card-footer clear"><span class="blog-card-date">'.$date.'</span></div></div>'; //本文中のURLをブログカードタグで置換 $the_content = preg_replace('{'.preg_quote($match).'}', $tag , $the_content, 1); } } return $the_content;//置換後のコンテンツを返す } add_filter('the_content','url_to_blog_card');//本文表示をフック
get_this_site_domain()で自分のサイトのドメインを取得し、自分のサイトの記事のみブログカード化します。
get_the_custom_excerpt()は、綺麗な抜粋を取得する関数です。Wordpress標準関数であるget_the_excerpt()みたいなもの($post->post_excerpt)で抜粋を取得しても良いのですが、ショートコードや特殊文字もそのまま表示されてしまうので、綺麗な抜粋文を作る関数を以前作成したのを流用しています。
詳しくは以下。
url_to_blog_card()は、今回の実装のメイン部分です。本文表示をフックして、記事内に含まれるサイト内URLを、ブログカードに置換しています。
style.cssの編集
style.cssには、以下のコードを貼り付けます。(子テーマのstyle.cssでもOK)
/************************************ ** ブログカードのスタイル ************************************/ .blog-card{ padding:12px; margin:10px 0; border:1px solid #ddd; word-wrap:break-word; max-width:100%; width:474px; border-radius:5px; } .blog-card-thumbnail{ float:left; } .blog-card-content{ margin-left:110px; line-height:120%; } .blog-card-title{ margin-bottom:5px; } .blog-card-title a{ font-weight:bold; text-decoration:none; color:#111; } .blog-card-excerpt{ color:#333; font-size:90%; } .blog-card-footer{ font-size:70%; color:#777; margin-top:5px; } .clear{ clear:both; }
はてなのブログカードのように、サムネイルを右側に持っていたり、文字サイズを好みの大きさにしたりは、このCSSをちょこっと編集すればできると思います。
このカスタマイズの注意点
ただ、このカスタマイズには以下のような注意点があります。
- <p>タグとURLを合わせて正規表現で判断しているので、pタグを除去するようなカスタマイズをしていると動作をしない
- このカスタマイズを使用してしばらく使った後、カスタマイズやめると、ただ単にURLが表示されるだけになる
- Simplicityに今回のカスタマイズをすると、関数名がかぶるのでエラーが出る
- 未知の不具合があるかもしれない
Pタグを除去するカスタマイズをしている場合は、正規表現部分をちょこっといじれば対応できると思います。
Simplicityには、いずれ機能追加予定なのでしばらくお待ちください。(カスタマイズする場合は、エラーの出る関数を削除すればOKです。)
追記:Simplicityにもver20141027より今回紹介した機能+αを追加しました。
WordPress4.4の埋め込みカードを無効にする方法
WordPress4.4から内部リンク、もしくは他ブログの外部リンク(oEmbed対応)を埋め込み表示できるようになりました。
こんなのが表示されます。
この新機能は、今回のカスタマイズと機能が競合して、記事にURLのみを記入した場合は、Wordpress標準の埋め込み機能が適用されてしまうことがあります。
これを回避するには、以下のように記事中にURLのみを記入するのではなく
https://nelog.jp/wordpress-blog-card
以下のようなURLリンクを挿入することで回避することができます。
<a href="https://nelog.jp/wordpress-blog-card">https://nelog.jp/wordpress-blog-card</a>
WordPress標準の埋め込みを無効にするコード
また、functions.phpに、以下のように記述すると、Wordpress標準の埋め込み動作を無効にすることも出来るようです。
//oembed無効 add_filter( 'embed_oembed_discover', '__return_false' ); //Embeds remove_action( 'parse_query', 'wp_oembed_parse_query' ); remove_action( 'wp_head', 'wp_oembed_remove_discovery_links' ); remove_action( 'wp_head', 'wp_oembed_remove_host_js' ); //Wordpress4.5.3でポスト時に再び表示されるようになってしまったので対処 remove_filter( 'pre_oembed_result', 'wp_filter_pre_oembed_result');
上記のコードは、以下を参考にさせていただきました。
参考 WordPress 4.4に備えよ! ~WordPress4.4の新機能~ | ぴんくいろにっき
oEmbedの参照先を強制する
もし仮に、上記の方法で、うまくいかなかった場合は、以下のコードをfunctions.phpに挿入してみてください。
wp_oembed_add_provider('http://*', 'http://hatenablog.com/oembed ');
上記の方法は、僕も偶然発見したため、どうして上記のように書くと、Wordpress標準の埋め込み動作しなくなるのか、よくわかってません。それとともに、はてなブログのURLを記事中に挿入すると、はてなブログの埋め込みカードは表示されるようになってしまいます。ご注意ください。
個人的には、ホワイトリスト形式ではてなブログカードのoembedを有効にしたことで、それ以外は無効になるのかなと思っています。(※詳細は確かめてません)
追記:コメントで、Hinaloeさんに教えていただきました。wp_oembed_oembed_add_provider は、(正規表現に一致する:すべての)oEmbedの参照先をはてなブログに強制させるという動作をしているようです。
(追記:2015年12月11日)
まとめ
以前からWordpressにもサイト内記事紹介用のブログカードを作りたいと思っていたんですけど、難しそうで手も付けていませんでした。
ただ、今回リクエストもらってやってみたら、何とか実装することができたので、何事もやってみるもんだなと思います。案ずるより産むが易しです。
一応、今回の方法の不具合確認はしましたが、もし変な動作をしたとしたら、連絡をいただければ修正します。
今回のブログカードの実装で、通常のリンクよりは、それなりに見た目が良くなったと思うので、「多少クリック率が上がって、サイト巡回率もよりよくなってくれるのでは?」と秘かに期待しています。
追記:外部URLで表示させるには、以下の方法がお勧めです。
こちら動きませんでした。
固定ページで試してみましたが、ダメだった用です。
もし可能でしたら導入をご教授いただきたいです。