「WordPress」カテゴリーアーカイブ

WordPressでJavaScriptを使う

WordPressでJavaScriptを書こうとすると、それ用のプラグインを入れたりするのが一般的かと思います。
が、はっきり言ってプラグイン使ってやるのは超面倒。

JavaScriptだけでなく、JavaScriptで使うinputタグやボタン配置など。
WordPressの編集画面でちまちま入力したり、もう面倒でやってられません。
JavaScriptを含んだHTMLは自前で書くから、それをそのまま読み込んで表示できないの?と思って調べると、同じこと思っている方を発見!

WordPressで固定ページでHTMLをちまちま入力するのが面倒なのでHTMLファイルをインポートするだけのショートコードを作った

なるほど、ファイルを直接PHP側でincludeしちゃうわけですね。
(includeなのでPHPにも使える!)
で、ショートコードを利用してそのパスを渡すと。

これを使えば簡単に自前のHTMLを取り込めますね。

ちなみに公開されているソースではファイルの親ディレクトリ指定が

$path = sprintf('%s/static_html/%s.html',
                get_template_directory(), $path);

とテーマ配下のstatic_htmlディレクトリになっているため、テーマをアップデートしたらディレクトリごと消えました…
(このショートコードを書くfunction.phpもテーマのものに直接書くとテーマのアップデートで消えます)

元々function.phpやcssは子テーマを作って更新しても消えないようにしていたので、static_htmlも子テーマのディレクトリ配下に移しました。
(もちろんソースのパスも子テーマ配下へ書き換える必要があります)
これでテーマをアップデートしても消えません。

子テーマについて書くと長くなるので、子テーマについては以下のページをご紹介します。
WordPressの子テーマを作る理由と子テーマを自作する方法

PHP7.0からPHP7.2に変更したらSyntax Highlighter ComPressでエラー発生

PHPの最新化のためにPHP7.0からPHP7.2へ変更しました。
7.2にするとプラグインでエラーが出るという話がありましたが、利用しているプラグインであるSyntax Highlighter ComPressで以下のエラーが発生しました。

Deprecated: Function create_function() is deprecated in /wp-content/plugins/syntax-highlighter-compress/syntax-highlighter-compress.php on line 418

調べてみるとPHP7.2ではcreate_function()という関数が使えなくなっているようです。
早速エラーが出ている個所を修正します。

変更前

/**
 * Actions
 */
add_action('plugins_loaded', create_function( '', 'global $wp_shc; $wp_shc = new wp_shc();' ) );

変更後

/**
 * Actions
 */
add_action('plugins_loaded', function() {global $wp_shc; $wp_shc = new wp_shc();} );

これでエラーはでなくなりました。

カテゴリー別全投稿タイトル一覧の固定ページを追加

全記事のタイトルを見ることができるサイトマップみたいなものが欲しかったのですが、単にタイトルを全部並べただけでは非常に見難い。
希望を満たせるものがないか少し探してみましたが、作った方が早いんじゃないかと思い作りました。
今回はタグではなくカテゴリーを使った投稿タイトル一覧にしました。

動きとしては、まず親カテゴリーを取得し、親カテゴリーに属している投稿のタイトル一覧を作成します。
但し親カテゴリーの子カテゴリーに属していた場合は一覧に含みません。
更に親カテゴリの下には属する子カテゴリを表示し、その子カテゴリに属する投稿のタイトル一覧を作成します。
(今回は対象の子カテゴリーは親カテゴリーの1階層下までとしました)
文章で書くと分かりにくいですが、私の固定ページを見て頂ければ直ぐに分かるかと思います。
コンテンツ一覧

まずwp-content/themes/all_contents.phpというファイルを作成して以下の内容を記述して保存します。

	.all_contents_sub_category {
		padding-left: 1em;
	}

<?php
// 親カテゴリーを取得
$top_categories = get_categories(array('parent' => 0, 'orderby' => 'term_order'));
// 親カテゴリー分ループ
foreach($top_categories as $top_category) :
	// 親カテゴリーのリンク作成 ?>
	<?php endforeach; ?>
<?php endforeach; ?>

これだけでは固定ページから呼び出せませんので、テーマのfunction.phpに以下の内容を追記します。

/*
* コンテンツ一覧のphpファイルを読み込むショートコード
*/
function include_all_contents_php( $atts ){
	ob_start();
	get_template_part('../all_contents'); // ../all_contents.phpを読みこみ
	return ob_get_clean();
}
add_shortcode( 'include_all_contents', 'include_all_contents_php' );

これはショートコードと呼ばれる方法で、PHPを投稿や固定ページから呼び出せるようにするものです。
投稿や固定ページには基本的にPHPを記述することはできませんが、このショートコードを利用することで簡単に呼び出せるようになります。

あとは固定ページで[include_all_contents]と書けば呼び出せます。
※そのまま書いてしまうと呼び出されてしまうため、上では[]を全角文字で書いてますので半角に置き換えてください。

尚、「Category Order and Taxonomy Terms Order」プラグインを使用してカテゴリーを並び替えている場合は、その並び替えた順番でカテゴリーが生成されます。

Syntax Highlighter ComPressでエラー

blog上でのコード表示用にSyntaxHighlighterを利用していました。
WPに乗り換えるにあたって直接header.phpにJavaScriptの呼び出しを記述するのではなく、プラグインを利用することにしました。
Syntax Highlighter ComPress バージョン 3.0.83.3を利用しましたが、問題点が2点出ました。
まず1点目は縦スクロールが必要ない場面でも縦スクロールが出ることです。
これはwp-content/plugins/syntax-highlighter-compress/styles/shCoreDefault.cssを変更することで解消されました。

変更前

.syntaxhighlighter {
  width: 100% !important;
  margin: 1em 0 1em 0 !important;
  position: relative !important;
  overflow: auto !important;
  font-size: 1em !important;
}

変更後

.syntaxhighlighter {
  width: 100% !important;
  margin: 1em 0 1em 0 !important;
  position: relative !important;
  font-size: 1em !important;
  overflow-x: auto !important;
  overflow-y: hidden !important;
  padding: 1px !important;
}

次に管理画面に以下の警告が出るようになりました。

Notice: has_cap がバージョン 2.0.0 から非推奨になった引数付きで呼び出されました。ユーザーレベルの使用は推奨されていません。代わりに権限を使ってください。

検索したところ以下のページを見つけました。
「Notice: has_cap の使用は…」はプラグインを確認する
※既にリンク先のサイトはなくなっているようです。

要は数字ではなく文字列で権限を指定しろということらしいです。
で、Syntax Highlighter ComPressで該当する箇所はwp-content/plugins/syntax-highlighter-compress/syntax-highlighter-compress.php内のadd_submenu_page関数でした。
add_submenu_pageの75行目を以下のように修正したら無事警告も出なくなりました。

変更前

add_submenu_page('options-general.php', __('Syntax Highlighter ComPress Options', 'SHC'), $menutitle, 8, basename(__FILE__), 'shc_options_subpanel');

変更後

add_submenu_page('options-general.php', __('Syntax Highlighter ComPress Options', 'SHC'), $menutitle, 'administrator', basename(__FILE__), 'shc_options_subpanel');

WordPressにカウンターを設置(同じIPはカウントしない)

blognplusからWordPressへ移行した際に良いカウンターがなかったので自作しました。
自作と言っても元はblogplusのモジュール用に作られた「カルカン(お手軽カウンター)」をWordPress用に改造したものです。
作者様に改造品の掲載許可を頂きたかったのですが、既にHPも閉鎖されているようで連絡が取れず…
もし作者様がこのブログを見られましたら許可・非許可のコメントを頂ければ幸いです。

「カルカン(お手軽カウンター)」で出来ることは以下の3つです。
1.トータルのカウント数を表示
2.当日のカウント数を表示
3.昨日のカウント数を表示
全てのカウント数で同じ日の同じIPからのアクセスは、何度アクセスしても1回としてカウントされます。
いわゆる「延べ数」なPVとは違い、実際の訪問者数が分かります。
(BOTかどうかまでは分かりませんが)
尚、7行目のIPアドレス保存件数しかIPを保存しないので、人気のあるサイトは数を大目にしないと直ぐに同じIPでもカウントアップしてしまいます。

使い方は簡単で以下のソースコードをテーマのfunction.phpに追記するだけで、ウィジェットとして使用することが可能となります。

/*
* カウンターウィジェット
*/
// 保存ファイル名
define('WIDGET_COUNTER_FILE', WP_CONTENT_DIR."/widget_counter_file");
// IPアドレス保存件数
define('WIDGET_COUNTER_REMOTE', 30);
class Counter_Widget extends WP_Widget {
	/* コンストラクタ */
	function __construct() {
		parent::__construct(
			false,
			$name = 'カウンター',
			array( 'description' => 'IP重複なしのカウンターです', )
		);
	}
	
	/* 管理画面のウィジェット設定用コード */
	function form($instance) {
	?>

	<?php
	}

	/* 管理画面のウィジェット設定を変更した時の処理 */
	function update($new_instance, $old_instance) {
		$instance = $old_instance;
		$instance['title'] = strip_tags($new_instance['title']);
		return $instance;
	}

	/* ウィジェットを配置した時の表示用コード */
	function widget($args, $instance) {
		extract( $args );
		
		// カウント取得
		$counter = $this->widgetCounterGetCount('default');
		$out_count = '';
		$out_count .= "合計: ".$counter['total']."\n";
		$out_count .= "今日: ".$counter['today']."\n";
		$out_count .= "昨日: ".$counter['yesterday']."\n";

		if($instance['title'] != ''){
			$title = apply_filters('widget_title', $instance['title']);
		}
		echo $before_widget;
		if( $title ){
			echo $before_title . $title . $after_title;
		}
		echo $out_count;
		echo $after_widget;
	}
	
	/* 日付を取得-----------------------------------------------------------------*/
	function widgetCounterGetDate($format, $timestamp = NULL) {
		$format = preg_replace('/(?<!\\\)T/', preg_replace('/(.)/', '\\\$1', 'JST'), $format);

		$time = 9 * 3600 + (($timestamp !== NULL) ? $timestamp : time() - date('Z'));

		return date($format, $time);
	}

	/* カウンターの値の取得及びカウントアップ-------------------------------------*/
	function widgetCounterGetCount($page) {
		$ipMax				= (WIDGET_COUNTER_REMOTE<1) ? 1 : WIDGET_COUNTER_REMOTE;
		
		$default = array(
			'total'		=> 0,
			'date'		=> $this->widgetCounterGetDate('Y/m/d'),
			'today'		=> 0,
			'yesterday'	=> 0
		);
		
		$counters			= array();
		$couterns[$page]	= $default;
		
		for ($i=0; $i<$ipMax; $i++) {
			$default["ip$i"] = '';
		}
		
		$file = WIDGET_COUNTER_FILE.'.'.$page.'.dat';
		
		$modify = FALSE;	//更新フラグ
		
		if (! $fp = @fopen($file, file_exists($file) ? 'r+' : 'w+')) return $default;
		set_file_buffer($fp, 0);
		flock($fp, LOCK_EX);
		rewind($fp);
		foreach ($default as $key=>$val) {
			//データ取得
			$counters[$page][$key] = rtrim(fgets($fp, 256));
			if (feof($fp)) break;
		}
		if ($counters[$page]['date'] != $default['date']) {
			// 新しい日付
			$modify = TRUE;
			$yesterday = ($counters[$page]['date'] == $this->widgetCounterGetDate('Y/m/d', (time() - date('Z') - 3600 * 24)));
			for ($i=$ipMax-1; $i>0; $i--) {
				$counters[$page]["ip$i"] = '';
			}
			$counters[$page]['ip0']       = $_SERVER['REMOTE_ADDR'];
			$counters[$page]['date']      = $default['date'];
			$counters[$page]['yesterday'] = $yesterday ? $counters[$page]['today'] : 0;
			$counters[$page]['today']     = 1;
			$counters[$page]['total']++;
			
		} else {
			$newer = TRUE;
			for ($i=0; $i<$ipMax; $i++) {
				if ($counters[$page]["ip$i"] == $_SERVER['REMOTE_ADDR']) {
					$newer = FALSE;
					break;
				}
			}
			if ($newer) {
				// カウントアップ
				$modify = TRUE;
				for ($i=$ipMax-1; $i>0; $i--) {
					$j = $i-1;
					$counters[$page]["ip$i"] = $counters[$page]["ip$j"];
				}
				$counters[$page]['ip0'] = $_SERVER['REMOTE_ADDR'];
				$counters[$page]['today']++;
				$counters[$page]['total']++;
			}
		}
		
		// 更新されていた場合
		if ($modify) {
			rewind($fp);
			ftruncate($fp, 0);
			foreach (array_keys($default) as $key)
				fputs($fp, $counters[$page][$key] . "\n");
		}
		
		flock($fp, LOCK_UN);
		fclose($fp);

		return $counters[$page];
	}
}
/* カウンターウィジェットを使えるように登録 */
register_widget('Counter_Widget');

上記コードをfunction.phpに登録すると、テーマのカスタマイズのウィジェットで選択して使用可能となります。

カウンタの数はデータベースではなくファイルに保存されます。
ファイルの保存場所は「wp-content」の直下でファイル名は「widget_counter_file.default.dat」です。
テーマを変更しても変更したテーマのfunction.phpに上記コードを書けば、カウンター数の内容を引き継ぐことが出来ます。

設置後初回だけはファイルが存在せずにエラーが出るかもしれませんが、自動でファイルが作成されますので2回目以降はエラーにならないはずです。
wp-contentの下にファイルが出来ていない場合は、ディレクトリに正しく権限が付与されていない可能性があります。
(プラグインのインストールが失敗するケースなどと同じ理由です)
基本は正しく権限を与えてもらうべきですが、手動でwidget_counter_file.default.datを作成して全権限を与えるというお勧めできない方法もあるにはあります。

また、見られても特に困るファイルではないと思いますが、念のために「wp-content」の直下に.htaccessを置いて以下の記述をしておくとwidget_counter_file.default.datへのアクセスが不可となります。
(アクセスしようとしても403エラーが返るようになります)

<Files widget_counter_file.default.dat>
    Deny from all
</Files>

ブログをBlognplusからWordPressへ変更しました

既に配布もメンテも終了しているBlognplusを長い間使わせて頂きましたが、流石に限界かと思いWordPressへと乗り換えました。

データの移行も結構大変でした。
記事内に自身のブログのリンクが張られていたりするので、その整合性を取るのにインポート前のファイルを編集したりしました。
WordPressへのインポート自体は、Blognplusのエクスポート機能でMovableType形式で吐き出せば簡単なのですが、Blognplus側で削除した記事の分だけ、WordPress側では詰めて投稿が作成されるのでズレていくのです…
エクスポートファイルを修正したり、DBを直接いじって値を変更したり、なんとかほとんどの記事を同じIDで作成できました。

他にも画像のリンクなども修正が必要でした。
(これは置換で一発でしたが)

URLもblognplusからblogに変更し、URLパラメーターもblognplus形式のindex.php?e=123からWordPress形式の?p=123へ変更になりました。
そこでApacheのRewriteEngineを使い、以前のblognplusのURL形式で開いても、新しいWordPressのURLで同じ記事が開くようにリダイレクトしています。
尚、カテゴリーに関しては、サブカテゴリーを見直して一部変更したため、以前のURLとの整合性がそもそも取れないので、RewriteEngineでの処理は行っていません。

あとは同一IPではカウントアップしないカウンターのウィジェットを自作したりしました。
(コアなロジックはblognplusのカルカンカウンターを流用させて頂きました)

そして固定ページには、カテゴリー毎に記事の見出しを自動で生成する機能も作成しました。

色々やってやっと形になったので、この度BlognplusからWordPressへ切り替えました。
色々やったおかげでWordPressの作りの勉強にもなりました。
近年仕事でやってるWeb系はAngularなどのJS系フロントエンドやJSFなどが殆どだったので、PHPを久々にちゃんと触りました。