WordPressをお客様に納品する場合など、最初に仮ドメインで設置をして、公開のタイミングで本ドメインに切り替えるという作業をよく行います。

それ以外にも、WordPressが動いているサーバーのドメインを変更しなくてはならなかったり、ステージングサーバーから公開サーバーにデータコピーをしたりと、WordPressを移設して動かすタイミングって、割と多かったりします。

移設の問題点

移設を行う場合の一番の問題点は、公開URLが変更になることです。

  1. テーマファイルのCSSやJavaScriptが読み込まれないためデザインが崩れる
  2. 公開URLが正しくないとWordPressの管理画面にログインができない
  3. 記事中に設定したリンクや、メディア(画像やファイル)が全てリンクが切れてしまう

1. 2. については公開URLの設定さえ元に変更してしまえば問題無いのですが、一番の問題は 3. で、記事中に設定した内部リンクやら、画像やら添付ファイルやらが全てリンク切れを起こしてしまうことです。

Search Regexという正規表現などで記事を検索してURLを置換できるツールなどが、まず考えつく1つの方法です。

しかしこのSearch Regexは、通常の投稿や固定ページの内容は置換できますが、カスタム投稿は検索できません。(カスタマイズすれば可能ですが)

またなにより大きな問題として、このプラグインではカスタムフィールドに入力された内容は対象外となってしまうため、カスタムフィールドに画像のURLや記事のURLなどが入っている場合、こちらを修正することができません。

CONTINUE READING

WordPressでカスタム投稿やカスタム分類を使って、新しく分類や投稿を作成することは簡単に情報が見つかります。

しかし逆に、デフォルトの「投稿」機能から「カテゴリー」や「タグ」といった、 デフォルトで設定されている分類機能を取り外したいといった場合の情報はあまり見つかりません。

そんな時は下記のコードをfunctions.phpに記述して利用します。

function my_unregister_taxonomies()
{
	global $wp_taxonomies;

	/*
	 * 投稿機能から「カテゴリー」を削除
	 */
	if (!empty($wp_taxonomies['category']->object_type)) {
		foreach ($wp_taxonomies['category']->object_type as $i => $object_type) {
			if ($object_type == 'post') {
				unset($wp_taxonomies['category']->object_type[$i]);
			}
		}
	}

	/*
	 * 投稿機能から「タグ」を削除
	 */
	if (!empty($wp_taxonomies['post_tag']->object_type)) {
		foreach ($wp_taxonomies['post_tag']->object_type as $i => $object_type) {
			if ($object_type == 'post') {
				unset($wp_taxonomies['post_tag']->object_type[$i]);
			}
		}
	}

	return true;
}

add_action('init', 'my_unregister_taxonomies');

これだけで簡単に「カテゴリー」や「タグ」などを外すことができます。

WordPressを複数のユーザーで運営しているとき、投稿やメディアに関しては自分以外が投稿したものも、標準で表示されるようになっています。

特にメディア関してはフィルタをするような項目がなく、自分が投稿したもののみを表示するような仕組みが用意されていません。

そのため、自分が投稿した画像を他人に利用されてしまったり、逆のこともできたりと、少々お粗末な管理になってしまっています。

フィルターフックを使って表示を制限

WordPressではWP_Queryクラスを利用して、一覧や詳細画面を表示する際にデータベースから投稿を取得してきます。

そこで、WP_Queryクラスが投稿を取得する前に、今現在ログインしているユーザーの投稿やメディアのみを取得するようにクエリを書き換える事で、上記のような問題を解決することができます。

下記のコードをfunctions.php等に記述してください。

function my_pre_get_posts_filter(&$wp_query)
{
	global $pagenow;
	$user = wp_get_current_user();

	if (WP_ADMIN && ($post_type = $wp_query->get('post_type'))) {
		if (in_array($pagenow, array('media-upload.php', 'upload.php')) && $post_type == 'attachment') {
			// メディアの表示情報を制限
			$wp_query->set('author', $user->ID);
		}
	}
}

add_action('pre_get_posts', 'my_pre_get_posts_filter', 10, 1);

管理画面で表示しているかどうかの条件判断についてはもっと良い方法があるかと思うんですが、とりあえず上記コードで問題無く動作しています。

WordPressのマルチサイトを利用して子ブログを作った場合、
子ブログでアップロードしたメディアファイルは、
全て /wp-content/blogs.dir/{blog_id}/{year}/{month}/{file_name} に保存されるようになっています。

しかしながら、実際にアップロードしたファイルのURLを取得すると、
/{account_name}/files/{year}/{month}/{file_name} というURLが帰ってきます。
これは、マルチサイト用の .htaccess にURLの書き換え処理が記載されているためです。

# uploaded files
RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [L]

このURLに直接アクセスすればファイルは表示されますし、通常の利用上では全く問題はありません。

しかしながら、サムネイルを生成する際に非常に便利なライブラリである TimThumbなどを利用する際に、この書き換えられたURLが問題になります。

TimThumbは、与えられたURLから実際のファイルパスを計算し、ファイルを読み込もうとします。

しかし、この与えられたURLは .htaccess により書き換えられたダミーのURLのため、実際にこの場所にはファイルは存在しません。

そのため、書き換えられる前のURLが必要になります。

関数作った

下記のような関数を作ってみました。

function ms_calc_media_url($blog_id, $media_url)
{
	global $wpdb;

	switch_to_blog($wpdb->siteid);
	$url = preg_replace('|^' . get_blog_option($blog_id, 'siteurl') . '/(files/[\d]{4}/[\d]{2}/.+)$|', get_bloginfo('url') . '/wp-content/blogs.dir/' . $blog_id . '/$1', $media_url);
	restore_current_blog();

	return $url;
}

$blog_id に当該のファイルをアップロードした子ブログのIDを指定して、$media_url にファイルのURLを与えれば、書き換えられる前のURLを計算して出力します。

この関数を使うことで、問題無くTimThumbなどのライブラリを活用できます。

WordPressをマルチブログで利用する場合に、子サイトのテーマをあらかじめ設定しておく方法を紹介します。

親サイトの functions.php に下記の記述をするだけです。

function default_theme_setting()
{
	update_option('template', 'theme_name');
	update_option('stylesheet', 'theme_name');
	update_option('current_theme', 'Theme Name');
}

add_action('populate_options', 'default_theme_setting');

theme_name となっている箇所は、テーマのディレクトリ名を入れます。
Theme Name となっている箇所は、テーマの名称を入れておきます。

子テーマを指定する方法

上記の設定で、あるテーマの子テーマを設定しようとすると上手くいきません。
これは、下記の記述にすることで対応可能です。

function default_theme_setting()
{
	update_option('template', 'parent_theme_name');
	update_option('stylesheet', 'child_theme_name');
	update_option('current_theme', 'Child Theme Name');
}

add_action('populate_options', 'default_theme_setting');

parent_theme_name は親テーマのディレクトリ名を入れます。
child_theme_name は子テーマのディレクトリ名を入れます。

要は stylesheet というオプションに子テーマ名を設定し、template というオプションには親テーマを設定しておかなきゃイカンよ、ということです。