TearSnow Fan


两个WordPress数据库合并和多站点共享用户数据表

本站下设中文版(http://blog.xieyc.com)和英文版(http://en.xieyc.com/blog)两个WordPress博客,最初考虑过使用WordPress的Multisite功能,但是看网上的评论,都说开启Multisite功能后,WordPress的结构复杂很多,而且数据库变得庞大臃肿,不如单站点稳定。因此最后还是使用了两个WordPress,并且为两个WordPress分别新建了两个数据库。

近日想将这两个WordPress数据库合并为一个,一个原因将主机空间从美国的VPS更换到了香港的虚拟主机,主机只支持5个数据库,两个WordPress就要占其中2个太浪费了。另一个更重要的考虑是想把用户数据表在两个WordPress站点间共享,使用户在一个WordPress注册后,可以登录两个网站。

原理比较简单,下面简单说下操作的步骤。

合并2个已有WordPress网站的数据库并共享用户数据表

先介绍背景:

目前两个WordPress分别独占数据库,数据库名 xieyccom_blog 和 xieyccom_en,数据表都是用默认的数据表前缀"wp_"。

希望保留数据库_blog,删除_en数据库,并将_en数据库中的数据迁移到_blog中。具体为:wp_users 和 wp_usermeta 两个数据表内容合并,保留"wp_"的前缀;其余从_en数据库移入的数据表前缀改为"enblog_"。

使用PhpMyAdmin管理面板,操作前一定记得先备份!

==================== 割 ====================

操作步骤:

第一步:先想办法将_en数据库中的wp_users和wp_usermeta数据表合并到_blog数据库的同名数据表中。先要看下这两个表的结构,大概的结构是:用户基本信息在wp_users表中,其他乱七八糟的信息在wp_usermeta表中,依赖user_id建立联系。我的英文站刚建立不久,注册用户很少,因此手工解决了。如果数据量大的话,还是自己写个SQL语句吧,需要注意的是user_id和umeta_id都是自动编号字段。

第二步:将_en数据库中的其余9个数据表改名复制到_blog数据库中。分别选中每个数据表,然后使用Operations - Copy table to (database.table) 的功能,可以将表复制到另一个数据库同时改名,如下图:

 

当然,如果你先把表改名了,也可以一次性的全部导出,然后导入到目标数据库中。具体操作可以参考本站关于数据库备份和恢复操作的帖子:使用phpMyAdmin备份和恢复WordPress数据库

第三步:修改英文博客的配置文件wp-config.php,具体有以下几处修改:

1、define('DB_NAME', 'xieyccom_en'); 改为整合后的数据库名xieyccom_blog,如果两个数据库使用了不同的用户名和主机位置,还需要相应更改DB_USER、DB_PASSWORD、DB_HOST等;

2、$table_prefix  = 'wp_'; 改为 $table_prefix  = 'enblog_';

3、在文件中插入:

define('CUSTOM_USER_TABLE', 'wp_users');
define('CUSTOM_USER_META_TABLE', 'wp_usermeta');

注意这里的wp_users和wp_usermeta都是第一个WordPress的用户数据表表,如果没有使用默认前缀,需相应修改。

完成上述步骤后,本以为大功告成,但是登陆后提示:

You do not have sufficient permissions to access this page.(你没有足够的权限访问该页面)

这是怎么回事呢?经查看数据库,wp_usermeta表中存储了用户权限,这个权限的值是以wp前缀开头的,以站点的首个管理员为例,该管理员用户id为1,角色是administrator,则表中就有类似这样的记录

user_id->1, meta_key->wp_capabilities, meta_value->a:1:{s:13:"administrator";s:1:"1";}

详见图:

但是数据库中还没有以"enblog_"为前缀的记录,如果试图使用该用户登陆以“enbog_”为前缀的网站(http://en.xieyc.com/blog),由于用户在该站点还没有角色,就会被提示没有足够的权限。

解决的方法是向数据库插入包含enblog_前缀的数据,即

user_id->1, meta_key->enblog_capabilities, meta_value->a:1:{s:13:"administrator";s:1:"1";}

给出 SQL 查询语句:

 

INSERT INTO `dbname`.`wp_usermeta` (`umeta_id`, `user_id`, `meta_key`, `meta_value`) VALUES (NULL, '1', 'wpen_capabilities', 'a:1:{s:13:"administrator";s:1:"1";}');


可能还需要添加的令一行数据是:

user_id->1, meta_key->enblog_user_level, meta_value->10

这样做仅仅使用户id为1的管理员可以正常登陆这两个网站。对于其他用户(包括之后新建的),如果试图在非创建本用户的网站登录,仍然会被提示权限不足,除非你一条一条的向数据库里插入数据,并且要注意改变角色。当然也可以用提示权限不足的网站管理员登录,在后台将用户角色从“无”改为对应的角色,其作用和向数据库插入数据是类似的。

一劳永逸的做法是写一段小代码让这个过程自动完成,代码如下:

//设置主站的前缀,其它网站都共享该网站的用户数据表
$main_prefix = 'wp_';
//设置子站的前缀,例如有两个子站,前缀分别为wpen_和wpcn_
$addi_prefixs = array('wpen_','wpcn_');
//添加功能到用户注册的钩子里
add_action( 'user_register', 'dup_capabilities' );
function dup_capabilities( $user_id ) {
    global $main_prefix, $addi_prefixs;
        //获取该用户权限的值,因为不同角色的值是不同的
    if( $cap_val = get_user_meta( $user_id, $main_prefix.'capabilities', true ) ) {
        if( count( $addi_prefixs ) > 0 ) {
            foreach( $addi_prefixs as $prefix ) {
                add_user_meta( $user_id, $prefix.'capabilities', $cap_val, true );
            }
        }
    }
}

WordPress 3.5上用这段代码:

add_action( 'user_register', 'dup_capabilities' );
add_action('profile_update', 'dup_capabilities');
function dup_capabilities( $user_id ){
//在这里设置数据表前缀,不分主站子站,全部写上即可。
$prefixs = array('wp11_','wp12_','wp13_');
global $table_prefix;
$cap_val = get_user_meta( $user_id, $table_prefix.'capabilities',true);
if( !empty( $cap_val ) ) {
foreach( $prefixs as $prefix ){
if( $prefix != $table_prefix )
update_user_meta( $user_id, $prefix.'capabilities', $cap_val );
}
}
}

已验证:经测试,在任意站点删除用户时,wp_usermeta表中对应该user_id的记录均会被完全删除,无论该记录是供哪个WordPress站点使用的,猜想可能是执行了在wp_usermeta表中删除所有"user_id=某个值"的记录。

未验证:更改某用户权限时,两个站点在wp_usermeta表中记录的同步问题。

待解决:如果在表wp_usermeta中添加数据后访问还有问题,可能说明更改前缀后,数据库其他表中的部分内容也需要更新。目前还没有完全明确需要更新的内容,经查阅网络资料,可能涉及到的数据还有:

表“wp_option”中,查找"option_name"="wp_user_roles"的行,目前不清楚是否应删除、还是修改或者使用"option_name"="enblog_user_roles"复制改行,希望高手指点!

简易情况:至少一个站点中没有数据(或数据较少),可以重建

上述方法适用于两个站点已经都有数据的情况下。如果你的第二个WordPress站中文章等数据很少,可以重建,则就不必像上面那么麻烦。

仍然以本站为例,如果英文WordPress站点数据不多,可以新建。则首先应用WordPress自带的功能以XML形式导出所有内容(文章、评论和页面等)。然后在上述第一步整合 wp_users 和 wp_usermeta 表后,就不必复制其他数据表了。直接修改wp-config.php文件后,访问http://en.xieyc.com/blog/wp-admin/install.php安装向导,会自动提示检测到已存在的用户,无须新注册管理员用户,如下图。

则系统会自动为user_id=1的管理员账户添加带有"enblog_"前缀的权限,之后可以使用该用户进行登录并进入网站后台。对于其他用户(包括以后新建用户)的处理,可以参考上文的解决方法。

让用户在多个WordPress网站之间通行登录

既然主站和英文站共享了用户数据,那么用户从任何一个网站登录,都应该自动登入另一个网站,可以在两个网站之间任意切换。这就涉及到整合wordpress cookie的问题。

这是一个WPMU的替代方案,并不是整合不同域名之间的wp网站,所有有一些限制。继续读之前请了解以下事实:

1. 出于安全问题,cookie不能在多域名之间共享,如果你追求的是 www.youdomain.com 和 www.anotherdomain.com 之间通行登陆,以下的方法不适用。也许你应该尝试通过PHP脚本自动登陆WordPress

2. 本方法支持的类型:

次级域名之间的通行登陆,例如 sub1.yourdomain.com 和 sub2.yourdomain.com 之间通行登陆

同一个域名下不同目录之间互相登陆,例如 www.yourdomain.com 和 www.yourdomain.com/site1 以及 www.yourdomain.com/site2 之间通行登陆。

测试环境(统一域名下不同目录间相互登陆):

WordPress版本: 3.3.1

主站:http://blog.xieyc.com (假设)

英文站:http://blog.xieyc.com/en (假设)

实现步骤:
1. 打开主站的wp-config.php,找到如下代码, 如果宏定义的值不是随机字符串,点击这里生成。

define('AUTH_KEY',         '{+Y:wtH~E}E2g7#$/_{%df9F2!9ed}m=E%^}%,[Z#;+R+vk]@q:x4u)?G,-#I89g');
define('SECURE_AUTH_KEY',  ' -$Hdq00N4F|iv4n&|}W]h:U}5?+jUb%)G#zgr={ 4yvgSRO;h-K+}R;&n.AAFv0');
define('LOGGED_IN_KEY',    '/K{%RclWh_e|46hl6w.b&C*U2cQ$&ZpL)n@|itUtHPm#PMS+9Jd|m%*5h#NQ1{k%');
define('NONCE_KEY',        '-Aluq5#|Pp:D6EsB8G-os=o${5FmP6!S#U)xgQsvAR2+0E/mz,{[b+6[zX4]OnUU');
define('AUTH_SALT',        'X:_SQx~;s}9|FIZ:pvR|beA>Jca_}.;S+sW>-^GFdFQ zjQUA<+G0z{_S+M'); define('LOGGED_IN_SALT',   'd`U.1inPDll}cH1Qcp,IaUeB+TO_m440$>IGs4B;v$)q^N>g[!&;t');
define('NONCE_SALT',       't`.LtDKyc9(fQlA@EMrvu*F(U6&amp;CV:%qKQ:eKz+0I*.V,0(@9E~9K</pre>!2087pJqs=Q');

2. 拷贝主站wp-config.php中的AUTH_KEY和SECURE_AUTH_KEY到英文站的wp-config.php中,替换相应的行。如果嫌麻烦上面代码全部拷贝到英文站也可以。

3. 在主站和英文站的wp-config.php中创建下面代码,记得去生成一个复杂的随机字符串,不要直接拷贝,主站和英文站的SECRET_SALT值要相同。

define('SECRET_SALT', 'Q$QuHIfQO^(CtrL5D(fcG$miB,fE2]-~::qoB,O_?o|TfgNfQB/x/kv$Tg1Aa7Hf');

4. 在主站和英文站的wp-config.php中创建如下代码

define('ADMIN_COOKIE_PATH', '/');
define('COOKIEPATH', '/');
define('SITECOOKIEPATH', '/');
define('COOKIEHASH', md5('用自己的随机字符串替换'));

5. 清除浏览器的cookie,选择其中一个网站登录,然后直接访问另一个网站的wp-admin,看是不是已经自动登陆了。

不同次级域名之间的通行登陆:

在所有网站的wp-config.php中再加上:

define('COOKIE_DOMAIN', 'yourdomain.com');

注意域名不要加www。

参考资料:

[1] 多个wordpress网站共享用户数据的方法(评论也很有用)

本文固定链接: http://blog.xieyc.com/merge-wordpress-database-and-share-user-tables-in-multisites/ | 小谢的小站

该日志由 xieyc 于2013年05月19日发表在 站长 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 两个WordPress数据库合并和多站点共享用户数据表 | 小谢的小站
关键字:

目前共有 1 条留言 【 访客:1 条, 博主:0 条 】 访客以 1:0 暂时领先博主!

  1. 沙发
    大隻佬:

    按照你的方法 一步步来 还是,不行。 重新安装新站时检测不到已经存在的用户。还望指点迷津

    2016-08-23 19:38

发表评论

:wink: :neutral: :mad: :twisted: :smile: :shock: :sad: :roll: :oops: :eek: :mrgreen: :lol: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

快捷键:Ctrl+Enter