自分でプラグインを作るのが一番いい解決方法だと思います。
- ユーザの登録時とユーザ情報の変更時にget_user_meta()を利用して、
{AのDBのテーブルPrefix}_capabilities
というメタ情報を取得。
- その値を、add_user_meta()を利用して、
{BのテーブルPrefix}_capabilities
というメタ情報に書き込む
という感じのフローで実現が可能かと思います。
回答ありがとうございます。
ご提案のフローを記述してみました。今のところ登録時のみのものです。
AのDBのテーブルPrefixが「wp_」で、
BのDBのテーブルPrefixが「wp2_」としています。
サイトAに以下の関数を作成しましたが、うまくいきません。
function synchro_roles ( $user_id ) {
$role = get_user_meta( $user_id, 'wp_capabilities' );
add_user_meta( $user_id, 'wp2_capabilities', $role );
}
add_action( 'user_register', 'synchro_roles' );
原因は以下のようにwpからwp2に値を移す際に余分なシリアライズが入ることです。
wp_capabilitiesのmeta_value → a:1:{s:11:”contributor”;b:1;}
wp2_capabilitiesのmeta_value → a:1:{i:0;a:1:{s:11:”contributor”;b:1;}}
上記のことがわかっていながら対策が打てない状況です。
大変申し訳ないのですが、アドバイス・打開策をいただけないでしょうか?
get_user_meta( $user_id, 'wp_capabilities' )
の結果をmaybe_unserialize()
でシリアライズを解除してあげれば解決するかと。
回答ありがとうございます。
Daisuke Takahashi様の回答が「シリアライズ化されてDBに格納されていた文字列をPHPの配列に変換して$roleに格納するという操作をすればいいのではないか」という提案と解釈して返信しています。
get_user_meta関数が実行しているget_metadata関数を見てみると出力時にmaybe_unserialize関数を通しており、get_user_metaの時点でシリアライズ化は解除されているため、maybe_unserialize()でgetした結果のシリアライズを解除しても解決には至りませんでした。
ソースコードを確認したところ、WordPressはシリアライズを解除するために正しい実装をしてはいません。はっきりというとバグです。
maybe_serialize()はis_serialized()をコールしていますが、wp-includes/functions.phpの297行目にif ( false !== $semicolon && $semicolon < 3 )
とあり、今回のケースでは$semicolon
の値が2であるため、is_serialized関数はfalseを返します。
その結果、maybe_unserialize()はそのままの文字列を返してきています。
今回のケースですが、PHP 5.5.13で確認したところ、PHPのunserialize()を利用することにより、正しくunserializeできるようです。
回答ありがとうございます。
またCoreファイルの修正依頼ありがとうございます。
function maybe_serialize( $data ) {
if ( is_array( $data ) || is_object( $data ) )
return serialize( $data );
// Double serialization is required for backward compatibility.
// See http://core.trac.wordpress.org/ticket/12930
if ( is_serialized( $data, false ) )
return serialize( $data );
return $data;
}
add_user_meta関数の中で使用されているmaybe_serialize関数(上記)を見てみました。
Daisuke Takahashi様の提案に従い、unserializeをして配列に戻したとしても、1回目のif文で正常なシリアライズが施され、2回目のif文のis_serialized関数で「シリアライズされていない」という判断をされ、更にシリアライズが施されるため、手の打ちようがないということがよくわかりました。
解決策としては
・アップデートを待ってそれに合わせたプラグインを作成する
・手でCoreファイルを書き換える(こちらはあまりしたくないです)
くらいでしょうかね。。。
結果としては「この問題は再現が困難な特定の環境での問題」ということになりました。
データベースやテーマの文字コード、wp-config.phpやfunctions.php、PHPやWebサーバの設定などに特別な設定をしていないかを確認してみてください。
一時的回避策としては
function synchro_roles ( $user_id ) {
$role = unserialize( get_user_meta( $user_id, 'wp_capabilities' ) );
add_user_meta( $user_id, 'wp2_capabilities', $role );
}
add_action( 'user_register', 'synchro_roles' );
が有効かと思います。
回答ありがとうございます。
サーバはさくら、データベースは文字コード以外に変更はしていません。
(データベース文字コード:UTF-8)
テーマ:Twenty Fourteen
また設定に関してはwp-config.phpの
/**
* ローカル言語 - このパッケージでは初期値として 'ja' (日本語 UTF-8) が設定されています。
*
* WordPress のローカル言語を設定します。設定した言語に対応する MO ファイルが
* wp-content/languages にインストールされている必要があります。例えば de.mo を
* wp-content/languages にインストールし WPLANG を 'de' に設定することでドイツ語がサポートされます。
*/
define ('WPLANG', 'ja');
の下に
define('CUSTOM_USER_TABLE', 'wp_users');
define('CUSTOM_USER_META_TABLE', 'wp_usermeta');
を追加したことに加えて、function.phpに記載した作成した関数を作成したのみです。
また、いただいた回避策に関してですが、wp2_capabilitiesの中身が空白の状態になり、権限グループの共有はできませんでした。
すみません追記です。
プラグインは現在すべて無効化しています。
p.s.
ツイッターを拝見しました。
ご協力、誠にありがとうございます。試験頑張ってください。
ありがとうございます。
テーマのfunctions.phpに以下のコードを書いて、出力を教えていただいてもよろしいでしょうか。
add_action('init', 'check_is_serialized');
function check_is_serialized() {
echo (true === is_serialized('a:1:{s:11:"contributor";b:1;}')) ? 'true' : 'false';
echo (true === is_serialized(get_user_meta( get_current_user_id(), 'wp_capabilities' ))) ? 'true' : 'false';
die();
}
コードありがとうございます。
真っ白な画面にtruefalseと出力されました。
ありがとうございます。functions.phpに追記したコードは削除していただいて結構です。
使用しているホスティングの名前やサーバソフトウェアのバージョンなどは分かりますか?
削除の件、かしこまりました。
ホスティングは、、、さくらサーバという回答で大丈夫でしょうか?
OSバージョンは「FreeBSD 9.1-RELEASE-p15 amd64」と記載してあります。
その他ソフトウェアのバージョンは以下の通りです。
Apache:2.2.25
MySQL:5.5
PHP:5.4.29
ありがとうございます。特に問題が報告されているような環境でもないので、検証するためのプラグインを作成しました。こちらのZIP形式のプラグインをご自身のサイトに追加して結果を教えてください。
結果はダッシュボードにウィジェットとして表示されます