每一个请求到来后,Drupal会构建一个$user对象,回来保存用户信息,所有匿名用户对应一个特定的对象。
实现这一过程是在引导的会话阶段完成的。
1.bootstrap.inc
<?php
case DRUPAL_BOOTSTRAP_SESSION:
require_once variable_get('session_inc', './includes/session.inc');
session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy_sid', 'sess_gc');
session_start();
break;
?>
调入会话处理文件,通过session_start()引导定制的SESSION函数:
* sess_open($save_path,$session_name);会话一开始会调用此函数,进行初始化工作。 这两个参数分别对应php.ini里的两个配置。
session.save_path = "N;MODE;/path"
session.name = PHPSESSID
* sess_read($key);[这里面的参数应该是session_id,这个ID可能是可客户端传来,也可能是sess_open生成。]
---------------------------------------
[初始化了什么?个人胡扯:]
会话开始,会判断是否有保存会话ID的COOKIE过来,如果有,那么就根据php.ini里设置的路径里找这个绘画id对应的session文件,反序列化。以备使用。如果没有保存会话id的COOKIE过来,那么就为这个可客户端分配一个会话ID,并在对应的路径里,初始化这个文件。
---------------------------------------
* sess_write($key, $value):[两个参数,一个为session_id,一个为会话关闭以前对会话设置的值。也就是通过$_SESSION[]设置的值。序列化后保存在sessions表的session字段。]
会话流程
* 如果是匿名用户第一次来
<?php
if (!isset($_COOKIE[session_name()])) {
$user = drupal_anonymous_user();
return '';
}
?>
drupal_anonymous_user函数原型,他会构建一个uid为0的$user对象,所有匿名用户公用uid=0的对象。
<?php
function drupal_anonymous_user($session = '') {
$user = new stdClass();
$user->uid = 0;
$user->hostname = ip_address();
$user->roles = array();
$user->roles[DRUPAL_ANONYMOUS_RID] = 'anonymous user';
$user->session = $session;
$user->cache = 0;
return $user;
}
?>
sess_write()会判断是否写入SESSIONS表,只有一种情况uid==0,客户端没有传session_id过来 ,会话期间没有设置SESSION,这三个条件同时成立,才不写入session表。
<?php
if (!session_save_session() || ($user->uid == 0 && empty($_COOKIE[session_name()]) && empty($value))) {
return TRUE;
}
?>
* 匿名用户已经来过了,并且COOKIE不过期。
<?php
$user = db_fetch_object(db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = '%s'", $key));
?>
因为已经来过,所以存在session_id.就会查询对应users表和sessions表来,不过是uid=0的。
如果你是一个匿名用户第二次来,在你之前没有其他匿名用户,那么会在sessions表里,插入一行,否则会更新uid为0的那一行。
* 注册用户登录。如果是第一此登录,更新的是sessions表里的对应uid的记录。
$user对象是users表,sessions表,roles表三表的联合体。
在$user对象中,有两个键可以存储数据,一个是date字段,一个是session字段,date字段是保存在users表中,数据是永久性保存,而 session是保存在sessions表中,数据保存时间可定制。
$user保存的序列化后的字段。drupal_unpack()这个函数是把$user的date字段里的值反序列化成键值对放到$user对象里
<?php
global $user;
$extra_data = array('disposition' => t('Grumpy'));
user_save($user, $extra_data);
?>
$user['session']保存的也是序列化后的字段,通过设置$_SESSION就可以保存了。
<?php
$_SESSION['date1']='date1';
?>
通过$user表的uid属性,是否为0,可以判断一个用户是否为登录用户。user_is_logged_in()这个函数也可以判定。
hook_user
<?php
function hook_user($op, &edit, &$account, $category = NULL){
//参数$op用来描述对用户账号所进行的当前操作,它可以有多个不同的值
switch($op) {
case 'register':
$fields['legal_agreement'] = array(
'#type' => 'fieldset',
'#title' => t('Legal Agreement')
);
}
//这个操作在用户打开注册页面时候发生,在显示注册页面之前,会调用这个钩子,添加一个字段。
}
?>
$op的值
* after_update:$user对象里的东西被保存到数据库后,就会触发
* categories :在用户信息页面,会有一些信息分类,这个钩子选项,应该是在显示这些分类前执行,可以加入一些自己定义的分类。也就是在加个分类
<?php
function change_user_user($op,&$edit,&$user,$category=NULL){
switch ($op){
case 'categories':
$out_user[]=array(
'name' => 'myfiretname',
'title' => 'myfirsttitle',
);
return $out_user;
break;
}
}
?>
* delete :当从数据库删除一个用户时,可以给个机会处理与这个用户相关的信息,一般管理员的角色触发。
* form:你编辑你的信息时,就会触发这个选项,他可以让你在编辑表单还没显示之前,进行操作表单。它和地四个参数$category关系紧密,一般编辑时候都用户的某一类信息进行编辑,因此,可以通过判断$category后,进行相关操作。
* insert:一个新的用户帐号将要被创建并保存到数据库中。在帐号插入数据库之间,可以做动作
* login:用户成功登录后,可以做操作,初始化之类的。
* login out :用户退出登录,会话被销毁之后。
* load:加载用户帐号,指的是浏览帐号信息的时候,在我的帐户里,凡是显示帐户信息了,都会出发load,按顺序load 应该在view和form前发生,修改的这个$user是第三个参数。
<?php
case 'load':
$user->name = 'mibaoxin';
return $user;
?>
* submit: 用户编辑表单已被提交。在帐号信息发送给user_save()以前可对其进行修改,user_save()你改变一个帐户或者新建一个帐户都会调用。
* update:已存在的用户帐号(修改后)将要被保存到数据库中。这个与前面的“after_update”参数的区别在于:“update”是在用户帐号$user被保存到数据库前,更新你的模块对应的数据表的信息;而“after_update”是用户帐号$user被保存到数据库中以后调用。
* validate: 用户帐号已被修改,需要等待验证,你写的模块应该验证它的定制数据并生成任何必要的错误报告信息。
* view: 正在展示用户的帐号信息。模块应该把它要添加到展示页面中的定制信息放到一个数组中并将数组返回。查看操作最后调用theme_user_profile 来生成用户个人资料页面。点击我的帐户->查看可以触发,关于$user->content他的默认原型是这样的
<?php
//content默认的是summary分类也就是历史,它的原型是这个样子的
$user->content['summary']=array(
'#type' => 'user_profile_category',//字段类型,通过hook_elements定制。
'#title' => '历史',//标题
'#attributes' => array('class' => 'user-member'),//属性
'#weight' => 5,//权重
'member_for' => array(//具体的字段信息,可以通过$op 的view动作,来添加更多字段,展示足够的信息,
'#type' => 'user_profile_item',//用户自定的数据类型。
'#title' => t('您最近的日志记录 '),
'#value' =>$user->name,
'#attributes' => array('class' => 'blog'),
),
);
?>
可以在分类里添加字段:
<?php
$user->content['summary']['infomation']=array(
'#type' => 'textfield',
'#title' => 'test',
'#value' => t('测试'),
);
?>
修改原来分类summary(历史)中的member_for字段信息
<?php
$user->content['summary']['member_for']['#title']='从您成为我们的会员起,一共经历了:';
?>
添加新的分类:
<?php
$user->content['info']=array(
'#type' => 'user_profile_category',
'#title' => '具体信息',
'mation' => array(
'#type' => 'mymymy',
'#title' => '测试一下',
'#value' => t('测试信息'),
),
);
?>
* register:用户帐号注册表单将被显示。模块可以向表单中添加额外的表单元素。drupal的默认的注册很简单的,可以通过这个钩子动作,向注册页面添加一些输入框之类,搜集更多的信息,当然这需要,在插入数据库时作处理。数据库是否有新加的字段。
<?php
//具体字段看form API
case 'register':
$fields['age'] = array(
'#type' => 'textfield',
'#title' => '输入年龄',
'#value' => '1',
);
return $fields;
?>
这样注册的时候就会多出一个需要填写的输入框,
* &$edit:这个参数是参数$op取值“form”时会返回一个数组。