モバイルPCをASUS TransBook 3 T303UAからHP Spectre 13へ買い替え

先日までノートPCはASUS TransBook 3 T303UAを使用していました。

正確にはノートPCではなく2-in-1モデルでキーボードを外すことができ、タブレットとしても利用することができます。
便利かなと思って2-in-1スタイルを選択してみましたが、私のモバイルPCの使い方だと全くタブレット運用がありませんでした。
逆に膝の上に置いて作業ができないなど、普通のノートPCの方が使いやすいと感じることも多々。

あと、3kのモニターも私の使い方だと正直なところ不必要でした。
12.6インチのモニターに3kで表示できても文字が小さすぎて読めません…
結果Windowsの拡大機能を使って拡大するわけで、多少は文字のジャギーが目立たないとかはあるかもしれませんが、プログラムによっては正しく拡大表示されなかったりとデメリットもあるので、小型のモニターではFullHDで十分だと感じます。
(高画質の動画を再生するような使い方だと3kを生かせるのかもしれません)

ダラダラと書きましたが、要は「私の使い方にTransBook3はマッチしていない」ということです。

更にモバイルCPUも時代は第8世代に突入し、今まで2CORE2スレッドだったのが4CORE8スレッドになり、大幅に処理能力が上がりました。
TransBook3は第6世代のCore i5で当時としては非力ではありませんでしたが、プログラムのコンパイルなども行う私にとっては多少イライラするスペックでした。
(ノートPCだから…という諦めでなんとか我慢してました)
第7世代までは多少の世代差は気になりませんでしたが、第7世代と第8世代では超えられない壁があります。

ということで、前から気になってたHPのノートPCに買い替えることにしました。
最初はSpectre x360が第一候補でした。
見た目の美しさ、そして360度キーボードを開くことでタブレットのように使うこともできる!

ん?待てよ
タブレット的な使い方は必要なかったんじゃ?
スタイラスペンなんてSurfaceペンまで買い増ししたのにTransBook3で使ったことあったか?
などと自問自答した結果、同じSpectreシリーズでスタイラスペン非対応になって360度回転をなくすかわりに、より軽く・より薄くしたSpectre 13が候補に上がり、最終的にSpectre 13を買うことにしました。
Spectre 13も非常に美しい見た目をしています。

HP Spectre 13

セラミックホワイトのパフォーマンスモデル
インテル® Core™ i7-8550U
16GB メモリ
NVMe M.2接続の512GB SSD
顔認証対応(Transbook3も顔認証対応で非常に便利でした)

この薄さで4CORE8スレッドです。

実際に使用してもTransbook3の時のようなもっさり感がほとんどありません。
プログラムのコンパイル中も他の作業ができる快適さです。
もちろんコンパイルも断然早いです。
ここまで来ると少し前のデスクトップの性能ですね…

はっきり言って買い替えて正解でした。
ノートPCにある程度のスペックを求める人は、絶対に第8世代以降のものを購入してください。
そこには完全に超えられない壁が存在します。

Spectre 13に一つだけ難点があるとすれば、外部接続用の端子がUSB-TypeCのみということでしょうか。
たたUSB-TypeCを3つ搭載していますので、変換アダプターを使えば特に難点とは言えないかもしれません。
これからはUSB-TypeCが主流になっていくでしょうし、過去の遺産を気にしなければ、逆に割り切っててスッキリしてます。

HP Spectre 13お勧めです。

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」プラグインを使用してカテゴリーを並び替えている場合は、その並び替えた順番でカテゴリーが生成されます。

ブログのURLを変更した場合のリダイレクト処理

ブログのアプリをblognplusからWordPressに変更した際にURLもhttps://hiro7216.mydns.jp/blognplusからhttps://hiro7216.mydns.jp/blogへと変更しました。
当然ながらGoogleやYahooなどの検索エンジンでは以前のURLが表示されますし、ブックマークなどでURL指定でお越しになられる方も以前のURLでのアクセスになります。
URLの変更はこちらの都合なので、以前のURLでアクセスしても可能な限り目的のページを表示できるようにしました。

今回はblognplus/index.php?e=xxxxをblog/?p=xxxxにするケースと
blognplus/xxxxをblog/xxxxにするケースの2種類だけの対応となります。

使用するのはApacheのRewriteEngineです。
サーバーが対応していない場合は使えませんので、その点だけは注意が必要です。
またApacheではなくnginxでもこの方法は使用できません。
nginxの場合は書き方を少し変えてnginx.confに記載する必要があります。

最初に結論から書きます。
設置してるwebのトップに.htaccessを置いて以下の内容を記述します。
(blognplusの部分は以前のURL、blogの部分は新しいURLとなります)

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{QUERY_STRING} e=(.+)
    RewriteRule ^blognplus/(.*)$ /blog/?p=%1 [R=301,L]
    RewriteRule ^blognplus/(.*)$ /blog/$1 [R=301,L]
</IfModule>

RewriteEngineを細かく説明すると色々と難しいので簡単な説明にします。

まず1行目の<IfModule mod_rewrite.c>ですが、これはRewriteEngineモジュールが使用できる場合という意味です。
RewriteEngineモジュールが使用不可の場合は今回の設定は全て無視されます。
2行目はRewriteEngineを使用する、です。

3行目と4行目は関連しています。
3行目はクエリ文字列(URLの?の後ろに付く文字列です)がe=xxxxになってた場合に変数に保存します。
(xxxxの部分は任意の文字列です)
4行目はURLがblognplus/~~~~だった場合に/blog/?p=%1にリダイレクトします。
%1の部分は3行目で保存していたxxxxの部分に置き換えられます。

5行目はblognplus/xxxxにアクセスがあった場合に/blog/xxxxにリダイレクトします。
($1がxxxxに置き換えられるだけです)

[R=301,L]の部分のR=301はリダイレクトなので、消して[L]だけにするとリダイレクトせずに昔のURLのまま、新しいURLの内容が表示されます。
Lの部分は条件に一致したらその次のルールは使わずに終了という意味です。

RewriteEngineを上手に使うとドメインを転送することもできますし、もっと細かくURLを変換することも可能です。
Webを扱う人は覚えておくと色々便利に使えます。

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>

主にPC、車・バイク、トイガンなどについて書いてます