作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
我们首先来看一个简单的实例。如果一个单位使用了Drupal6搭建了自己的网站,觉得比较好用,在另一个新建网站上使用了Drupal7,然后提出了这样的需求,那就是Drupal6站点的用户能够直接登录到Drupal7上,这里假定两个网站都放在同一个服务器上。
我们把这个模块的名字命名为d6user,表示Drupal 6的用户集成,先创建两个文件d6user.info, d6user.module。接着我们向info文件中添加以下代码:
name = Drupal 6 User
description = Drupal 6 老网站用户的同步登录.
core = 7.x
注意文件的编码格式,UTF-8。接着我们向module文件中添加逻辑代码:
<?php
/**
* @file
* 当登录Drupal7站点时,检查是否在drupal6站点存在这个帐户,
* 如果存在,将其保存到新的站点.
*/
/**
* 实现钩子hook_form_FORMID_alter().
*/
function d6user_form_alter(&$form, &$form_state, $form_id){
//这里我们对于表单user_login,user_login_block同时添加了一个验证器
if($form_id == 'user_login' || $form_id == 'user_login_block'){
$form['#validate'] = d6user_login_default_validators();
}
}
我们需要在用户登录时,提前检查Drupal6站点是否存在该用户,所以我们需要修改user_login、user_login_block表单,把它的验证函数集合,替换成我们自己的。我们先来看一下Drupal核心为登录定义的验证器函数:
function user_login_default_validators() {
return array('user_login_name_validate', 'user_login_authenticate_validate', 'user_login_final_validate');
}
我们看到,这里定义了3个验证器函数:
user_login_name_validate:用来检查是否设置了用户名,并且它对应用户的状态是否为0,如果属于这种情况,则为表单返回错误信息;
user_login_authenticate_validate:首先会检查连续尝试登录未成功的次数,如果超过了最大次数,则返回;反之,会根据用户名、密码、以及状态为1,来对users表进行查询,如果返回结果的不为空,为user_login_name_validate设置对应的标记$form_state['uid'];
user_login_final_validate:会根据$form_state['uid']是否存在进行判断,如果不存在,则为表单返回错误信息,反之登录用户。
对于大多数的外部验证系统,只需要修改第二个验证器就可以了。在我们的这个例子当中,我们将三个验证器全部保留了下来,并在第一个验证器函数后面追加我们自定义的验证器函数。代码如下:
/**
* 我们自己的登录验证函数集合,.
*/
function d6user_login_default_validators(){
//注意这里面保留了Drupal自带的验证器,只是在中间加上了一个自定义的验证器。这些验证器的执行存在先后顺序的
return array('user_login_name_validate', 'd6user_user_form_validate', 'user_login_authenticate_validate', 'user_login_final_validate');
}
最后,我们看一下d6user_user_form_validate函数的代码:
/**
* 我们自己定义的登录验证函数,它在user_login_authenticate_validate前面执行.
*/
function d6user_user_form_validate($form, &$form_state){
//form_set_error('name',t('用户名,密码不匹配.')); 这里保留了调试信息
$name = $form_state['values']['name'];
$pass = $form_state['values']['pass'];
if (!empty($name) && !empty($pass)) {
//drupal_set_message('123');
// 这里保留了调试信息,用户调试代码,方便大家测试
$account = db_query("SELECT * FROM {users} WHERE name = :name ", array(':name' => $name))->fetchObject();
//如果用户名存在,则返回.
if ($account) {
return;
}else{
// $sql = "SELECT * FROM {users} WHERE name = :name AND pass = :pass";
//drupal_set_message('123456');
//我们向Drupal6站点的用户表进行查询,检查该用户是否存在。
db_set_active('d6user');
$account = db_query("SELECT * FROM users WHERE name = :name AND pass = :pass", array(':name' => $name, ':pass' => md5($pass)))->fetchObject();
db_set_active('default');
if($account){
// drupal_set_message('1234567');
//此时,用户帐号在Drupal6中存在,并且用户名密码正确
$userinfo = array(
'name' => $name,
'pass' => $pass,
'mail' => $account->mail,
'init' => $name,
'status' => 1,
'access' => REQUEST_TIME
);
//我们将查询到的信息保存到Drupal7的用户表中
$account = user_save(drupal_anonymous_user(), $userinfo);
}
}
}
}
上述代码中,有详细的注释,这里就不再过多解释。我们需要做的是,修改settings.php文件,让Drupal7站点能够直接访问Drupal6站点的数据库。有关Drupal连接多个数据库,可参看数据库API一章。修改的代码如下:
$databases['default']['default'] = array(
'driver' => 'mysql',
'database' => 'thinkindrupal',
'username' => 'root',
'password' => '',
'host' => 'localhost',
'prefix' => '',)
;
$databases['d6user']['default'] = array(
'driver' => 'mysql',
'database' => 'drupal6',
'username' => 'root',
'password' => '',
'host' => 'localhost',
'prefix' => '',
);
这样,当用户登录时,如果该用户名在Drupal7站点上不存在,那么我们会检查它是否存在于Drupal6站点上,如果存在,自动将其保存到Drupal7的系统中去。