コマンドラインから WordPress 関連処理を実行する

FC2 ブログで行ってたつぶやきアーカイブを hetarena.com に移すために、コマンドラインで実行するための記事投稿用プログラムを書く方法を調べてみました。 wp-cron ではなく OS の crontab を使用したいので、単独の PHP プログラムファイルとして動かしたいのです。

結論からすると簡単で wp-load.php をプログラムの最初に読み込めば良いです。 参考にしたのはこちらの記事ですが、投稿を作成する程度であれば特に $_SERVER を設定しなくても動きました (→ マルチサイト化されていると $_SERVER を設定しなければ動きませんでした。追記参照)。 以下サンプルコードです。 コマンドラインから実行すると 7/7 付けの投稿が作成されます。 使用する場合はご自分の環境に合わせて修正してからお試しください。

#!/usr/bin/php
<?php

//require the WP bootstrap
require_once('/usr/share/wordpress-ja/wp-load.php');

class WP_Command_Line {

  public function __construct() {
    //nothing here
  }

  public function main() {

    $post = array (
      'post_content'   => 
        "<p>これはインポートされた記事です。</p>\n<p>よろしく!</p>",
      'post_type'      => 'post',
      'comment_status' => 'closed',
      'ping_status'    => 'closed',
      'post_status'    => 'publish',
      'post_author'    => 2,
      'post_title'     => 'テスト用記事',
      'post_date'      => '2012-07-07 00:00:00',
      'post_category'  => array(6)
    );
    $e = wp_insert_post($post, true);
    if (is_wp_error($e)) {
      print $e->get_error_message();
    }
    else {
      print "Post ID = " . $e . "\n";
    }
  }
}

$importer = new WP_Command_Line();
$importer->main();

wp_insert_post の Tips も簡単に紹介しておきます。

  • $post->post_date を設定しなければ実行時の時刻で記事が作成されます。
  • $post->post_author や $post->post_category は既に存在するユーザ/カテゴリーの ID を渡します。 カテゴリーは配列を渡します。
  • 記事 ID 指定で追加したい時は $post->import_id に ID をセットします。$post->ID は更新の時に使います。

詳しくは wp_insert_post のリファレンスをご確認ください。


2012.7.28 追記
マルチサイト化されていると $_SERVER の設定が必要です。以下の様な感じで動きました。

$_SERVER = array(
  "HTTP_HOST" => "hetarena.com",
  "SERVER_NAME" => "hetarena.com",
  "REQUEST_URI" => "/",
  "REQUEST_METHOD" => "GET"
                 );

内部リンクを壊さずに FC2 ブログの記事を WordPress にインポートする

内部リンク切れを起こさずに FC2 ブログを WordPress サイトに移行する際の手順です。 ブログ記事番号を合わせることで、FC2 ブログからの個別記事へのリダイレクトも可能なようにします。 ある程度プログラムや HTTP、HTML の知識がある人向けで、説明を端折っている部分もあります。 スクリプトプログラム等もダウンロードできるようにしていますが、環境に合わせて修正が必要となるので最終的には自己責任でご利用ください。 WordPress のバージョンは 3.3、3.4 で試していますが、Movable Type and TypePad Importer のバージョン (0.4) の方が重要です。 これ以降の説明はホスト名として実際に私が行った blogger323.blog83.fc2.com (FC2) と hetarena.com (WordPress) を使用します。

以下の条件で移行を行います。

  • http://blogger323.blog83.fc2.com/blog-entry-NNN.html を https://hetarena.com/archives/NNN に対応させます。(追記: 他のパーマリンク形式が良い人はコメント欄参照。)
  • FC2 にこれまでアップロードしたファイルは https://hetarena.com/oldimages/ の下に置きます。

手順の概要は以下の通りです。

  1. FC2 ブログでエクスポートした記事と sitemaps.xml を使用して、各記事に ID (先述の URL 内の NNN の部分) を付与したエクスポートデータを作成します。
  2. 記事中の内部リンクの変換を行います。
  3. Movable Type and TypePad Importer を一部変更し、ID を読むようにしてから記事をインポートします。
  4. 画像の引越し、FC2 のリダイレクトの設定を行います。

インポートするデータの作成

実際の手順では先の 1. 2 を合わせてプログラムで処理しました。 FC2 ブログの記事をエクスポートし、UTF-8 に変換して blogger323.txt として保存します。 続いて http://blogger323.blog83.fc2.com/sitemaps.xml をファイルとして保存します。 こちらの perl スクリプトをダウンロードし、先の 2つのファイルと同じディレクトリに置いて以下を実行します。

perl fc22wp.pl blogger323.txt > blogger323_wp.txt

これで「ID: 」の行が足され、更に内部リンクの変換が行われます。 perl のスクリプトについて簡単に説明すると以下の処理をしています。

  • blogger323.txt の「DATE:」行を sitemaps.xml の「<lastmod>」の日時とマッチさせ、記事番号の含まれる「ID:」行を挿入する。
  • blog-entry-NNN.html を archives/NNN に変換
  • blogger323.blog83.fc2.com を hetarena.com に変換
  • http://blog-imgs*.fc2.com/b/l/o/blogger323/ を /oldimages/ に変換

使い捨てで書いているので使用する際は「blogger323」、「hetarena.com」の含まれている行を適切に修正し、処理内容を確認してから使用してください。 まあ、短いプログラムなので見ていただければ perl を知らなくても何をしているか想像がつくと思います。

インポートの実行

WordPress に標準でついてくる「Movable Type and TypePad Importer」(Version 0.4) を使用しますが、そのままだと「ID:」行を読んでくれません。 そこで movabletype-importer.php に以下の修正を行います。 (wp-content/plugins/movabletype-importer/ の下にあるファイルにこのパッチファイルを当てても良いですが、WordPress 管理画面の「プラグイン編集」から修正するのがお手軽です)

--- movabletype-importer.php.orig       2011-01-15 09:53:03.000000000 +0900
+++ movabletype-importer.php    2011-08-02 20:22:59.000000000 +0900
@@ -388,6 +388,10 @@
                                $slug = trim( substr($line, strlen('BASENAME:')) );
                                if ( !empty( $slug ) )
                                        $post->post_name = $slug;
+                       } else if ( 0 === strpos($line, 'ID:') ) {
+                               $post_id = trim( substr($line, strlen('ID:')) );
+                               if ( !empty( $post_id ) )
+                                       $post->import_id = $post_id;
                        } else if ( 0 === strpos($line, 'STATUS:') ) {
                                $status = trim( strtolower( substr($line, strlen('STATUS:')) ) );
                                if ( empty($status) )

import_id はまともに公式解説されていないパラメータなのですが、更新のときは $post->ID に、新規のときは $post->import_id に記事 ID をセットして wp_insert_post を呼ぶと希望通りの ID で記事が更新/作成されます。

安全を期すならば blogger323_wp.txt をインポートする前に記事ID の大きなダミーデータを 1つ作成してインポートしておきます。 import_id で指定した番号の記事が存在すると既存最大 ID + 1 の番号が振られて記事が作成されてしまうのですが、こうしてダミーデータを入れておけば万が一既に記事が存在していたとしてもダミーデータの後ろの番号で作成され、続く記事のインポートに影響を与えません。

そのほかもろもろ

他にもいくつか実行しておくべきことがあります。

  • WordPress でパーマネントリンク設定を行って archives/NNN 形式を選んでおきます。
  • FC2 にアップロードされているファイルをダウンロードして WordPress ディレクトリの下の oldimages の中に置きます。 ダウンロードするファイルが多い場合は何かツールを使うなりしてダウンロードしましょう。 (私は HTML からリンクを取り出して wget を回すスクリプトを書いたような気がします)
  • RSSフィード読者向けに FC2 側に移転告知エントリを一つ書いておく必要があると思います。 FeedBurner を使っていれば、Original Feed URL を変更することで読者の手を煩わせることなく引き続きフィードを提供することができます。 しかし、この場合もリーダー上で既読情報等がリセットされるようなので告知をしておいた方が良いでしょう。
  • どこまでやるかという問題になるのですが、ここまでの手順で救えるのは個別記事 URL です。 カテゴリーやタグつき記事に対してのリンクが記事中に大量に埋め込まれている場合、それらへの手当ても必要かも知れません。 一つの手として Redirection プラグインを使う方法を紹介しておきます。 Redirection プラグインでは正規表現も使えるので、例えば「/\?tag=(.*)」→「/?s=$1」みたいなルールを作るとかつてタグで指定していた単語での検索結果を表示するようになります。
  • WordPress サイトの準備が整ったら FC2 テンプレートに meta refresh でリダイレクトする設定を入れます。 あと rel="canonical" の <link> タグも入れておいた方が良いでしょう。

最後の FC2 テンプレートの件については説明が必要ですね。 まずはリダイレクトは以下の記述を <head> セクションに追記します。 (実際は改行なしで書いています)

<meta <!--index_area--><!--/index_area--> http-equiv="refresh" 
content="0;URL=https://hetarena.com/<!--permanent_area-->
<!--topentry-->archives/<%topentry_no><!--/topentry--><!--/permanent_area-->" />

リダイレクトの設定についてはこちらの記事を参考とさせていただきました。 続いて <link> タグですが、以下の記述を同じく <head> セクションに追記します。

<!--permanent_area--><!--topentry-->
<link rel="canonical" href="https://hetarena.com/archives/<%topentry_no>" />
<!--/topentry--><!--/permanent_area-->

ところで

hetarena.com を立ち上げてからこれまでは FC2 ブログを Twitter のつぶやきアーカイブ用に使っていたのですが、最近、WordPress のカスタム投稿タイプを使えば hetarena.com 側でアーカイブしてもブログ記事と混ざらないことに気づき、FC2 ブログの方は閉鎖することにしました。 そんなこともあってこんな記事を書いてみたのでした。 ちなみにつぶやきアーカイブはこちらです。


コメントいただいたので、ちょっと追記

実行例を挙げておきます。 まずコマンドプロンプトを開きます。 アクセサリの下にありますが、スタートメニューで cmd.exe と入力してもコマンドプロンプトを実行できます。 まずディレクトリを作成します。まあ、ここはエクスプローラーで実行しても良いですが。

C:\Users>blogger323>mkdir c:\temp
C:\Users>blogger323>cd \temp
C:\temp>

強調部分が入力するところです。 ここまでで C:\temp フォルダができているので必要なファイルをそこに入れます。 そして perl コマンドを実行します。

C:\temp>perl fc22wp.pl blogger323.txt > blogger323_wp.txt

これで C:\temp フォルダの中に blogger323_wp.txt というファイルができます。

WordPress のカスタマイズを始める前に知っておくべきこと

はじめに

WordPress のカスタマイズを考えている方向けに以下の項目をまとめてみました。

  • 自分自身が WordPress でカスタマイズを始めた頃に、知っていたら作業が捗っただろうと思われること
  • WordPress サイト構築作業関連での私の個人的なお勧め

WordPress を導入しようと考えているぐらいなので、IT系のスキルがそれなりにある読者を前提としています。 また、ブログ用途として使おうと考えている方向けです。

CSS 中心のカスタマイズがお勧め

世の中には自作テーマに関するブログ記事が溢れていますが、まずは標準テーマの Twenty Ten や Twenty Eleven をベースに CSS で外観を変更するのがお勧めです。 ご存知のように Web ページの論理的構造は HTML、視覚的な構造は CSS という役割分担になっていますが、ブログの論理構造なんてたかが知れているわけで、特殊用途でない限り標準テーマをベースにすれば十分です。 もちろん、余裕があって興味のある人は一からテンプレートを作れば良いと思うのですが、その時も標準テーマの構成を理解しておくことが役に立つはずです。

一からのテーマ作成をお勧めしない理由はもう一つあります。 WordPress を使ったサイト構築に不可欠な各種プラグインは簡単に言ってしまえば、フック/コールバック関数の固まりなのですが、呼ぶべき関数を適切な場所で呼んでいないテンプレートではプラグインが動作しなくなってしまいます。 こんなマナーを覚えてフルスクラッチでテンプレートファイルをつくるよりは標準テーマの style.css の修正を集中してやった方が効率はずっと良いです。

CSS をいじろうとすると、どんな id、class が使われてマークアップされているかが重要ですね。 Twenty Ten でどうなっているかを別記事にまとめます (→ 追記: グズグズしていたら Twenty Twelve の時代になってしまったので企画倒れとなりました…)。 Twenty Eleven をベースとしたい場合は自分で調べてみてください。

ブログの外観は大事だと思うので、CSS のカスタマイズは気が済むまでやりましょう。 私の場合、スキルと時間が足りてないので、このあたりで妥協してしまっていますが…。

ちょっと断り書き

以下、公式情報へのリンクを記載していますが、残念ながら日本語化された公式情報は英語のものよりも古いことが多い (ひどい時は日本語版が存在しない) ので、英語版の方をリンクしておきます。 必要ならば、ページに表示されている「日本語」を辿って日本語版の方も確認してみてください。

テンプレート階層

それでも CSS で全て解決するわけではないので、テンプレートファイル (*.php) に手を入れる必要は出てきます。 広告入れたり、アクセス解析入れたり、みたいな時ですね。

で、この時にどこを直したら良いかを知るにはテンプレート階層とモジュール構成を理解しなければなりません。 表示されるページの種類によって使用されるテンプレートファイルが異なるのですが、このテンプレートファイルの選択は階層的に行われ、最低 index.php があればページの表示はできるという構造になっています。 まずすべきなのは公式情報を読み、この図の意味を理解することです。

Twenty Ten も Twenty Eleven もシングルポストなら single.php、固定ページなら page.php が使用されます。 ここで、例えば page.php ファイルを削除してしまうと、固定ページの表示には index.php が呼ばれることになります。 また、特定の固定ページのみ異なるテンプレートを使用したいのであれば、page-$slug.php か page-$id.php ($slug はスラッグ、$id はページ ID) を新たに作成すれば良いことがわかります。

モジュール化

しかし、標準テーマのディレクトリには、先の階層図には記載されていない名前のファイルが存在します。 これがどのように使用されるかを把握するには、テンプレートファイルのモジュール化についての理解が必要です。 テンプレートファイルはモジュール化されていて、例えば single.php でも page.php でもヘッダー表示には get_header() が呼ばれ header.php が使用されます。 (ここでいう「ヘッダー」は HTML の <head> + <body> の最初、すなわちページ上部までを指します)

なので、ページ上部に広告を表示したければ、header.php を編集するだけで、サイト全体に表示されるようになります。 このように get_* として使えるのは header/footer/sidebar があります。

ただし、標準テンプレートの構成を理解するには header/footer/sidebar だけでは不十分で更に get_template_part() を使った呼び出しを理解する必要があります。 例えば、Twenty Ten の loop-single.php は single.php 内のループ処理中で以下のように呼び出されています。

get_template_part( 'loop', 'single' );

同様に Twenty Eleven の single.php を見てみると、投稿表示部分では以下の形式で投稿のフォーマット (フォーマットについては後述) に従ったマークアップ用テンプレートファイルを呼び出しています。

get_template_part( 'content', get_post_format() );

このあたりの構造を理解してテーマディレクトリ内の各ファイルがどんな時に使用されるかを把握できれば、自ずと編集対象のファイルはわかるようになります。 他のファイルをインクルードする方法の詳細は公式サイトのこのページで解説されています。

メニューをカスタマイズしよう

メニューについても様々なプラグインを使いたくなってしまう人が多い様ですが、標準テーマそのままでもメニューを階層化してドロップダウンメニューを使用することができます。 メニュー設定を行っていない状態だと固定ページ一覧が表示されてしまうので、「使えない」と思っている人もいるのかも知れませんが、WordPress 管理ページの「外観 (Appearance)」-「メニュー (Menus)」からカスタムメニューを設定すれば簡単に階層化されたメニューを使い始めることができます。

階層化するには設定画面上のインデント配置で表します。 詳しい設定方法は WordPress.com に書かれていますが、操作は簡単です。

この hetarena.com も階層メニューを使用していますが、下図は「まとめ記事」-「DAW」-「Cubase」と3階層となっている例です。 この例の場合「まとめ記事」と「DAW」は「カスタムリンク」で「URL」を「#」に設定し、クリックしても何も起こらないようにしています (注: 記事執筆時の状況)。 あとは CSS で外見を整えれば十分ではないでしょうか。
階層化メニュー

子テーマの使用

あるテーマを元としてカスタマイズする場合、元テーマの子テーマとして作成し、変更を加えたいファイルのみを新テーマとして管理する方法があります。 標準テーマをベースにする場合は、もちろんこの子テーマ機能を使うことをお勧めします。 私も Twenty Ten の子テーマを作成して使っています。

ところで子テーマ作成時に1つ注意点があります。 大抵のファイル (style.css も含む) は親テーマのものが子テーマディレクトリ内に作成されたものに置き換わるのですが、functions.php については子テーマの functions.php がロードされてから親テーマの functions.php もロードされます。 ですので、差分のみを子テーマの functions.php に追加しなければなりません。

ついでに言うと functions.php に同じ名前で関数重複があると、管理画面含めて WordPress サイトの表示が真っ白になってしまいます! こんな時は焦らず functions.php を元に戻してアクセスし直せば復旧します。 ちょっと怖いですね。(はい、怖かったです)

子テーマ作成についても詳しくは公式情報ということで。 公式情報にも記載されていますが、style.css については以下のように親テーマの CSS ファイルを import した後、上書きしたい項目を列挙する形にしておくと、管理はしやすいと思います。

@import url("../twentyten/style.css");

HTML を直書きしたい

多分 Visual なエディタよりも HTML を直接書いて、改行も <BR> タグでコントロールしたい、という人はそれなりにいるんじゃないかと思います。 そんな人は HTML エディタに切り替えて記事を書くと思いますが、これだけでは改行箇所に <BR> が挿入されるのを防ぐことはできません。 functions.php に以下の記述が必要です。

<?php
function mywpautop( $pee ) {
  return wpautop($pee, 0);
}        

remove_filter( 'the_content', 'wpautop' );
remove_filter( 'the_excerpt', 'wpautop' );
add_filter   ( 'the_content', 'mywpautop' );    
add_filter   ( 'the_excerpt', 'mywpautop' );    
?>

詳しくは wpautop() の解説をご覧ください。

jQuery ファイルのインクルード

そして、JavaScript をいじりたくなり jQuery をインクルードするようなこともあると思いますが、注意してください。 WordPress のディレクトリには既に jQuery の .js ファイルが含まれていて、これを作法に従って呼び出す必要があります。 何故ならばプラグインが jQuery を使ったりしていてもインクルードするのを 1回にするためです。

.js ファイルをインクルードするには wp_enqueue_script() を呼び出します。 jQuery を使うには functions.php 内に以下を記述します。

wp_enqueue_script( 'jquery' );

WordPress に付属してくる jQuery ではなく、他の jQuery (例えば Google の CDN 版) を使用したいときの例は wp_enqueue_script() の解説ページで紹介されています。 (2013.3.23 追記: 最近内容が変わったようなので、CDN 版を利用したいときはこちらを参照してください)

ちなみに自作スクリプトをテーマファイルフォルダの下に置いて使うには以下のような呼び出し方ができます。 (pathto はテーマファイルが格納されるフォルダ配下のサブフォルダ名)

<script type="text/javascript" 
  src="<?php echo get_stylesheet_directory_uri(); ?>/pathto/yourscript.js"></script>

ちなみに get_template_directory_uri() だと親テーマのディレクトリ名を返してしまうので子テーマ作成の際は注意が必要です。 また、配布できるぐらいのテーマ作成を目指す人は自作スクリプトも wp_enqueue_script で呼び出すクセをつけておいた方が良いでしょう。

コンテンツ (投稿・ページ) の種類を増やしたい

このセクションの話は応用なので、今すぐには必要ないかも知れませんが、覚えておいて損はないと思います。 通常のブログ投稿と告知情報の扱いを分けたいとか、ただのテキスト記事とビデオ関連記事で見せ方を変えたい時などに使用できる機能として「カスタム投稿タイプ」「フォーマット」という2つの機能があります。 本来、この2つはそれぞれ異なる用途向けの機能なので、以下のように覚えておきましょう。

  • カスタム投稿タイプは通常の「投稿 (post)」以外のものをつくりたい時に使う機能です。(名前がミスリーディングですが)
  • フォーマットは「投稿」の種類を設定する機能です。 RSS フィードにそのコンテンツを載せたいのであれば、それはカスタム投稿タイプでなくフォーマット機能を使うべき状況だと思われます。

カスタム投稿タイプであれば、テンプレート階層で single-$posttype.php というファイルが使用されるので、種類に応じた扱いが可能です。 フォーマットであれば、先に紹介した Twenty Eleven の使用例が参考になります。 またフォーマットに関しては post_class() (= 投稿を囲む div に設定されるクラス) で返される CSS class の中にフォーマットを識別するものが含まれるので、新たな .php ファイルを作らずにフォーマット毎に CSS レベルで異なるスタイルを適用するという手もあります。

公式情報 (カスタム投稿タイプフォーマット) の他に、以下のリンクでもわかりやすく使用方法が解説されています。

最後にもう少し

  • WordPress プラグインはスマホアプリと同様、必要なものだけ導入することをお勧めしておきます。
  • SQL がわかる人はここら辺を見てデータベースを活用すると良いと思います。
  • スマホ対応はやっておいた方が良いでしょう。 無料の WPtouch を使う人も多いと思いますが、私はせっかく設定したカスタムメニューを使うために WPtouch Pro を購入してしまいました。
  • ガラケー対応はどうだろう…。 やるならば Ktai Style を使用することになると思いますが、そろそろ割り切っても良い頃のような気もします。

というわけで WordPress についてまとめてみました。 この記事が少しでもお役に立てれば幸いです。