【WordPress】iframeを使わずにはてなのブログカード風に外部リンクをデザインするショートコード

wordpress
追記)
現在、当ブログでは以下の方法での外部リンクのブログカード化は行っていません。
寝ログさんが配布されているSimplicityCocoonという無料WordPressテーマで簡単に外部リンクのブログカード化ができるので、そちらをオススメいたします。

先日、WordPressで自分のブログ内のほかの記事に内部リンクを貼る場合に、はてなブログなんかでよく見るきれいにデザインされたブログカード風のデザインにするショートコードを作りました。

【WordPress】内部リンクをはてなのブログカード風のサムネイル付きリンクにデザインするショートコード
追記) 現在、当ブログでは以下の方法での内部リンクのブログカード化は行っていません。 寝ログさんが配布されているSimplicityやCocoonという無料WordPressテーマで簡単に外部リンクのブログカード化ができるので、そちらをオス...

ただしこれはWordPress独自のタグなんかを使ってアイキャッチ画像とかを取得しているため内部リンク専用でした。
今回は、外部サイト、自分のブログ以外の人様のサイトやブログにリンクを貼る際にも、はてなのブログカード風のデザインにすることができるショートコードを作りました。

[glink url=”http://nanapi.jp/120607″]

↑こんな感じのショートコードを投稿画面に入力すると、
※[]は全角なので、コピペする場合は[]と半角にしてください。

↓こんな感じに表示されます。

http://nanapi.jp/120607

iframeを使う方法もある

WordPressではてなのブログカード風にリンクを貼る簡単な方法だと、iframeを使ってブログカードに対応させる方法があります。

はてなブログのブログカードがOGPに対応! はてなブログ以外もブログカードスタイルになるぞ
はてなブログのブログカードが拡張され、OGPにも対応しました。これによりOGPが設定されているサイトを記事中にリンクするとき、ブログカード形式で挿入することができるようになります。
http://www.allbloggerdayo.com/entry/blog-card

これはこれでお手軽でいいのですが、リファラーがhatenablog.comになってしまったり、はてな的にどうなの?と、ちょっと不具合が起こる可能性もありそうなので、今回はiframeを使わない方向で考えてみました。

リファラーを見ていて気づいたんですが、ブログカードでリンクを挿入すると、参照先がhttp://hatenablog.com/となり、リンク先ブログのアクセス解析からは自分が発リンクしたことが伝わりません。
WordPressのピンバックはもちろん、Google Analyticsのトラックバックからもログを参照できないので、「それは嫌だなぁ」という人は普通にリンクを挿入したほうが良いと思います。mbdb

考え方とカスタマイズコードと手順

自分のWordPressブログであれば、アイキャッチ画像とか記事タイトルとか説明文とか簡単に取得して表示できますが、外部サイトとなるとそう簡単にはいきません。
で、今回は本家のはてなのブログカードでも使われている「OGP(Open Graph Protocol)」を利用してブログカードを表示させたいと思います。
また、OGPの設定をしていないサイトなどでOGPを取得できない場合は、HTMLソースのタイトルタグやmetaディスクリプションタグを利用し、アイキャッチ画像の代わりに「HeartRails Capture」を使用して、リンク先のサムネイルを表示するようにしました。

プラグイン『Celtispack プラグインパック』をインストールする。

Celtispack プラグインパック』は、色々な便利な機能を持ったプラグインがパックになっています。
その中にWordPressのoEmbed機能を拡張するプラグインも入っていて、記事中にブログカードにしてリンクさせたいURLを埋め込むだけでブログカードに自動で変換してくれるという便利な機能があります。

僕は最初、このプラグインがあれば自分で作らなくてもやりたいこと実現してくれてるからいけるやん!と思ってインストールしたのですが、なぜか自分の環境ではoEmbedがうまく働いてくれなくて、URLがブログカードに変換してくれませんでした。
そんなわけで、このプラグインのコードを元にさせていただいて、ショートコードを作ることにしました。

このプラグインだけでちゃんとブログカードになった人はそれでOKです。
また、僕が作ったこのプラグインを元にしたショートコードを使う場合でも、このプラグインパックに入っているライブラリを使用するので、プラグインパックをインストールして有効化する作業は必要です。

OGPをパースするライブラリをfunctions.phpと同じディレクトリにアップ

パースってのは直訳すると「構文解析」ってことで、ある規則性の元に記述された文書を解析して、プログラムで扱えるような形に変換することです。
今回の場合、OGPという規則性の元に記述されている文書をPHPで扱えるように配列に入れることです。

で、そんな処理をしてくれるコードを自分で一から書く必要はなく、先人達が便利なコードを公開してくれているので、ありがたく使わせていただきます。

PHP Open Graph Library (mapkyca/php-ogp)

上記のサイトのogpってフォルダに入っているParser.phpをダウンロードしてきます。
そのParser.phpを、使用しているテーマのfunctions.phpと同じディレクトリにアップします。
僕は、ogpというフォルダを作ってその中に入れました。(例:wp-content/themes/stinger3_child/ogp/Parser.php)

あ、あとその前に、Parser.phpを開いて、23行目の「class Parser {」を「class Parser1 {」と1を足しておきます。

理由はちょっとややこしいんですが^^;
先にインストールしたCeltispack プラグインパックにも、Parser.phpはちゃんと含まれていまして、本来であればそれを使えばいい話なんですが、どうもプラグインフォルダへのパスの指定の仕方が分からなくて、functions.phpと同じディレクトリにアップしたわけなんす。
でそうなると、同じプラグラムがワードプレスの中に混在することになってしまい、クラス名が被っているよ!とエラーが出ます。
なので、クラス名に1を足してクラス名の重複を避けているわけです。
素人なもんでややこしいことをしてすいませんです。。。

functions.phpに追加するコード【旧版】

//OGPデータからブログカード用HTML生成

function glink_scode($atts) {//ショートコードの値を取得
	extract(shortcode_atts(array(
  	'url'=>"",
	'g_title'=>"",
	'g_dsc'=>"",
	'g_sitename'=>""
	),$atts));
	
	require_once ('ogp/Parser.php'); //OGPをパースするライブラリを読み込み
 
        $html = '';
        $args = array( 'timeout' => 10, 'httpversion' => '1.1' );
        $response = wp_safe_remote_get( $url, $args );
        //サイトによってはタイムアウトとなる場合あるのでデフォルト 5->10秒にして1回だけリトライ
        if ( is_wp_error( $response ) || $response['response']['code'] !== 200 ) {
            $response = wp_safe_remote_get( $url, $args );
        }
        if ( ! is_wp_error( $response ) && $response['response']['code'] === 200 ) {
            $head = Celtis_lib::htmltagsplit($response['body'], '<head', '/head>');
            if(!empty($head[1])){
                //OGP パース
                $ogp = ogp\Parser1::parse( mb_convert_encoding($head[1], 'HTML-ENTITIES', 'UTF-8'));                    
                $myurl = get_bloginfo('url');
                //OGP には含まれていないが favicon を head から取得 
                $ogp['og:favicon'] = '';
                preg_match('#<link.+icon.+href=.(.+\.ico|.+\.png)#', $head[1],$match);
                if(!empty($match[1])){
                    $response = wp_safe_remote_get( $match[1] );
                    if ( ! is_wp_error( $response ) && $response['response']['code'] === 200 ) {
                        $type = $response['headers']['content-type'];
                        //アイコンはローカルにキャッシュする
                        $upload = wp_upload_dir();
                        $keyid  = md5( 'icon_' . $match[1]);
                        //Hatena blog の icon は拡張子を ico にしないと IE で表示されない
                        $newext = ($type == 'image/x-icon' || $type == 'image/vnd.microsoft.icon')? 'ico' : 'png';
                        $fname  = $upload['basedir'] . '/celtispack/icon/' . "{$keyid}.{$newext}";
                        $ifp = @ fopen( $fname, 'wb' );
                        if ( $ifp ){
                            @fwrite( $ifp, $response['body'] );
                            fclose( $ifp );
                            clearstatcache();
                            // Set correct file permissions
                            $stat = @ stat( dirname( $fname ) );
                            $perms = $stat['mode'] & 0007777;
                            $perms = $perms & 0000666;
                            @ chmod( $fname, $perms );
                            clearstatcache();
                            $imageurl =  $upload['baseurl'] . '/celtispack/icon/' . "{$keyid}.{$newext}";
                            $ogp['og:favicon'] = '<img width="16" height="16" src="' . $imageurl . '"  class="favicon" />';
                        }
                    }
                }
                $thumbnail = '';
                if(!empty($ogp['og:image'])){
                    $img = (!is_array($ogp['og:image']))? $ogp['og:image'] : $ogp['og:image'][0];
                    $imgsize = array('width' => 150, 'height' => 150);
                    if(!empty($ogp['og:url']) && !preg_match("#$myurl#", $ogp['og:url'])){
                        //自サイト以外の画像はサムネイルを生成してキャッシュ
                        if(class_exists('Celtispack_thumbnail', FALSE)){
                            $module = Celtispack_thumbnail::thumbnail_module_instance();
                            $value = $module->getmake_thumbnail_size( $img, $imgsize, 'thumbnail');
                            if (false !== $value) 
                                $img = $value['url'];
                        }
                    }
                    $default_attr = array(
                        'src'	=> $img,
                        'class'	=> "ogp-thumb",
                        'alt'	=> '',
                    );
                    $imgattr = wp_parse_args($imgsize, $default_attr);
                    $imgattr = array_map( 'esc_attr', $imgattr );
                    $thumbnail = rtrim("<img ");
                    foreach ( $imgattr as $name => $value ) {
                        $thumbnail .= " $name=" . '"' . $value . '"';
                    }
                    $thumbnail .= ' />';
                }
                if(!empty($ogp['og:title']) && !empty($ogp['og:url'])){
                    $og_title = (!is_array($ogp['og:title']))? $ogp['og:title'] : $ogp['og:title'][0];
                    $og_url = (!is_array($ogp['og:url']))? $ogp['og:url'] : $ogp['og:url'][0];
                    $grid = (empty($thumbnail)) ? 'no-thumb' : 'with-thumb';
 
                    $html .= '<div class="blog-card">';
                    
                    if(!empty($thumbnail)){
                        $html .= '<a href="' . $og_url . '" target="_blank"><div class="blog-card-thumbnail">' . $thumbnail. '</a></div>';
                    }
					
					$html .= '<div class="blog-card-content"><div class="blog-card-title"><a href="' . $og_url . '" target="_blank">'.$og_title.'</a></div>';
					
					
                    if(!empty($ogp['og:description'])){
                        $og_dsc = (!is_array($ogp['og:description']))? $ogp['og:description'] : $ogp['og:description'][0];
                        $html .='<div class="blog-card-excerpt">' . $og_dsc . '</div>';
                    }
					if(!empty($ogp['og:title']) && !empty($ogp['og:url'])){
						$html .= "</div>";
					}

                    //カードフッター
                    if(!empty($ogp['og:site_name'])){
                        $og_site = (!is_array($ogp['og:site_name']))? $ogp['og:site_name'] : $ogp['og:site_name'][0];
                        $html .= '<div class="blog-card-footer clear"><div class="blog-card-favicon"><a href="' . $og_url . '" target="_blank">' . $ogp['og:favicon'] . '</div><div class="blog-card-sitename">' . $og_site . '</a></div>';
                    }
                    $html .= '</div></div>';
                    //html カスタマイズ用のフィルターフック
                    $html = apply_filters( 'oembed_ogp_dataparse', $html, $ogp, $url );
                }
                if(empty($html)){
                    //OGPを取得できない場合
                    preg_match('#<title>(.+)</title>#', $head[1],$match);
                    $title = (!empty($match[1]))? esc_html($match[1]) : esc_html($g_title);
					
					preg_match('#<meta name="description" content="(.+)">#', $head[1],$match);
                    $dsc = (!empty($match[1]))? esc_html($match[1]) : esc_html($g_dsc);
					
					$site_image = '<img src="http://capture.heartrails.com/150x150?'.$url.'" />';
					
                    $html = '<div class="blog-card"><a href="' . $url . '" target="_blank"><div class="blog-card-thumbnail">' . $site_image. '</a></div><div class="blog-card-content"><div class="blog-card-title"><a href="' . $url . '" target="_blank">'.$title.'</a></div><div class="blog-card-excerpt">' . $dsc . '</div></div><div class="blog-card-footer clear"><div class="blog-card-sitename"><a href="' . $url . '" target="_blank">' . $g_sitename . '</a></div></div></div>';
                }
            }
        }
        return $html;
    }
	
	add_shortcode("glink", "glink_scode");

functions.phpに追加するコード【改良版】

旧版のコードだと、リンク先サイトのOGP設定によっては<div>タグの閉じ忘れが発生したりすることが分かりました。
リンク先サイトの方でちゃんと全部のOGP設定を入れてくれてれば問題ないはずですが、og:imageだけがなかったり、og:descriptionだけがなかったりといったイレギュラーなケースで発生するようです。

イレギュラーなケースの条件分岐に対応してコードを作り直そうとしたのですが面倒だったので、おかしくなる場合は手動で入力するようにしました。

ショートコードに、g_sitename(サイト名)、g_title(記事タイトル)、g_dsc(説明文)の3つのパラメーターを追加できるようにしました。

[glink url=”記事のURL” g_sitename=”サイト名” g_title=”記事タイトル” g_dsc=”記事の説明文” ]

こんな感じで入力すると、OGP設定を取得せずに手動で設定した内容を出力します。
og_imageも取得しないので、キャプチャ画像となります。

[glink url=”記事のURL” ]

従来のようにURLのみ指定した場合は、OGP設定を取得しにいきます。
まずはこれで設定してみて、表示がおかしくなるようなら手動で入力するようにしてください。

[glink url=”記事のURL” g_dsc=”記事の説明文”  ]

上記のように、記事の説明文のパラメーターのみ指定した場合は、記事の説明文のみ手動入力の内容を表示し、残りの項目はOGP設定を取得しにいきます。

ちょっとややこしいので表にしますね。

設定パラメーター 動作
g_sitenameのみ設定 全てOGP設定を出力
g_titleのみ設定 全てOGP設定を出力
g_dscのみ設定 説明文のみ手動入力の内容を出力。残りはOGP設定を出力 
3つとも入力 手動で入力した内容を出力

説明文のみ個別に手動設定できるようにしている理由は、og:descriptionに記事全文を設定しているサイトがけっこう多くて、そのまま表示しちゃうとすごく大きなリンクボックスになっちゃうのと、引用の範囲を超えて無断転載レベルになっちゃいます。
かといって、あとのog:imageとかはちゃんと設定できているのに全部、手動にしてしまうのはもったいないなあと思ったからです。

また、リンク先サイトがog:imageだけ設定できていない場合は、自動的にキャプチャ画像となり、残りの項目はOGP設定から表示するようになっています。

//OGPデータからブログカード用HTML生成改

function glink_scode($atts) {//ショートコードの値を取得
	extract(shortcode_atts(array(
  	'url'=>"",
	'g_title'=>"",
	'g_dsc'=>"",
	'g_sitename'=>""
	),$atts));
	
	
	
	if(!empty($g_title) && !empty($g_dsc) && !empty($g_sitename) ){
		$site_image ='<img src="http://capture.heartrails.com/150x150?'.$url.'" />';
		$html = '<div class="blog-card"><a href="' . $url . '" target="_blank"><div class="blog-card-thumbnail">' . $site_image. '</a></div><div class="blog-card-content"><div class="blog-card-title"><a href="' . $url . '" target="_blank">'.$g_title.'</a></div><div class="blog-card-excerpt">' . $g_dsc . '</div></div><div class="blog-card-footer clear"><div class="blog-card-sitename"><a href="' . $url . '" target="_blank">' . $g_sitename . '</a></div></div></div>';
		
		}else{
			
		require_once ('ogp/Parser.php'); //OGPをパースするライブラリを読み込み
 
        $html = '';
        $args = array( 'timeout' => 10, 'httpversion' => '1.1' );
        $response = wp_safe_remote_get( $url, $args );
        //サイトによってはタイムアウトとなる場合あるのでデフォルト 5->10秒にして1回だけリトライ
        if ( is_wp_error( $response ) || $response['response']['code'] !== 200 ) {
            $response = wp_safe_remote_get( $url, $args );
        }
        if ( ! is_wp_error( $response ) && $response['response']['code'] === 200 ) {
            $head = Celtis_lib::htmltagsplit($response['body'], '<head', '/head>');
            if(!empty($head[1])){
                //OGP パース
                $ogp = ogp\Parser1::parse( mb_convert_encoding($head[1], 'HTML-ENTITIES', 'UTF-8'));                    
                $myurl = get_bloginfo('url');
                //OGP には含まれていないが favicon を head から取得 
                $ogp['og:favicon'] = '';
                preg_match('#<link.+icon.+href=.(.+\.ico|.+\.png)#', $head[1],$match);
                if(!empty($match[1])){
                    $response = wp_safe_remote_get( $match[1] );
                    if ( ! is_wp_error( $response ) && $response['response']['code'] === 200 ) {
                        $type = $response['headers']['content-type'];
                        //アイコンはローカルにキャッシュする
                        $upload = wp_upload_dir();
                        $keyid  = md5( 'icon_' . $match[1]);
                        //Hatena blog の icon は拡張子を ico にしないと IE で表示されない
                        $newext = ($type == 'image/x-icon' || $type == 'image/vnd.microsoft.icon')? 'ico' : 'png';
                        $fname  = $upload['basedir'] . '/celtispack/icon/' . "{$keyid}.{$newext}";
                        $ifp = @ fopen( $fname, 'wb' );
                        if ( $ifp ){
                            @fwrite( $ifp, $response['body'] );
                            fclose( $ifp );
                            clearstatcache();
                            // Set correct file permissions
                            $stat = @ stat( dirname( $fname ) );
                            $perms = $stat['mode'] & 0007777;
                            $perms = $perms & 0000666;
                            @ chmod( $fname, $perms );
                            clearstatcache();
                            $imageurl =  $upload['baseurl'] . '/celtispack/icon/' . "{$keyid}.{$newext}";
                            $ogp['og:favicon'] = '<img width="16" height="16" src="' . $imageurl . '"  class="favicon" />';
                        }
                    }
                }
                $thumbnail = '';
                if(!empty($ogp['og:image'])){
                    $img = (!is_array($ogp['og:image']))? $ogp['og:image'] : $ogp['og:image'][0];
                    $imgsize = array('width' => 150, 'height' => 150);
                    if(!empty($ogp['og:url']) && !preg_match("#$myurl#", $ogp['og:url'])){
                        //自サイト以外の画像はサムネイルを生成してキャッシュ
                        if(class_exists('Celtispack_thumbnail', FALSE)){
                            $module = Celtispack_thumbnail::thumbnail_module_instance();
                            $value = $module->getmake_thumbnail_size( $img, $imgsize, 'thumbnail');
                            if (false !== $value) 
                                $img = $value['url'];
                        }
                    }
                    $default_attr = array(
                        'src'	=> $img,
                        'class'	=> "ogp-thumb",
                        'alt'	=> '',
                    );
                    $imgattr = wp_parse_args($imgsize, $default_attr);
                    $imgattr = array_map( 'esc_attr', $imgattr );
                    $thumbnail = rtrim("<img ");
                    foreach ( $imgattr as $name => $value ) {
                        $thumbnail .= " $name=" . '"' . $value . '"';
                    }
                    $thumbnail .= ' />';
                }
                if(!empty($ogp['og:title']) && !empty($ogp['og:url'])){
                    $og_title = (!is_array($ogp['og:title']))? $ogp['og:title'] : $ogp['og:title'][0];
                    $og_url = (!is_array($ogp['og:url']))? $ogp['og:url'] : $ogp['og:url'][0];
                    $grid = (empty($thumbnail)) ? 'no-thumb' : 'with-thumb';
 
                    $html .= '<div class="blog-card">';
                    
                    if(!empty($thumbnail)){
                        $html .= '<a href="' . $og_url . '" target="_blank"><div class="blog-card-thumbnail">' . $thumbnail. '</a></div>';
					}else{$html .= '<a href="' . $og_url . '" target="_blank"><div class="blog-card-thumbnail"><img src="http://capture.heartrails.com/150x150?'.$url.'" /></a></div>';
						}
					
					$html .= '<div class="blog-card-content"><div class="blog-card-title"><a href="' . $og_url . '" target="_blank">'.$og_title.'</a></div>';
					
					
                    if(empty($g_dsc)){
                        $og_dsc = (!is_array($ogp['og:description']))? $ogp['og:description'] : $ogp['og:description'][0];
                        $html .='<div class="blog-card-excerpt">' . $og_dsc . '</div>';
					}else{
						$html .='<div class="blog-card-excerpt">' . $g_dsc . '</div>';
						
                    }
					if(!empty($ogp['og:title']) && !empty($ogp['og:url'])){
						$html .= "</div>";
					}

                    //カードフッター
                    if(!empty($ogp['og:site_name'])){
                        $og_site = (!is_array($ogp['og:site_name']))? $ogp['og:site_name'] : $ogp['og:site_name'][0];
                        $html .= '<div class="blog-card-footer clear"><div class="blog-card-favicon"><a href="' . $og_url . '" target="_blank">' . $ogp['og:favicon'] . '</div><div class="blog-card-sitename">' . $og_site . '</a></div>';
                    }
                    $html .= '</div></div>';

                }
                
            }
        }
	
		}
		
		return $html;
        
    }
	
	add_shortcode("glink", "glink_scode");

CSS

cssは内部リンクをブログカードにしたときと同じものを併用しています。
一応、外部リンクの場合、ファビコンも表示するので、.blog-card-faviconというクラス名を追加したくらいです。

/*ブロカード*/

.blog-card{
  padding:12px 12px 0 12px;
  margin:10px 0;
  border:1px solid #ddd;
  word-wrap:break-word;
  max-width:100%;
  /*width:522px;*/
  border-radius:5px;
}

.blog-card-thumbnail{
  float:left;
  margin-right:10px;
}

.blog-card-content{
   line-height:120%;
}
.blog-card-title{
  margin-bottom:5px;
}

.blog-card-title a{
	font-weight:bold;
	color:#111;
	text-decoration: none;
}

.blog-card-title a:hover{
	text-decoration: underline;
}

.blog-card-excerpt{
  color:#333;
  font-size:90%;
  padding-bottom:10px;
}

.blog-card-footer{
	padding:5px;
	border-top:1px solid #ddd;
	border-top-width: 90%;
}

.blog-card-hatebu{

	}

.blog-card-date{
	color:#333;
	font-size:75%;
	float:left;
	margin-right:10px;
}

.clear{
  clear:both;
}

.blog-card-sitename{

}

.blog-card-sitename a{
	text-decoration: none;
	color:#333;
	font-size:75%;

	margin-right:10px;
}
.blog-card-sitename a:hover{
	text-decoration: underline;
	color:#333;
	font-size:75%;

	margin-right:10px;
}

.blog-card-favicon{
	float:left;
	margin-right:5px;
}

スペシャルサンクス

今回のコードはほぼセルティスラボさんが公開してくれていたプラグインのコードをちょこっと改造したものとなっています。
負荷軽減のためのキャッシュ化など僕のスキルではできないことも多かったので、めちゃくちゃ助かりました。

WordPressで「はてなブログカード」のような埋め込み機能作成 – セルティスラボ
WordPress 4.0 以上で使用できる「はてなブログカード」のようなOGPブログカードの埋め込み機能を作成したので紹介します

コメント

  1. 古田 より:

    突然のご連絡失礼致します。
    外部リンクのデザインが気に入り、ショートコードを参考にさせて頂きました。

    無事、使用することは出来ているのですが、例えばリンクするURLが
    「http://app.tokyo/2015/05/18/895/」
    ですと、Stinger3のレイアウトが崩れ、ウィジェット部分が記事の下に表示されてしまいます。
    別のURLでは無事レイアウトも保ったままリンク出来ているのですが、何か原因はわかりますでしょうか?また対策があればご教授頂けると幸いです。
    以上、よろしくお願い致します。

  2. よしたけ よしたけ より:

    古田さん、こんにちは。

    外部リンクショートコードお使いいただきありがとうございます^^
    不具合があったようですいません・・・。

    ざっとコードを見てみた感じ、リンク先URLのOGP設定に画像設定があるか・ないか、またOGP設定自体があるか・ないかなどの分岐のところで、

    タグの閉じ忘れがあるようで、デザインがずれちゃうみたいです。

    ちょっと時間がかかるかもですが、修正次第、またこの記事でお知らせさせていただきます!
    少しお待ちいただけますと幸いです。

    よろしくお願いいたしますm(_ _)m

    • あ、もしかして私のページにタグの閉じ忘れがあったりするんでしょーか。
      ご迷惑おかけします。。

      • よしたけ よしたけ より:

        アップトーキョーさん

        すいません!!
        アップトーキョー さんの方に不具合があるってわけじゃないですm(_ _)m
        僕のコードに閉じ忘れが発生するようです。

        巻き込んでしまってすいません。。。

        • ありがとうございます。
          うちもStringerのテンプレートをいろいろいじくってるので閉じ忘れとか互い違いとかいっぱいあるとおもうのですが放置しておりますw

    • 古田 より:

      早速ありがとうございます。
      上手く表示することができました。

      また、いつも参考になる記事ありがとうございます。
      今後もブログの運営頑張って下さい!

      • よしたけ よしたけ より:

        古田さん

        早速ありがとうございます。
        うまく表示できたようでよかったです。

        今後ともよろしくお願いいたします。

  3. ushigyu より:

    よしたけさん、はじめまして!ushigyuと申します。

    私もブログカード風のリンクを貼りたいと思い、はてなブログ経由はどうもイマイチ→Celtispackプラグイン導入・有効化してもうまくいかず、この記事にたどりつきました。

    記事の通りに設定してみたのですが、以下のような警告とエラーが出てしまいどうもうまく表示できません。

    Warning: preg_match() expects parameter 2 to be string, array given in /home/ushigyu2014/ushigyu.net/public_html/wp-content/themes/blue-grace/functions.php on line 684

    Fatal error: Call to undefined method Celtispack_thumbnail::getmake_thumbnail_size() in /home/ushigyu2014/ushigyu.net/public_html/wp-content/themes/blue-grace/functions.php on line 688

    「パラメーター足りないよ!」「そんな関数ないよ!」と言われているのはわかるのですが、知識が足りずそれに対してどういう対処をすればよいかわかりません。。。
    (Celtisプラグインの「oEmbed extend」はチェックを入れて有効化しています)

    もし解決策がわかるようであれば、お手すきにご教授いただけると大変ありがたいですm(__)m

    • よしたけ よしたけ より:

      ushigyuさん、はじめまして!
      お返事遅くなってすいませんです!

      ちょっといま旅行中でバタバタしてまして、また帰ってから見てみますね!
      お時間いただいてすいません!

      取り急ぎお返事まで。

    • よしたけ よしたけ より:

      ushigyuさん

      遅くなってすいません!
      よしたけです。

      僕もプログラミングは素人なものであんまりよく分からないのですが、一つ目のエラーは「preg_match()関数の第2引数は文字列にしてね~。」ってことみたいです。
      preg_match()関数は第1引数と第2引数には文字列しか入れたらダメで、配列を入れちゃうとこんなエラーが出るようです。

      で、エラーの出てる箇所は恐らくこの記事のコード行数(//OGPデータからブログカード用HTML生成改)で言うと、
      67行目のif(!empty($ogp[‘og:url’]) && !preg_match(“#$myurl#”, $ogp[‘og:url’])){だと思われます。

      ここの!preg_match(“#$myurl#”, $ogp[‘og:url’])の第2引数$ogp[‘og:url’]が文字列じゃないよ!ってことかと。

      ■以上を踏まえて、1個目のエラーの原因です。

      恐らく、ushigyuさんがリンクしようと指定したURLのヘッダーに【<meta property=”og:url content=”パーマリンク”>】の設定が複数入っていると思われます。
      試しに僕の運営サイトにog:urlの設定を2個入れてテストしてみたら同じエラーが出ました。
      ※万が一、特定のURLだけじゃなくて、どんなURLを指定しても同じエラーがでるんだよ!という場合はまたお知らせください。

      OGP設定を重複して入れてしまっているサイトへの対処はこのコードでは出来ていませんでした。
      すいませんm(_ _;)m

      このエラー回避のコード修正はちょっと大変そうなので、以下のとりあえずの解決策をお試しいただければと思います。

      ■とりあえずの解決策

      該当箇所は、指定したURLが自サイトか外部サイトか判定して、外部サイトなら画像をサムネイル化してキャッシュする処理をしているのですが、このコードは外部サイト専用なので、ぶっちゃけこの条件分岐はいらないかと。
      なので、if(!empty($ogp[‘og:url’]) && !preg_match(“#$myurl#”, $ogp[‘og:url’])){
      自体を削除してしまってOKかと思います。
      ※75行目のIF文の閉じ括弧も忘れずに削除。

      せっかくコードを使っていただいたのにエラーでお手間をおかけして申し訳ありません。
      もし、まだお使いいただけるなら以上を参考にしてください。

      2個目のエラーの「そんな関数ないよ」については1個目のエラーが解決してから検証できればと思いますので、よろしければ経過をお教えいただけますと幸いです。

      • ushigyu より:

        Twitterでは返信しましたが、今後このページにたどりついた方のためにこちらでも。

        OGP情報がダブっているという指摘をいただき調べてみたところ、自分で設定したもののほかにJetpackが自動でもう1つOGP(og:url含む)を生成していたようです。後者の不要な方を削除することで、エラーがなくなり表示することができました!
        あとはCSSで整えるとうまくいきそうです。突然の質問にも関わらず丁寧に教えていただき、本当に助かりました。ありがとうございました!