simplepie.phpで複数サイトのRSS一覧をアイコンを付けて表示させる覚え書き

イベントのサイトや幾つかのブランドがあるサイトで一つの場所に全部のRSS情報を最新5件、一覧で表示させるというミッションがあり、四苦八苦。
いくつかのrssプラグインを使ってみたものの、個別にアイコンを付ける機能がついているようなプラグインなど無く、wpにもとからあるclass-simplepie.phpを使って表示させることに。

最終的なコードはこちら。

FEED A URL,FEED B URL、、と複数のフィードするURLを指定する。
ここでハマったのが、キャッシュするフォルダを指定していなかったので、エラーが表示されてしまった。
ディレクトリのトップにcacheフォルダを作り、パーミッションを700に指定すればOK。

一覧では、複数のサイトの最新5件を一覧させたかったので、そのように。

<?php include_once(ABSPATH . WPINC . '/class-simplepie.php');
	$feed = new SimplePie();
	$feed->set_feed_url(array(
	'FEED A URL', // サイトAのフィードURL
	'FEED B URL', // サイトBのフィードURL
	'FEED C URL', // サイトCのフィードURL
	));
	 $feed->set_cache_location('./cache');
	 $feed->set_cache_duration(600);
	 $feed->set_item_limit(5);
	 $feed->init();
	 $items = $feed->get_items(0, 5); // 最新5件表示
	 foreach($items as $item)
: ?>

で、後はそのデータを表示させるだけなのだけど、ここでもトラップがいくつか。

1)それぞれのサイト専用のアイコンを表示させるため、preg_matchでアイコンを指定

if(preg_match("/FEED-A/",$item->get_permalink()

とすると、パーマリンク(URL)の中の任意の文字列「FEED-A」が入っている場合は「ic_a.png」をタイトルの横に表示させることになる。
ただ、同じドメインにいくつかのサイトやサービスがある場合、ドメインの文字列を使うと全部同じアイコンになってしまったり、ページタイトルにその文字列が入ってるとややこしくなってしまうため、

if(preg_match("/FEED-B/",$item->get_feed()->get_title()

として、サイトのタイトルを指定して、そこにある文字列で分けることで同じドメインでもOKに!(下のコードでは一応両方設定。)

2)get_descriptionでコンテンツの中身を一部表示させた際、最後の文字が文字化けしてしまった。

通常は echo mb_substr で中身を表示させるのが一般的みたいだけど、日本語は2バイト言語なので、echo mb_strimwidth
の関数を使い、その前で言語とエンコードも指定。

本来は

$len = 10;
echo mb_strimwidth(strip_tags($item->get_description()), 0, $len, "...", "UTF-8"); ?>

とかのほうがいいのかも?

ま、動いたので今回はこれで、、

<dl>	
	<dt><?php echo $item->get_date("Y.n.j"); ?></dt>
	<dd><a href='<?php echo $item->get_permalink(); ?>' title=''>
	<?php echo $item->get_title(); ?></a>&nbsp;&nbsp;&nbsp;
	<?php if(preg_match("/FEED-A/",$item->get_permalink())){echo '<img src="img/ic_a.png" alt="">';}
	else if(preg_match("/FEED-B/",$item->get_feed()->get_title())){echo '<img src="img/ic_b.png" alt="">';}
	else if(preg_match("/FEED-C/",$item->get_permalink())){echo '<img src="img/ic_c" alt="">';} ?><br>
	<p class="siteinfo">by <?php echo $item->get_feed()->get_title(); ?></p>
	<span class="desc">
	<?php mb_language('Japanese');
	mb_internal_encoding('UTF-8'); 
	echo mb_strimwidth(strip_tags($item->get_description()), 0, 360, "..."); ?>
	<a href='<?php echo $item->get_permalink(); ?>' target="_blank">続きを読む</a>
	</span>
	</dd>	
</dl>

基本のコードはこちらのサイトを参考にさせていただきました。ありがとうございます。

» Website Creating RSSフィードで複数サイトの新着一覧アイコン付

Google Feed API が廃止になったので件数を指定したリスト表示を代替え案での覚え書き

今までも何度か表示されないことがあったけど、微妙に動いていたGoogle Feed APIがとうとうエラーで表示されなくなり、、
幾つかのクライアントのFeed表示をどうしようかと調べていた中で使えそうなライブラリがあったのでそっちで対応。

PHPが動けばこれでいけそうです。

» ダウンロードするライブラリはこれ。feed.php

で、一つphpを用意(get-feed.phpという名前とかにして。)し、中身は下記をペースト。
取得するfeedのURL、件数を指定。
feed.phpの場所は同階層じゃない場合は階層も指定。

<?php
 
	// ライブラリの読み込み
	require_once "feed.php" ;
 
	// 取得するフィードのURLを指定(アメブロだとこんな感じ)
	$url = "http://feedblog.ameba.jp/rss/ameblo/アメブロID/rss20.xml" ;
 
	// インスタンスの作成
	$feed = new Feed ;
 
	// RSSを読み込む
	$rss = $feed->loadRss( $url ) ;
 
	// HTML表示用
	$html = '' ;
 
	$MAX_feed = 10;// 表示させる件数
	$feed_count = 0; $feed = new Feed ; $rss = $feed->loadRss( $url ) ;
 
 
	foreach( $rss->item as $item ){
		if ($feed_count >= $MAX_feed) { break; }
		// 各エントリーの処理
		$feed_count++;
 
		$title = $item->title ;	// タイトル
		$link = $item->link ;	// リンク
		$description = $item->description ;	// 詳細
 
 
		// 日付の取得(UNIX TIMESTAMP)
		foreach( array( "pubDate" , "date_timestamp" , "dc:date" , "published" , "issued" ) as $time )
		{
			if( isset( $item->{ $time } ) && !empty( $item->{ $time } ) )
			{
				$timestamp = ( is_int( $item->{ $time } ) ) ? $item->{ $time } : strtotime( $item->{ $time } ) ;
				break ;
			}
		}
 
 
		// 仮に日付が取得できなかったら現在時刻を表示
		if( !isset( $timestamp ) )
		{
			$timestamp = time() ;
		}
 
		// 表示
		$html .= '<dt>'.date( "Y年m月d日" , $timestamp ) .'</dt><dd><a href="' . $link . '">' . $title . '</a></dd>' ;
	}
?>
 
 
<?php echo $html ?>

後は読み込みたいページのhtmlの記述。

まず、ヘッダでjqueryを読み込む。既に別のライブラリで使ってる場合は不要かも。
ただ、バージョンによってコンフリクトするので、読み込み順、バージョンは注意。

ライブラリの読みこみ。

<!-- rss -->
<script type="text/javascript">
;(function($){
$(function(){
  $.get('get-feed.php',function(data){
    $('#feed').html(data);
  })
})
})(jQuery);
</script>

あとは、bodyの中で

<div id="feed"></div>

で読み込ませればOK。
表示スタイルはget-feed.phpの表示部分で変更すればスタイル変更ができます(^^)

表示件数を指定する部分を変更してますが、ここのブログを参考にさせていただきました。

» PHPでRSSやAtomのフィードを取得する方法
» Google Feed API」の代替として「rss-php」でRSSやAtomフィードを取得・表示する

プラグインを使わないでフィルター、ソート機能をつける覚え書き。[MixltUp]

投稿内容の一覧をタイル状に表示して、フィルターやソートをさせたい時はプラグインを使うことも多いけど、jQueryをその分重複して読み込むことになってしまったり、そのせいでスライドショーとか他のライブラリが動かなくなることが多いので、シンプルに機能をつけたかったので、試してみました。
使うライブラリは
MixltUp
というもの。
サイトにソートとフィルターのデモが出ています。

で、これを実際にwordpressのコンテンツのソートに使う場合、

まずはヘッダに必要なものを読み込ませます。
header.php

<?php wp_head(); ?>

の後に記述したら、案の定コンフリクトを起こしたので、前に記述。

<!-- jQuery読み込み -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
 
<!-- ソートスクリプト読み込み -->
<script src="http://cdn.jsdelivr.net/jquery.mixitup/latest/jquery.mixitup.min.js"></script>
 
<!-- Javascript -->
<script type="text/javascript">
$(function(){
	// Instantiate MixItUp:
	$('#Container').mixItUp();
});
</script>

cssにはこれを記述。

#Container .mix{
	display: none;
}

後は必要な部分をマークアップするだけ。

フィルタするボタンの部分にそのカテゴリのクラス名を入れる。
このブログだと、

がループされるのでその中にあるクラスのカテゴリ名を指定。

↓フィルタ用のボタン
<div class="filter" data-filter="all">すべて表示</div>
<div class="filter" data-filter=".category-wordpress">カテゴリー(wordpress)</div>
<div class="filter" data-filter=".category-news">カテゴリー(news)</div>
 
↓コンテンツの中身
<div id="Container">
	<!--ここからがループ-->
	<article class="mix category-wordpres">カテゴリー(wordpress)</article>
	<article class="mix category-news">カテゴリー(news)</article>
	<article class="mix category-wordpres">カテゴリー(wordpress)</article>
	<article class="mix category-news">カテゴリー(news)</article>
	<!--//ここまでがループ-->
</div>

1つややこしかったのが、articleのclassに「mix」を足さなくちゃいけないけど、この部分のclassはpost_classで吐き出しているので、直接記述ができない。
そういう場合はその中に追加したいクラス名を入れればいいだけ。

↓これを
<article id="Container post-<?php the_ID(); ?>" <?php post_class(); ?>>
 
↓こう変更する
<article id="Container post-<?php the_ID(); ?>" <?php post_class('mix'); ?>>

これでバッチリフィルタ機能が付けられました。

ループの最初の記事だけ違うデザインにする覚え書き

通常、記事はループを使って一覧表示をするのだけど、最初の記事だけ、、とか、最初の3つの記事だけデザインを変更して大きく表示させたいという時もあり、、覚え書き。
この記述は最初の1つめの記事の表示方法を変える場合。

<?php if(have_posts()): while(have_posts()): the_post(); $counter++; ?>
<?php if ($counter <= 1): ?><!-- 最初の記事判別 -->
// 最初の記事の内容を記述する
<?php else:?>
// 最初の記事以降のループ処理する内容を記述する
<?php endif;?><!-- /最初の記事判別 -->
<?php endwhile; endif; ?>

既存のテーマをカスタマイズする時、子テーマを使おぼえがき

クライアントの意向とか、予算の問題で既存のテーマを使うことが多いけど、結局cssやら、テンプレートファイルをカスタマイズすることになってしまう。
テンプレートファイルをまったくカスタマイズする必要がなければ、cssファイルのみcustom.cssとかにして、ヘッダの最後に読み込むようにすればいいけど、テーマを触るのであれば、子テーマを作ったほうがテーマがバージョンアップした時にカスタマイズしたファイルが全部上書きされてしまうことはないので、今回はそっちの方法のおぼえがき。

まず、テーマディレクトリ

/wp-content/themes/

に子テーマを入れるディレクトリを作成。
親テーマがこういうものだったら、

/wp-content/themes/themename(親テーマ)/

↓「_child」とかにすると分かりやすい。

/wp-content/themes/themename_child(子テーマ)/

次に子テーマの中に

functions.php(これも追記することが多いからね。)
style.css(上書きしていくので名前は変更しないで)
screenshot.png(テーマを選ぶときに表示される画像なので、これは新しく作成!)

なぞをコピー。

functions.phpは子テーマの方から読み込まれるそうなので、必要な部分だけを記述。
style.cssは最後に読み込んで必要な部分を上書きします。

あとは、style.cssのヘッダ部分に下記を記述

/*
Template:テンプレート名(abc)
Theme Name: abc_child
Theme URI:http://www.xxx.jp/abc/
Description:child theme of abc
Author:Your name
Version:1.0
*/

@import url(“../abc/style.css”);

↑これで親テーマを先にインポート。

これで設定は終了です。
後は管理画面から外観のテーマで今回作った子テーマをしていすれば、完了です。
必要なテンプレートだけをこっちのテーマディレクトリにコピーしてカスタマイズしていけるので、編集したファイルだけが分かるのも便利ねー。

一つ子テーマを使うと、、

<?php bloginfo('template_directory'); ?>

これでテーマディレクトリを指定できない。

<?php echo home_url( '/' ); ?>/wp-content/themes/themename/

こんな感じにホームディレクトリだけ指定するしかないかな。
もしくは

<?php echo bloginfo('stylesheet_directory'); ?>

これでもいいかも?

秘密鍵を使っているサーバで管理画面からプラグインのアップデートをするおぼえがき。

久しぶりにハマったのでおぼえがき。
クライアントのサーバは秘密鍵・公開鍵をつかってFTPをつかっていたので、当然wordpressでプラグインのアップデートをしようとするとひっかかります。
でも、それぞれのプラグインを個別でダウンロードして、個別で上書きするのもめんどくさいし、、ということで、やっぱりプラグインをつかってみることにしました。
SSH SFTP Updater Support
ssh

FTPで設定している通り、ホスト、ユーザ名を入れるところまではOK。
さて、秘密鍵、秘密っていうくらいなので、簡単な場所には保存していないし、、
これだっけ?っていうものも違うと出てしまう。

なので、久しぶりにターミナルを開いて、公開鍵の中身をしらべることに。
$cd ~/.ssh
$ls
ああ、あった。
open -e xxx_rsa.pub

中身をコピーして、privetekeyに貼り付けてみる。

うごかない。

そこから30分、死闘

何気なく隣にリストされていた、clientname_key.pemをひらいてみる。

ご丁寧に上下に「——private key——」とかかれていた。

いれてみる。

うごいた。

時間を返せ。。(T_T)

Contact form 7で確認用のメールアドレスのエラーチェックを入れるためのおぼえがき。

Contact Form 7でメールアドレスをチェックさせようとしたら、そういう機能はないのね、、
いつもどおり、ちゃーんと実装されている方がいらっしゃいました。

[Contact Form 7 4.1] 確認用メールアドレスのエラーチェック(最新版対応)

しかも、最新版に対応されていました。ありがとうございます。

functions.phpに下記を追加。

/*** add confirm mail add on contact form 7 */
add_filter( 'wpcf7_validate_email', 'wpcf7_text_validation_filter_extend', 11, 2 );
add_filter( 'wpcf7_validate_email*', 'wpcf7_text_validation_filter_extend', 11, 2 );
function wpcf7_text_validation_filter_extend( $result, $tag ) {
    $type = $tag['type'];
    $name = $tag['name'];
    $_POST[$name] = trim( strtr( (string) $_POST[$name], "\n", " " ) );
    if ( 'email' == $type || 'email*' == $type ) {
        if (preg_match('/(.*)_confirm$/', $name, $matches)){
            $target_name = $matches[1];
            if ($_POST[$name] != $_POST[$target_name]) {
                if (method_exists($result, 'invalidate')) {
                    $result->invalidate( $tag,"確認用のメールアドレスが一致していません");
                } else {
                    $result['valid'] = false;
                    $result['reason'] = array( $name => '確認用のメールアドレスが一致していません' );
                }
            }
        }
    }
    return $result;
	
}

フォームのショートコード部分はこんなかんじで。

<p>メールアドレス<br />
[email* your-email] </p>

<p>メールアドレス (確認用)<br />
[email* your-email_confirm] </p>

こういうの、結構使うので助かります!

sidebar.phpでis_homeなどの条件分岐が効かない時の覚え書き。

sidebar.phpでウィジェットを使い分ける場合、今まではsidebar-index.phpとか、sidebar-category.phpとか、別のファイルを複製して、その中で呼び出すウィジェットを変更してました。
ただ、この方法だとファイルの数が増えてしまい、面倒くさい上、中身は呼び出すウィジェットの名前しか変わらない。
さらに、呼び出し元のテンプレートでも

とかに変更しなくてはならず、条件分岐をすることに。
処理としては簡単なはず・・と if (is_home())とそれ以外で分けようとしたら、何故かis_homeが効かない。
ひたすら調べること30分。簡潔に説明しているページがありました。

sidebar.phpやfooter.phpでis_homeなどの条件分岐が効かない

条件分岐のifの前にリセット処理をしなくてはいけなかったようです。

普通は

<?php if(is_home()): ?>
	//homeの時の処理。フロントページを指定している場合はis_front_page()
<?php else: ?>
	//home以外の時の処理
<?php endif; wp_reset_query(); ?>

としがちだけど、
こっちにしたらバッチリ動きました。

<?php wp_reset_query(); if(is_home()): ?>
	//homeの時の処理。フロントページを指定している場合はis_front_page()
<?php else: ?>
	//home以外の時の処理
<?php endif; ?>

今回はウィジェットを切り替えたかったので、最終的なコードはこっち。

<?php wp_reset_query(); if(is_home()): ?>
	<?php if ( is_active_sidebar( 'sidebar-1' ) ) : ?>
		<div id="secondary" class="widget-area" role="complementary">
			<?php dynamic_sidebar( 'sidebar-1' ); ?>
		</div><!-- #secondary -->
<?php endif; ?>
<?php else: ?>
	<?php if ( is_active_sidebar( 'sidebar-2' ) ) : ?>
		<div id="secondary" class="widget-area" role="complementary">
			<?php dynamic_sidebar( 'sidebar-2' ); ?>
		</div><!-- #secondary -->
<?php endif; ?>

ひとつ勉強になりました。

wordpressで投稿内のURLをショートコードで記述する覚え書き。

これ、最近よく使う手なので。備忘録として。

投稿内に画像を記述する時、最終的にURLが変更になる場合もあるので、フルパスで書くのが面倒な時が多々あります。
よくあるのが、
http://www.xxx.jp/wp/

以下にwordpressのファイル一式を置くような場合、最終的なURLは

http://www.xxx.jp/
となることがよくあります。ただ、開発中は/wp/以下で作業をしているので、普通にメディアの追加をしたりすると/wp/まで入っちゃいます。
そんな時に、ショートコードでURLを指定しておくと公開時に画像のパスを書きなおしたりしなくても済みますね。
使用しているテーマの中のfunctions.phpに以下のような記述をして、
[url]とか、[top_url]とか、[imageurl]と入れると置き換えてくれます。
最後の
add_filter(‘widget_text’, ‘do_shortcode’);
は、widgetでもショートコードが使えるようにするものです。

意外と便利です。

/*** add shorcode for page -siteURL */
function my_home_url( $atts ) {
    return home_url();
}
add_shortcode( 'url', 'my_home_url' );

function my_tpl_url() {
    return get_bloginfo('template_url');
}
add_shortcode('tpl_url', 'my_tpl_url');

function festurl() {
    return 'http://www.xxx.jp/images/';
}
add_shortcode('imageurl', 'imageurl');

add_filter('widget_text', 'do_shortcode');

iPhoneとかMac bookとかで一度表示された画像が数秒で消えてしまう現象

つくったサイトがすぐに画像が消えてしまうと言われ、初めて気づいたバグ・・。
日本語で調べてもなかなか答が見つかりませんでした。

原因はretinaディスプレイで画像がきれいに表示されるためにそもそも入っていたスクリプトのコンフリクトでした。
retina.js
コイツだったっぽい。

http://stackoverflow.com/questions/21440559/simpleimage-php-images-disappearing-on-iphone-ipad

ここに、さらっと答が書いてありました。
読み込みをしなくしたらおかしな現象はなくなりましたw

こんな現象になっている人、あまりいないと思うけど、一応覚え書きとして保存。